diff --git a/bochs/.bochsrc b/bochs/.bochsrc index 225f7f99c2..285a77d876 100644 --- a/bochs/.bochsrc +++ b/bochs/.bochsrc @@ -73,7 +73,8 @@ # win32, x) # "fullscreen" - startup in fullscreen mode (sdl, sdl2) # "gui_debug" - use GTK debugger gui (sdl, sdl2, x) / Win32 debugger gui (sdl, -# sdl2, win32) +# sdl2, win32). When using the "globalini" extension the +# debugger uses ini file from BXSHARE path (see below). # "hideIPS" - disable IPS output in status bar (rfb, sdl, sdl2, term, vncsrv, # win32, wx, x) # "nokeyrepeat" - turn off host keyboard repeat (sdl, sdl2, win32, x) @@ -100,7 +101,7 @@ # on desktop window size #display_library: win32, options="traphotkeys, autoscale" #display_library: wx -#display_library: x +#display_library: x, options="gui_debug:globalini" #======================================================================= # CPU: @@ -414,8 +415,8 @@ romimage: file=$BXSHARE/BIOS-bochs-latest, options=fastboot # you cannot use a PCI enabled VGA ROM BIOS option such as the cirrus # option shown below. #======================================================================= -vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest -#vgaromimage: file=bios/VGABIOS-lgpl-latest-cirrus +vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest.bin +#vgaromimage: file=bios/VGABIOS-lgpl-latest-cirrus.bin #vgaromimage: file=$BXSHARE/vgabios-cirrus.bin-1.13.0 # http://www.seabios.org/SeaVGABIOS #vgaromimage: file=bios/VGABIOS-elpin-2.40 @@ -957,15 +958,15 @@ parport1: enabled=1, file="parport.out" # waveoutdrv: # This defines the driver to be used for the waveout feature. # Possible values are 'file' (all wave data sent to file), 'dummy' (no -# output) and the platform-dependant drivers 'alsa', 'oss', 'osx', 'sdl' -# and 'win'. +# output), 'pulse', 'sdl' (both cross-platform) and the platform-dependant +# drivers 'alsa', 'oss', 'osx' and 'win'. # waveout: # This defines the device to be used for wave output (if necessary) or # the output file for the 'file' driver. # waveindrv: # This defines the driver to be used for the wavein feature. -# Possible values are 'dummy' (recording silence) and platform-dependent -# drivers 'alsa', 'oss', 'sdl' and 'win'. +# Possible values are 'dummy' (recording silence), 'pulse', 'sdl' (both +# cross-platform) and platform-dependent drivers 'alsa', 'oss' and 'win'. # wavein: # This defines the device to be used for wave input (if necessary). # midioutdrv: @@ -1296,7 +1297,7 @@ speaker: enabled=1, mode=sound, volume=15 # non_exist: will break and load the debugger on a non-existant port access # (experimental and is under development) #======================================================================= -#usb_debug: type=xhci, reset, enable, start_frame, doorbell, event, non_exist +#usb_debug: type=xhci, reset=1, enable=1, start_frame=1, doorbell, event=1, non_exist=1 #======================================================================= # PCIDEV: diff --git a/bochs/.conf.linux b/bochs/.conf.linux index 7bff115c34..88749f912e 100755 --- a/bochs/.conf.linux +++ b/bochs/.conf.linux @@ -6,6 +6,11 @@ if test $# = 0; then which_config=plugins else which_config=$1 + if test $# = 2; then + if test $2 = debugger; then + CONFIGURE_ARGS=--enable-debugger + fi + fi fi CC="gcc" diff --git a/bochs/CHANGES b/bochs/CHANGES index aa730d4fa5..7a525fd804 100644 --- a/bochs/CHANGES +++ b/bochs/CHANGES @@ -2,17 +2,48 @@ Changes after 2.8: Brief summary : - Integrated softfloat3e library replacing older softfloat2a fpu-emulation code + - Implemented AVX512_FP16 Intel instruction set based on softfloat3e library (enabled in Xeon Sapphire Rapids CPU definition) + - Bugfixes for CPU emulation correctness (critical bugfixes for XSAVEC/XSAVES, CPUID and SHA1 ISA implementation) - USB: Added the USB Debugger support for xHCI and UHCI Detailed change log : - CPU + - Bugfixes for CPU emulation correctness (critical bugfixes for XSAVEC/XSAVES, CPUID and SHA1 ISA implementation) - Integrated softfloat3e library replacing older softfloat2a fpu-emulation code - Implemented AVX512_FP16 Intel instruction set based on softfloat3e library (enabled in Xeon Sapphire Rapids CPU definition) +- Configure and compile + - Fixed compilation of plugin version with debugger enabled on Windows + - Removed legacy libltdl code and force using library installed on host system + - GTK-based gui debugger can now use GTK3 if GTK2 is not installed + +- GUI and display libraries + - Debugger gui can now use ini file from BXSHARE path when using gui option + extension "gui_debug:globalini" (sdl, sdl2, win32, x11) + - Debugger gui now updates the memory dump window if necessary + - added bitmap change support for the wxWidgets toolbar + - I/O Devices + - SVGA Cirrus + - Added support for graphics controller mode extensions in VGA mode + - Added support for hardware cursor in VGA mode + - Fixes to make original VGABIOS work correctly with WinXP - USB - Now includes the USB Debugger support for the xHCI and UHCI controllers + - Sound + - Added PCM playback/recording support using PulseAudio simple API + - Networking + - Added support for using libslirp library instead of builtin slirp code + - Updated builtin slirp based on libslirp 4.8.0 (including IPv6 support) + +- BIOS + - Added panic in legacy BIOS in case no VGA BIOS ROM is found at C000:0000, + - Fixed unwanted side effects caused by some helper functions. + - LGPL'd VGABIOS updated to version 0.9b (several VBE bugfixes) + +- Misc + - bximage: added simple partition table viewer to the info function ------------------------------------------------------------------------- Changes in 2.8 (March 10, 2024): diff --git a/bochs/Makefile.in b/bochs/Makefile.in index ffc559a0b2..c1e6ecb895 100644 --- a/bochs/Makefile.in +++ b/bochs/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2001-2021 The Bochs Project +# Copyright (C) 2001-2024 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -178,7 +178,7 @@ all: @PRIMARY_TARGET@ @PLUGIN_TARGET@ bximage@EXE@ @OPTIONAL_TARGET@ @BUILD_DOCB bochs@EXE@: @IODEV_LIB_VAR@ @DISPLAY_LIB_VAR@ @HDIMAGE_LIB_VAR@ @USB_LIB_VAR@ @NETWORK_LIB_VAR@ @SOUND_LIB_VAR@ \ @DEBUGGER_VAR@ cpu/libcpu.a @AVX_LIB_VAR@ cpu/cpudb/libcpudb.a memory/libmemory.a \ gui/libgui.a @INSTRUMENT_VAR@ $(BX_OBJS) \ - $(SIMX86_OBJS) @FPU_VAR@ @GDBSTUB_VAR@ @PLUGIN_VAR@ + $(SIMX86_OBJS) @FPU_VAR@ @GDBSTUB_VAR@ @LINK@ @EXPORT_DYNAMIC@ $(BX_OBJS) $(SIMX86_OBJS) \ @IODEV_LIB_VAR@ @DISPLAY_LIB_VAR@ @HDIMAGE_LIB_VAR@ @USB_LIB_VAR@ @NETWORK_LIB_VAR@ @SOUND_LIB_VAR@ \ @DEBUGGER_VAR@ cpu/libcpu.a @AVX_LIB_VAR@ cpu/cpudb/libcpudb.a \ @@ -199,12 +199,12 @@ bochs@EXE@: @IODEV_LIB_VAR@ @DISPLAY_LIB_VAR@ @HDIMAGE_LIB_VAR@ @USB_LIB_VAR@ @N .win32_dll_plugin_target: @IODEV_LIB_VAR@ @DISPLAY_LIB_VAR@ @HDIMAGE_LIB_VAR@ @USB_LIB_VAR@ @NETWORK_LIB_VAR@ \ @SOUND_LIB_VAR@ @DEBUGGER_VAR@ cpu/libcpu.a @AVX_LIB_VAR@ cpu/cpudb/libcpudb.a \ memory/libmemory.a gui/libgui.a @INSTRUMENT_VAR@ \ - $(BX_OBJS) $(SIMX86_OBJS) @FPU_VAR@ @GDBSTUB_VAR@ @PLUGIN_VAR@ + $(BX_OBJS) $(SIMX86_OBJS) @FPU_VAR@ @GDBSTUB_VAR@ $(DLLTOOL) --export-all-symbols --output-def bochs.def \ $(BX_OBJS) $(SIMX86_OBJS) \ @IODEV_LIB_VAR@ @DISPLAY_LIB_VAR@ @HDIMAGE_LIB_VAR@ @USB_LIB_VAR@ @NETWORK_LIB_VAR@ @SOUND_LIB_VAR@ \ cpu/libcpu.a @AVX_LIB_VAR@ cpu/cpudb/libcpudb.a memory/libmemory.a gui/libgui.a \ - @DEBUGGER_VAR@ @INSTRUMENT_VAR@ @PLUGIN_VAR@ \ + @DEBUGGER_VAR@ @INSTRUMENT_VAR@ \ @GDBSTUB_VAR@ @FPU_VAR@ $(DLLTOOL) --dllname bochs.exe --def bochs.def --output-lib dllexports.a $(DLLTOOL) --dllname bochs.exe --output-exp bochs.exp --def bochs.def @@ -550,7 +550,6 @@ local-dist-clean: clean @RMCOMMAND@ build/win32/nsis/Makefile build/win32/nsis/bochs.nsi @RMCOMMAND@ build/macosx/Info.plist build/macosx/script_compiled.rsrc @RMCOMMAND@ libtool - @RMCOMMAND@ ltdlconf.h clean_pcidev:: cd host/linux/pcidev @COMMAND_SEPARATOR@ @@ -794,21 +793,21 @@ crc.o: crc.@CPP_SUFFIX@ config.h gdbstub.o: gdbstub.@CPP_SUFFIX@ bochs.h config.h osdep.h gui/paramtree.h logio.h \ instrument/stubs/instrument.h misc/bswap.h param_names.h \ cpu/cpu.h bx_debug/debug.h config.h osdep.h cpu/decoder/decoder.h \ - cpu/i387.h cpu/fpu/softfloat.h cpu/fpu/tag_w.h cpu/fpu/status_w.h \ + cpu/i387.h cpu/fpu/tag_w.h cpu/fpu/status_w.h \ cpu/fpu/control_w.h cpu/crregs.h cpu/descriptor.h cpu/decoder/instr.h \ cpu/lazy_flags.h cpu/tlb.h cpu/icache.h cpu/apic.h cpu/xmm.h cpu/vmx.h \ cpu/cpuid.h cpu/stack.h cpu/access.h logio.o: logio.@CPP_SUFFIX@ bochs.h config.h osdep.h gui/paramtree.h logio.h \ instrument/stubs/instrument.h misc/bswap.h gui/siminterface.h \ gui/paramtree.h pc_system.h bxthread.h cpu/cpu.h bx_debug/debug.h \ - config.h osdep.h cpu/decoder/decoder.h cpu/i387.h cpu/fpu/softfloat.h \ + config.h osdep.h cpu/decoder/decoder.h cpu/i387.h \ cpu/fpu/tag_w.h cpu/fpu/status_w.h cpu/fpu/control_w.h cpu/crregs.h \ cpu/descriptor.h cpu/decoder/instr.h cpu/lazy_flags.h cpu/tlb.h \ cpu/icache.h cpu/apic.h cpu/xmm.h cpu/vmx.h cpu/cpuid.h cpu/access.h main.o: main.@CPP_SUFFIX@ bochs.h config.h osdep.h gui/paramtree.h logio.h \ instrument/stubs/instrument.h misc/bswap.h bxversion.h param_names.h \ config.h cpu/cpu.h bx_debug/debug.h osdep.h \ - cpu/decoder/decoder.h cpu/i387.h cpu/fpu/softfloat.h cpu/fpu/tag_w.h \ + cpu/decoder/decoder.h cpu/i387.h cpu/fpu/tag_w.h \ cpu/fpu/status_w.h cpu/fpu/control_w.h cpu/crregs.h cpu/descriptor.h \ cpu/decoder/instr.h cpu/lazy_flags.h cpu/tlb.h cpu/icache.h cpu/apic.h \ cpu/xmm.h cpu/vmx.h cpu/cpuid.h cpu/access.h iodev/iodev.h bochs.h \ @@ -820,7 +819,7 @@ osdep.o: osdep.@CPP_SUFFIX@ bochs.h config.h osdep.h gui/paramtree.h logio.h \ pc_system.o: pc_system.@CPP_SUFFIX@ bochs.h config.h osdep.h gui/paramtree.h \ logio.h instrument/stubs/instrument.h misc/bswap.h cpu/cpu.h \ bx_debug/debug.h config.h osdep.h cpu/decoder/decoder.h cpu/i387.h \ - cpu/fpu/softfloat.h cpu/fpu/tag_w.h cpu/fpu/status_w.h \ + cpu/fpu/tag_w.h cpu/fpu/status_w.h \ cpu/fpu/control_w.h cpu/crregs.h cpu/descriptor.h cpu/decoder/instr.h \ cpu/lazy_flags.h cpu/tlb.h cpu/icache.h cpu/apic.h cpu/xmm.h cpu/vmx.h \ cpu/cpuid.h cpu/access.h iodev/iodev.h bochs.h plugin.h extplugin.h \ diff --git a/bochs/README b/bochs/README index 6853680568..59f2199214 100644 --- a/bochs/README +++ b/bochs/README @@ -8,11 +8,11 @@ Bochs is a highly portable open source IA-32 (x86) PC emulator written in C++, that runs on most popular platforms. It includes emulation of the Intel x86 CPU, common I/O devices, and a custom BIOS. Bochs can be compiled to emulate many different x86 CPUs, -from early 386 to the most recent x86-64 Intel and AMD processors -which may even not reached the market yet. Bochs is capable of running -most Operating Systems inside the emulation, for example DOS, -Linux or Windows. Bochs was written by Kevin Lawton and is currently -maintained by the Bochs project at "https://bochs.sourceforge.io". +from early 386 to the most recent (sometimes even pre-market) x86-64 +Intel and AMD processors. Bochs is capable of running most Operating +Systems inside the emulation, for example DOS, Linux or Windows. Bochs +was written by Kevin Lawton and is currently maintained by the Bochs +project at "https://bochs.sourceforge.io". Bochs can be compiled and used in a variety of modes, some which are still in development. The 'typical' use of bochs is to provide diff --git a/bochs/aclocal.m4 b/bochs/aclocal.m4 index b7b4b04199..fe301444ab 100644 --- a/bochs/aclocal.m4 +++ b/bochs/aclocal.m4 @@ -24,9 +24,9 @@ define(WX_SYS_LARGEFILE_MACRO_VALUE, [ AC_CACHE_CHECK([for $1 value needed for large files], [$3], [ - AC_TRY_COMPILE([#define $1 $2 - #include ], - WX_SYS_LARGEFILE_TEST, + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#define $1 $2 + #include ]], + [WX_SYS_LARGEFILE_TEST])], [$3=$2], [$3=no]) ] @@ -305,12 +305,12 @@ AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], enable_win32_dll=yes, enable_win32_dll=no) AC_ARG_ENABLE([libtool-lock], - [AC_HELP_STRING([--disable-libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes AC_ARG_WITH([pic], - [AC_HELP_STRING([--with-pic], + [AS_HELP_STRING([--with-pic], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [pic_mode="$withval"], [pic_mode=default]) @@ -526,7 +526,7 @@ AC_SUBST(ECHO) # ----------- AC_DEFUN([_LT_AC_LOCK], [AC_ARG_ENABLE([libtool-lock], - [AC_HELP_STRING([--disable-libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes @@ -629,7 +629,7 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) - AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LINK_IFELSE([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf @@ -1705,7 +1705,7 @@ test "$dynamic_linker" = no && can_build_shared=no # ---------------- AC_DEFUN([_LT_AC_TAGCONFIG], [AC_ARG_WITH([tags], - [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [AS_HELP_STRING([--with-tags@<:@=TAGS@:>@], [include additional configurations @<:@automatic@:>@])], [tagnames="$withval"]) @@ -1739,7 +1739,7 @@ if test -f "$ltmain" && test -n "$tagnames"; then if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null then - AC_MSG_ERROR([tag name \"$tagname\" already exists]) + AC_MSG_ERROR([tag name "$tagname" already exists]) fi # Update the list of available tags. @@ -1823,7 +1823,7 @@ AC_DEFUN([AC_LIBTOOL_WIN32_DLL], AC_DEFUN([AC_ENABLE_SHARED], [define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([shared], - [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in @@ -1862,7 +1862,7 @@ AC_ENABLE_SHARED(no) AC_DEFUN([AC_ENABLE_STATIC], [define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([static], - [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in @@ -1901,7 +1901,7 @@ AC_ENABLE_STATIC(no) AC_DEFUN([AC_ENABLE_FAST_INSTALL], [define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([fast-install], - [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in @@ -2041,7 +2041,7 @@ fi # find the pathname to the GNU or non-GNU linker AC_DEFUN([AC_PROG_LD], [AC_ARG_WITH([gnu-ld], - [AC_HELP_STRING([--with-gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no]) @@ -6112,7 +6112,6 @@ AC_DEFUN([AC_LIB_LTDL], [AC_PREREQ(2.50) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_C_CONST]) -AC_REQUIRE([AC_HEADER_STDC]) AC_REQUIRE([AC_HEADER_DIRENT]) AC_REQUIRE([_LT_AC_CHECK_DLFCN]) AC_REQUIRE([AC_LTDL_ENABLE_INSTALL]) @@ -6144,7 +6143,7 @@ AC_CHECK_FUNCS([closedir opendir readdir]) # ---------------------- AC_DEFUN([AC_LTDL_ENABLE_INSTALL], [AC_ARG_ENABLE([ltdl-install], - [AC_HELP_STRING([--enable-ltdl-install], [install libltdl])]) + [AS_HELP_STRING([--enable-ltdl-install], [install libltdl])]) if test x"${enable_ltdl_install-no}" != xno; then AC_DEFINE(INSTALL_LTDL) @@ -6356,11 +6355,11 @@ AC_CHECK_FUNC([shl_load], [AC_DEFINE([HAVE_LIBDL], [1], [Define if you have the libdl library or equivalent.]) LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"], - [AC_TRY_LINK([#if HAVE_DLFCN_H + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#if HAVE_DLFCN_H # include #endif - ], - [dlopen(0, 0);], + ]], + [[dlopen(0, 0);]])], [AC_DEFINE([HAVE_LIBDL], [1], [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"], [AC_CHECK_LIB([svld], [dlopen], @@ -6415,15 +6414,15 @@ EOF if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then : else - echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC + echo "configure: cannot find nm_test_func in $ac_nlist" >&AS_MESSAGE_LOG_FD fi fi else - echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else - echo "configure: failed program was:" >&AC_FD_CC - cat conftest.c >&AC_FD_CC + echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.c >&AS_MESSAGE_LOG_FD fi rm -rf conftest* ]) diff --git a/bochs/bios/BIOS-bochs-latest b/bochs/bios/BIOS-bochs-latest index 81f2d4906e..cf7a25151a 100644 Binary files a/bochs/bios/BIOS-bochs-latest and b/bochs/bios/BIOS-bochs-latest differ diff --git a/bochs/bios/BIOS-bochs-legacy b/bochs/bios/BIOS-bochs-legacy index be3336b173..aad89e074e 100644 Binary files a/bochs/bios/BIOS-bochs-legacy and b/bochs/bios/BIOS-bochs-legacy differ diff --git a/bochs/bios/VGABIOS-lgpl-README b/bochs/bios/VGABIOS-lgpl-README index 36210194e2..4180ce696d 100644 --- a/bochs/bios/VGABIOS-lgpl-README +++ b/bochs/bios/VGABIOS-lgpl-README @@ -36,8 +36,8 @@ To compile the VGA Bios you will need the following packages: Untar the archive, and type 'make'. You should get this set of binary files: "VGABIOS-lgpl-latest.bin", "VGABIOS-lgpl-latest-debug.bin", -"VGABIOS-lgpl-latest-cirrus.bin", "VGABIOS-lgpl-latest-cirrus-debug.bin" and -"VGABIOS-lgpl-latest-banshee.bin". +"VGABIOS-lgpl-latest-cirrus.bin", "VGABIOS-lgpl-latest-cirrus-debug.bin", +"VGABIOS-lgpl-latest-banshee.bin" and "VGABIOS-lgpl-latest-banshee-debug.bin". Alternatively, you can use one of the precompiled binary files present in the archive. @@ -107,6 +107,15 @@ For any information on Qemu, visit the website http://wiki.qemu.org/ History ------- +vgabios-0.9b : Jun 09 2024 + - Volker + - Fixed VBE protected mode bank switching (all extensions) + - Fixed VBE protected mode page flipping (Bochs VBE / Banshee) + - Get rid of the Win2k clear VRAM hack after fixing emulation + - Bochs VBE function 07h now also supports wait for VSYNC + - Added 'Banshee debug' binary that fits in 32k + - Return VBE mode info only if mode is supported by hardware + vgabios-0.9a : Mar 03 2024 - Volker - Implemented AH=12h / BL=36h (video refresh control) diff --git a/bochs/bios/VGABIOS-lgpl-latest b/bochs/bios/VGABIOS-lgpl-latest deleted file mode 100644 index 387d47348a..0000000000 Binary files a/bochs/bios/VGABIOS-lgpl-latest and /dev/null differ diff --git a/bochs/bios/VGABIOS-lgpl-latest-banshee-debug.bin b/bochs/bios/VGABIOS-lgpl-latest-banshee-debug.bin new file mode 100644 index 0000000000..6a44a72dbe Binary files /dev/null and b/bochs/bios/VGABIOS-lgpl-latest-banshee-debug.bin differ diff --git a/bochs/bios/VGABIOS-lgpl-latest-banshee b/bochs/bios/VGABIOS-lgpl-latest-banshee.bin similarity index 55% rename from bochs/bios/VGABIOS-lgpl-latest-banshee rename to bochs/bios/VGABIOS-lgpl-latest-banshee.bin index 198498a8b7..99b746050a 100644 Binary files a/bochs/bios/VGABIOS-lgpl-latest-banshee and b/bochs/bios/VGABIOS-lgpl-latest-banshee.bin differ diff --git a/bochs/bios/VGABIOS-lgpl-latest-cirrus-debug b/bochs/bios/VGABIOS-lgpl-latest-cirrus-debug.bin similarity index 54% rename from bochs/bios/VGABIOS-lgpl-latest-cirrus-debug rename to bochs/bios/VGABIOS-lgpl-latest-cirrus-debug.bin index 223d17604b..612aed4b6f 100644 Binary files a/bochs/bios/VGABIOS-lgpl-latest-cirrus-debug and b/bochs/bios/VGABIOS-lgpl-latest-cirrus-debug.bin differ diff --git a/bochs/bios/VGABIOS-lgpl-latest-cirrus b/bochs/bios/VGABIOS-lgpl-latest-cirrus.bin similarity index 56% rename from bochs/bios/VGABIOS-lgpl-latest-cirrus rename to bochs/bios/VGABIOS-lgpl-latest-cirrus.bin index 71b9fe5a29..28dbc5dc85 100644 Binary files a/bochs/bios/VGABIOS-lgpl-latest-cirrus and b/bochs/bios/VGABIOS-lgpl-latest-cirrus.bin differ diff --git a/bochs/bios/VGABIOS-lgpl-latest-debug b/bochs/bios/VGABIOS-lgpl-latest-debug deleted file mode 100644 index 2eb6c47f40..0000000000 Binary files a/bochs/bios/VGABIOS-lgpl-latest-debug and /dev/null differ diff --git a/bochs/bios/VGABIOS-lgpl-latest-debug.bin b/bochs/bios/VGABIOS-lgpl-latest-debug.bin new file mode 100644 index 0000000000..125b73488e Binary files /dev/null and b/bochs/bios/VGABIOS-lgpl-latest-debug.bin differ diff --git a/bochs/bios/VGABIOS-lgpl-latest.bin b/bochs/bios/VGABIOS-lgpl-latest.bin new file mode 100644 index 0000000000..e381dfc1b8 Binary files /dev/null and b/bochs/bios/VGABIOS-lgpl-latest.bin differ diff --git a/bochs/bios/rombios.c b/bochs/bios/rombios.c index 6ed4bd85a0..c9369bd236 100644 --- a/bochs/bios/rombios.c +++ b/bochs/bios/rombios.c @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2023 The Bochs Project +// Copyright (C) 2001-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -455,12 +455,15 @@ typedef unsigned long Bit32u; ;; cmp function lcmpl: lcmpul: - and eax, #0x0000FFFF - shl ebx, #16 - or eax, ebx - shr ebx, #16 + push eax + push ebx + and eax, #0x0000FFFF + shl ebx, #16 + or eax, ebx SEG SS cmp eax, dword ptr [di] + pop ebx + pop eax ret ;; sub function @@ -519,33 +522,29 @@ typedef unsigned long Bit32u; ;; sr function lsrul: - mov cx,di + push ecx + mov cx, di jcxz lsr_exit - and eax, #0x0000FFFF - shl ebx, #16 - or eax, ebx lsr_loop: - shr eax, #1 + shr bx, #1 + rcr ax, #1 loop lsr_loop - mov ebx, eax - shr ebx, #16 lsr_exit: + pop ecx ret ;; sl function lsll: lslul: - mov cx,di + push ecx + mov cx, di jcxz lsl_exit - and eax, #0x0000FFFF - shl ebx, #16 - or eax, ebx lsl_loop: - shl eax, #1 + shl ax, #1 + rcl bx, #1 loop lsl_loop - mov ebx, eax - shr ebx, #16 lsl_exit: + pop ecx ret idiv_: @@ -10752,6 +10751,10 @@ use16 386 pop ebp retf +vga_rom_error_msg: + .ascii "No VGABIOS ROM at C000:0000h! Legacy BIOS does not support PCI ROM!\n" + db 0x00 + rom_scan: ;; Scan for existence of valid expansion ROMS. ;; Video ROM: from 0xC0000..0xC7FFF in 2k increments @@ -11208,6 +11211,19 @@ use16 386 #if BX_PCIBIOS call pcibios_init_iomem_bases call pcibios_init_irqs + ;; Hack fix: Legacy BIOS cannot initialize PCI VGA ROM + push ds + mov ax, #0xc000 + mov ds, ax + xor bx, bx + cmp [bx], #0xaa55 + je vga_rom_ok + push #vga_rom_error_msg + push #BIOS_PRINTF_DEBHALT + call _bios_printf + add sp, #4 +vga_rom_ok: + pop ds #endif //BX_PCIBIOS #endif diff --git a/bochs/bios/rombios.h b/bochs/bios/rombios.h index ad346c5b38..93f04e6619 100644 --- a/bochs/bios/rombios.h +++ b/bochs/bios/rombios.h @@ -74,6 +74,9 @@ #define SMB_IO_BASE 0xb100 #define SMP_MSR_ADDR 0x0510 +#define PIIX_GPE0_BLK 0xafe0 +#define PIIX_GPE0_BLK_LEN 4 + // Define the application NAME #if defined(BX_QEMU) # define BX_APPNAME "QEMU" diff --git a/bochs/bios/rombios32.c b/bochs/bios/rombios32.c index ea319978e3..75e23fb1ab 100644 --- a/bochs/bios/rombios32.c +++ b/bochs/bios/rombios32.c @@ -1742,9 +1742,11 @@ void acpi_bios_init(void) fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base); fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04); fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08); + fadt->gpe0_blk = cpu_to_le32(PIIX_GPE0_BLK); fadt->pm1_evt_len = 4; fadt->pm1_cnt_len = 2; fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = PIIX_GPE0_BLK_LEN; fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */ diff --git a/bochs/build/redhat/bochs.rpmspec.template b/bochs/build/redhat/bochs.rpmspec.template index e743b669f6..ae2fdbdf5e 100644 --- a/bochs/build/redhat/bochs.rpmspec.template +++ b/bochs/build/redhat/bochs.rpmspec.template @@ -20,6 +20,8 @@ including Linux, DOS, Windows 9X/NT/2000/XP or Windows 7. %define pkg_name bochs +%define _build_id_links none + %prep rm -rf $RPM_BUILD_DIR/bochs-@SEDVERSION@ tar xzvf $RPM_SOURCE_DIR/bochs-@SEDVERSION@.tar.gz diff --git a/bochs/build/win32/nsis/Makefile.in b/bochs/build/win32/nsis/Makefile.in index fde216920c..bffed34e50 100644 --- a/bochs/build/win32/nsis/Makefile.in +++ b/bochs/build/win32/nsis/Makefile.in @@ -11,8 +11,10 @@ MAKENSIS='/c/Program Files (x86)/NSIS/makensis' VERSION=@VERSION@ -TARGET=Bochs-${VERSION}.exe -DLXDIR=bochs-${VERSION}/dlxlinux +BITS=@BOCHS_BITS@ +SOURCE=bochs-${VERSION} +TARGET=Bochs-win$(BITS)-${VERSION}.exe +DLXDIR=${SOURCE}/dlxlinux all: ${TARGET} @@ -27,4 +29,6 @@ ${TARGET}: fixups bochs.nsi ls -l ${TARGET} clean:: + rm -rf ${SOURCE} + rm -f ${SOURCE}.zip rm -rf ${TARGET} diff --git a/bochs/build/win32/nsis/bochs.nsi.in b/bochs/build/win32/nsis/bochs.nsi.in index 964fbbbe79..11d61bccaf 100644 --- a/bochs/build/win32/nsis/bochs.nsi.in +++ b/bochs/build/win32/nsis/bochs.nsi.in @@ -8,7 +8,7 @@ ; ; Based on Example Script by Joost Verburg ; also original BOCHS script by Robert (segra) -; updated for NSIS 3.04 by Volker Ruppert +; updated for NSIS 3.09 by Volker Ruppert ; version check and reinstall page based on NSIS example ; ;--------------------- @@ -61,6 +61,8 @@ Var IndependentSectionState Name "${NAME}" OutFile Bochs-win${BITS}-${VERSION}.exe SetOverwrite on + Unicode True + XPStyle On ; Installation Types InstType "Normal" @@ -270,6 +272,7 @@ Section -post SetRegView ${BITS} ; Register Uninstaller WriteRegStr HKLM "Software\Bochs" "" $INSTDIR + WriteRegStr HKLM "Software\Bochs" "BX_SHARE_PATH" $INSTDIR WriteRegDword HKLM "Software\Bochs" "VersionMajor" "${VER_MAJOR}" WriteRegDword HKLM "Software\Bochs" "VersionMinor" "${VER_MINOR}" WriteRegDword HKLM "Software\Bochs" "VersionRevision" "${VER_REVISION}" diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/avx.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/avx.vcxproj index 5f97c01c90..674960f475 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/avx.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/avx.vcxproj @@ -70,19 +70,19 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\avx\ + .\..\obj-debug\ .\..\obj-debug\avx\ - .\..\obj-debug\avx\ + .\..\obj-debug\ .\..\obj-debug\avx\ - .\..\obj-release\avx\ + .\..\obj-release\ .\..\obj-release\avx\ - .\..\obj-release\avx\ + .\..\obj-release\ .\..\obj-release\avx\ @@ -92,7 +92,7 @@ Disabled ..\;..\cpu;..\instrument\stubs\;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions) MultiThreadedDebugDLL .\..\obj-debug\avx\avx.pch .\..\obj-debug\avx\ @@ -122,7 +122,7 @@ Disabled ..\;..\cpu;..\instrument\stubs\;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions) MultiThreadedDebugDLL .\..\obj-debug\avx\avx.pch .\..\obj-debug\avx\ @@ -223,7 +223,7 @@ - + diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bochs-plugins.sln b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bochs-plugins.sln index b80ccaf0c9..25cba198c0 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bochs-plugins.sln +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bochs-plugins.sln @@ -8,6 +8,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bochs", "bochs.vcxproj", "{ {B916642D-36CA-4D94-AC7D-B0FC21F14D85} = {B916642D-36CA-4D94-AC7D-B0FC21F14D85} {5F8FC352-0076-4558-9153-CA93F50E63F4} = {5F8FC352-0076-4558-9153-CA93F50E63F4} {9EFB2055-35E8-42E9-A274-F4987CB2A655} = {9EFB2055-35E8-42E9-A274-F4987CB2A655} + {BDA1EB83-D53E-41A7-825F-0EFDC3D643E3} = {BDA1EB83-D53E-41A7-825F-0EFDC3D643E3} {9D398791-61A2-4F3F-801D-8B892D571CBE} = {9D398791-61A2-4F3F-801D-8B892D571CBE} {7A5099B9-F3BF-4AF8-9770-82DA635407B2} = {7A5099B9-F3BF-4AF8-9770-82DA635407B2} EndProjectSection @@ -154,300 +155,600 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bx_textconfig", "bx_textcon EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bx_win32config", "bx_win32config.vcxproj", "{E66DB777-8EE1-43FE-892C-039F22944B65}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "softfloat3e", "softfloat3e.vcxproj", "{BDA1EB83-D53E-41A7-825F-0EFDC3D643E3}" +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 {A09427D6-1B00-4416-9B29-20E659ED2606}.Debug|Win32.ActiveCfg = Debug|Win32 {A09427D6-1B00-4416-9B29-20E659ED2606}.Debug|Win32.Build.0 = Debug|Win32 + {A09427D6-1B00-4416-9B29-20E659ED2606}.Debug|x64.ActiveCfg = Debug|x64 + {A09427D6-1B00-4416-9B29-20E659ED2606}.Debug|x64.Build.0 = Debug|x64 {A09427D6-1B00-4416-9B29-20E659ED2606}.Release|Win32.ActiveCfg = Release|Win32 {A09427D6-1B00-4416-9B29-20E659ED2606}.Release|Win32.Build.0 = Release|Win32 + {A09427D6-1B00-4416-9B29-20E659ED2606}.Release|x64.ActiveCfg = Release|x64 + {A09427D6-1B00-4416-9B29-20E659ED2606}.Release|x64.Build.0 = Release|x64 {88F11CBB-D14A-4981-A91A-BFE987C756E8}.Debug|Win32.ActiveCfg = Debug|Win32 {88F11CBB-D14A-4981-A91A-BFE987C756E8}.Debug|Win32.Build.0 = Debug|Win32 + {88F11CBB-D14A-4981-A91A-BFE987C756E8}.Debug|x64.ActiveCfg = Debug|x64 + {88F11CBB-D14A-4981-A91A-BFE987C756E8}.Debug|x64.Build.0 = Debug|x64 {88F11CBB-D14A-4981-A91A-BFE987C756E8}.Release|Win32.ActiveCfg = Release|Win32 {88F11CBB-D14A-4981-A91A-BFE987C756E8}.Release|Win32.Build.0 = Release|Win32 + {88F11CBB-D14A-4981-A91A-BFE987C756E8}.Release|x64.ActiveCfg = Release|x64 + {88F11CBB-D14A-4981-A91A-BFE987C756E8}.Release|x64.Build.0 = Release|x64 {1009364E-AC0A-4407-B18F-27BB6ED82E4C}.Debug|Win32.ActiveCfg = Debug|Win32 {1009364E-AC0A-4407-B18F-27BB6ED82E4C}.Debug|Win32.Build.0 = Debug|Win32 + {1009364E-AC0A-4407-B18F-27BB6ED82E4C}.Debug|x64.ActiveCfg = Debug|x64 + {1009364E-AC0A-4407-B18F-27BB6ED82E4C}.Debug|x64.Build.0 = Debug|x64 {1009364E-AC0A-4407-B18F-27BB6ED82E4C}.Release|Win32.ActiveCfg = Release|Win32 {1009364E-AC0A-4407-B18F-27BB6ED82E4C}.Release|Win32.Build.0 = Release|Win32 + {1009364E-AC0A-4407-B18F-27BB6ED82E4C}.Release|x64.ActiveCfg = Release|x64 + {1009364E-AC0A-4407-B18F-27BB6ED82E4C}.Release|x64.Build.0 = Release|x64 {17E9DDBE-FC7E-4EE0-9F21-9FA0415F9ED8}.Debug|Win32.ActiveCfg = Debug|Win32 {17E9DDBE-FC7E-4EE0-9F21-9FA0415F9ED8}.Debug|Win32.Build.0 = Debug|Win32 + {17E9DDBE-FC7E-4EE0-9F21-9FA0415F9ED8}.Debug|x64.ActiveCfg = Debug|x64 + {17E9DDBE-FC7E-4EE0-9F21-9FA0415F9ED8}.Debug|x64.Build.0 = Debug|x64 {17E9DDBE-FC7E-4EE0-9F21-9FA0415F9ED8}.Release|Win32.ActiveCfg = Release|Win32 {17E9DDBE-FC7E-4EE0-9F21-9FA0415F9ED8}.Release|Win32.Build.0 = Release|Win32 + {17E9DDBE-FC7E-4EE0-9F21-9FA0415F9ED8}.Release|x64.ActiveCfg = Release|x64 + {17E9DDBE-FC7E-4EE0-9F21-9FA0415F9ED8}.Release|x64.Build.0 = Release|x64 {5661CD4E-BA54-4E67-A586-BB014AC94614}.Debug|Win32.ActiveCfg = Debug|Win32 {5661CD4E-BA54-4E67-A586-BB014AC94614}.Debug|Win32.Build.0 = Debug|Win32 + {5661CD4E-BA54-4E67-A586-BB014AC94614}.Debug|x64.ActiveCfg = Debug|x64 + {5661CD4E-BA54-4E67-A586-BB014AC94614}.Debug|x64.Build.0 = Debug|x64 {5661CD4E-BA54-4E67-A586-BB014AC94614}.Release|Win32.ActiveCfg = Release|Win32 {5661CD4E-BA54-4E67-A586-BB014AC94614}.Release|Win32.Build.0 = Release|Win32 + {5661CD4E-BA54-4E67-A586-BB014AC94614}.Release|x64.ActiveCfg = Release|x64 + {5661CD4E-BA54-4E67-A586-BB014AC94614}.Release|x64.Build.0 = Release|x64 {1F5E4760-8D1E-47A7-9730-E29DCBB6701F}.Debug|Win32.ActiveCfg = Debug|Win32 {1F5E4760-8D1E-47A7-9730-E29DCBB6701F}.Debug|Win32.Build.0 = Debug|Win32 + {1F5E4760-8D1E-47A7-9730-E29DCBB6701F}.Debug|x64.ActiveCfg = Debug|x64 + {1F5E4760-8D1E-47A7-9730-E29DCBB6701F}.Debug|x64.Build.0 = Debug|x64 {1F5E4760-8D1E-47A7-9730-E29DCBB6701F}.Release|Win32.ActiveCfg = Release|Win32 {1F5E4760-8D1E-47A7-9730-E29DCBB6701F}.Release|Win32.Build.0 = Release|Win32 + {1F5E4760-8D1E-47A7-9730-E29DCBB6701F}.Release|x64.ActiveCfg = Release|x64 + {1F5E4760-8D1E-47A7-9730-E29DCBB6701F}.Release|x64.Build.0 = Release|x64 {25A3CFB3-8943-4D9C-84BE-DA3E3C8A4115}.Debug|Win32.ActiveCfg = Debug|Win32 {25A3CFB3-8943-4D9C-84BE-DA3E3C8A4115}.Debug|Win32.Build.0 = Debug|Win32 + {25A3CFB3-8943-4D9C-84BE-DA3E3C8A4115}.Debug|x64.ActiveCfg = Debug|x64 + {25A3CFB3-8943-4D9C-84BE-DA3E3C8A4115}.Debug|x64.Build.0 = Debug|x64 {25A3CFB3-8943-4D9C-84BE-DA3E3C8A4115}.Release|Win32.ActiveCfg = Release|Win32 {25A3CFB3-8943-4D9C-84BE-DA3E3C8A4115}.Release|Win32.Build.0 = Release|Win32 + {25A3CFB3-8943-4D9C-84BE-DA3E3C8A4115}.Release|x64.ActiveCfg = Release|x64 + {25A3CFB3-8943-4D9C-84BE-DA3E3C8A4115}.Release|x64.Build.0 = Release|x64 {BBFF892D-2F57-4561-B2D0-ED4C3A9B7051}.Debug|Win32.ActiveCfg = Debug|Win32 {BBFF892D-2F57-4561-B2D0-ED4C3A9B7051}.Debug|Win32.Build.0 = Debug|Win32 + {BBFF892D-2F57-4561-B2D0-ED4C3A9B7051}.Debug|x64.ActiveCfg = Debug|x64 + {BBFF892D-2F57-4561-B2D0-ED4C3A9B7051}.Debug|x64.Build.0 = Debug|x64 {BBFF892D-2F57-4561-B2D0-ED4C3A9B7051}.Release|Win32.ActiveCfg = Release|Win32 {BBFF892D-2F57-4561-B2D0-ED4C3A9B7051}.Release|Win32.Build.0 = Release|Win32 + {BBFF892D-2F57-4561-B2D0-ED4C3A9B7051}.Release|x64.ActiveCfg = Release|x64 + {BBFF892D-2F57-4561-B2D0-ED4C3A9B7051}.Release|x64.Build.0 = Release|x64 {CB7FED3F-0053-4ED9-8155-70D06457C620}.Debug|Win32.ActiveCfg = Debug|Win32 {CB7FED3F-0053-4ED9-8155-70D06457C620}.Debug|Win32.Build.0 = Debug|Win32 + {CB7FED3F-0053-4ED9-8155-70D06457C620}.Debug|x64.ActiveCfg = Debug|x64 + {CB7FED3F-0053-4ED9-8155-70D06457C620}.Debug|x64.Build.0 = Debug|x64 {CB7FED3F-0053-4ED9-8155-70D06457C620}.Release|Win32.ActiveCfg = Release|Win32 {CB7FED3F-0053-4ED9-8155-70D06457C620}.Release|Win32.Build.0 = Release|Win32 + {CB7FED3F-0053-4ED9-8155-70D06457C620}.Release|x64.ActiveCfg = Release|x64 + {CB7FED3F-0053-4ED9-8155-70D06457C620}.Release|x64.Build.0 = Release|x64 {B107C955-4324-4990-BB79-6CBC91C6D12A}.Debug|Win32.ActiveCfg = Debug|Win32 {B107C955-4324-4990-BB79-6CBC91C6D12A}.Debug|Win32.Build.0 = Debug|Win32 + {B107C955-4324-4990-BB79-6CBC91C6D12A}.Debug|x64.ActiveCfg = Debug|x64 + {B107C955-4324-4990-BB79-6CBC91C6D12A}.Debug|x64.Build.0 = Debug|x64 {B107C955-4324-4990-BB79-6CBC91C6D12A}.Release|Win32.ActiveCfg = Release|Win32 {B107C955-4324-4990-BB79-6CBC91C6D12A}.Release|Win32.Build.0 = Release|Win32 + {B107C955-4324-4990-BB79-6CBC91C6D12A}.Release|x64.ActiveCfg = Release|x64 + {B107C955-4324-4990-BB79-6CBC91C6D12A}.Release|x64.Build.0 = Release|x64 {E17D0C6E-2A3C-4B72-A311-C23CF403EE16}.Debug|Win32.ActiveCfg = Debug|Win32 {E17D0C6E-2A3C-4B72-A311-C23CF403EE16}.Debug|Win32.Build.0 = Debug|Win32 + {E17D0C6E-2A3C-4B72-A311-C23CF403EE16}.Debug|x64.ActiveCfg = Debug|x64 + {E17D0C6E-2A3C-4B72-A311-C23CF403EE16}.Debug|x64.Build.0 = Debug|x64 {E17D0C6E-2A3C-4B72-A311-C23CF403EE16}.Release|Win32.ActiveCfg = Release|Win32 {E17D0C6E-2A3C-4B72-A311-C23CF403EE16}.Release|Win32.Build.0 = Release|Win32 + {E17D0C6E-2A3C-4B72-A311-C23CF403EE16}.Release|x64.ActiveCfg = Release|x64 + {E17D0C6E-2A3C-4B72-A311-C23CF403EE16}.Release|x64.Build.0 = Release|x64 {2BAD9B44-E126-4B57-A9C1-52594546B90A}.Debug|Win32.ActiveCfg = Debug|Win32 {2BAD9B44-E126-4B57-A9C1-52594546B90A}.Debug|Win32.Build.0 = Debug|Win32 + {2BAD9B44-E126-4B57-A9C1-52594546B90A}.Debug|x64.ActiveCfg = Debug|x64 + {2BAD9B44-E126-4B57-A9C1-52594546B90A}.Debug|x64.Build.0 = Debug|x64 {2BAD9B44-E126-4B57-A9C1-52594546B90A}.Release|Win32.ActiveCfg = Release|Win32 {2BAD9B44-E126-4B57-A9C1-52594546B90A}.Release|Win32.Build.0 = Release|Win32 + {2BAD9B44-E126-4B57-A9C1-52594546B90A}.Release|x64.ActiveCfg = Release|x64 + {2BAD9B44-E126-4B57-A9C1-52594546B90A}.Release|x64.Build.0 = Release|x64 {1212DA45-79C7-4ECF-B904-AEB864AD981F}.Debug|Win32.ActiveCfg = Debug|Win32 {1212DA45-79C7-4ECF-B904-AEB864AD981F}.Debug|Win32.Build.0 = Debug|Win32 + {1212DA45-79C7-4ECF-B904-AEB864AD981F}.Debug|x64.ActiveCfg = Debug|x64 + {1212DA45-79C7-4ECF-B904-AEB864AD981F}.Debug|x64.Build.0 = Debug|x64 {1212DA45-79C7-4ECF-B904-AEB864AD981F}.Release|Win32.ActiveCfg = Release|Win32 {1212DA45-79C7-4ECF-B904-AEB864AD981F}.Release|Win32.Build.0 = Release|Win32 + {1212DA45-79C7-4ECF-B904-AEB864AD981F}.Release|x64.ActiveCfg = Release|x64 + {1212DA45-79C7-4ECF-B904-AEB864AD981F}.Release|x64.Build.0 = Release|x64 {2348A7EA-3D1B-427D-9514-AB5DB44F2ECA}.Debug|Win32.ActiveCfg = Debug|Win32 {2348A7EA-3D1B-427D-9514-AB5DB44F2ECA}.Debug|Win32.Build.0 = Debug|Win32 + {2348A7EA-3D1B-427D-9514-AB5DB44F2ECA}.Debug|x64.ActiveCfg = Debug|x64 + {2348A7EA-3D1B-427D-9514-AB5DB44F2ECA}.Debug|x64.Build.0 = Debug|x64 {2348A7EA-3D1B-427D-9514-AB5DB44F2ECA}.Release|Win32.ActiveCfg = Release|Win32 {2348A7EA-3D1B-427D-9514-AB5DB44F2ECA}.Release|Win32.Build.0 = Release|Win32 + {2348A7EA-3D1B-427D-9514-AB5DB44F2ECA}.Release|x64.ActiveCfg = Release|x64 + {2348A7EA-3D1B-427D-9514-AB5DB44F2ECA}.Release|x64.Build.0 = Release|x64 {94DE6FFB-C51E-4293-9E82-4E98B8ACBCE0}.Debug|Win32.ActiveCfg = Debug|Win32 {94DE6FFB-C51E-4293-9E82-4E98B8ACBCE0}.Debug|Win32.Build.0 = Debug|Win32 + {94DE6FFB-C51E-4293-9E82-4E98B8ACBCE0}.Debug|x64.ActiveCfg = Debug|x64 + {94DE6FFB-C51E-4293-9E82-4E98B8ACBCE0}.Debug|x64.Build.0 = Debug|x64 {94DE6FFB-C51E-4293-9E82-4E98B8ACBCE0}.Release|Win32.ActiveCfg = Release|Win32 {94DE6FFB-C51E-4293-9E82-4E98B8ACBCE0}.Release|Win32.Build.0 = Release|Win32 + {94DE6FFB-C51E-4293-9E82-4E98B8ACBCE0}.Release|x64.ActiveCfg = Release|x64 + {94DE6FFB-C51E-4293-9E82-4E98B8ACBCE0}.Release|x64.Build.0 = Release|x64 {F64F07D3-1DFE-4F9E-96B2-8E7EF520AC84}.Debug|Win32.ActiveCfg = Debug|Win32 {F64F07D3-1DFE-4F9E-96B2-8E7EF520AC84}.Debug|Win32.Build.0 = Debug|Win32 + {F64F07D3-1DFE-4F9E-96B2-8E7EF520AC84}.Debug|x64.ActiveCfg = Debug|x64 + {F64F07D3-1DFE-4F9E-96B2-8E7EF520AC84}.Debug|x64.Build.0 = Debug|x64 {F64F07D3-1DFE-4F9E-96B2-8E7EF520AC84}.Release|Win32.ActiveCfg = Release|Win32 {F64F07D3-1DFE-4F9E-96B2-8E7EF520AC84}.Release|Win32.Build.0 = Release|Win32 + {F64F07D3-1DFE-4F9E-96B2-8E7EF520AC84}.Release|x64.ActiveCfg = Release|x64 + {F64F07D3-1DFE-4F9E-96B2-8E7EF520AC84}.Release|x64.Build.0 = Release|x64 {B04F2C2F-E3DE-4ADC-956F-1D05BE3C8EBB}.Debug|Win32.ActiveCfg = Debug|Win32 {B04F2C2F-E3DE-4ADC-956F-1D05BE3C8EBB}.Debug|Win32.Build.0 = Debug|Win32 + {B04F2C2F-E3DE-4ADC-956F-1D05BE3C8EBB}.Debug|x64.ActiveCfg = Debug|x64 + {B04F2C2F-E3DE-4ADC-956F-1D05BE3C8EBB}.Debug|x64.Build.0 = Debug|x64 {B04F2C2F-E3DE-4ADC-956F-1D05BE3C8EBB}.Release|Win32.ActiveCfg = Release|Win32 {B04F2C2F-E3DE-4ADC-956F-1D05BE3C8EBB}.Release|Win32.Build.0 = Release|Win32 + {B04F2C2F-E3DE-4ADC-956F-1D05BE3C8EBB}.Release|x64.ActiveCfg = Release|x64 + {B04F2C2F-E3DE-4ADC-956F-1D05BE3C8EBB}.Release|x64.Build.0 = Release|x64 {2051E209-3D9D-4CF2-9C52-84050C776C4C}.Debug|Win32.ActiveCfg = Debug|Win32 {2051E209-3D9D-4CF2-9C52-84050C776C4C}.Debug|Win32.Build.0 = Debug|Win32 + {2051E209-3D9D-4CF2-9C52-84050C776C4C}.Debug|x64.ActiveCfg = Debug|x64 + {2051E209-3D9D-4CF2-9C52-84050C776C4C}.Debug|x64.Build.0 = Debug|x64 {2051E209-3D9D-4CF2-9C52-84050C776C4C}.Release|Win32.ActiveCfg = Release|Win32 {2051E209-3D9D-4CF2-9C52-84050C776C4C}.Release|Win32.Build.0 = Release|Win32 + {2051E209-3D9D-4CF2-9C52-84050C776C4C}.Release|x64.ActiveCfg = Release|x64 + {2051E209-3D9D-4CF2-9C52-84050C776C4C}.Release|x64.Build.0 = Release|x64 {F4B4ABD9-0606-427F-A694-7C7B72324420}.Debug|Win32.ActiveCfg = Debug|Win32 {F4B4ABD9-0606-427F-A694-7C7B72324420}.Debug|Win32.Build.0 = Debug|Win32 + {F4B4ABD9-0606-427F-A694-7C7B72324420}.Debug|x64.ActiveCfg = Debug|x64 + {F4B4ABD9-0606-427F-A694-7C7B72324420}.Debug|x64.Build.0 = Debug|x64 {F4B4ABD9-0606-427F-A694-7C7B72324420}.Release|Win32.ActiveCfg = Release|Win32 {F4B4ABD9-0606-427F-A694-7C7B72324420}.Release|Win32.Build.0 = Release|Win32 + {F4B4ABD9-0606-427F-A694-7C7B72324420}.Release|x64.ActiveCfg = Release|x64 + {F4B4ABD9-0606-427F-A694-7C7B72324420}.Release|x64.Build.0 = Release|x64 {217B6903-CD5A-4F81-B608-5C6879964D03}.Debug|Win32.ActiveCfg = Debug|Win32 {217B6903-CD5A-4F81-B608-5C6879964D03}.Debug|Win32.Build.0 = Debug|Win32 + {217B6903-CD5A-4F81-B608-5C6879964D03}.Debug|x64.ActiveCfg = Debug|x64 + {217B6903-CD5A-4F81-B608-5C6879964D03}.Debug|x64.Build.0 = Debug|x64 {217B6903-CD5A-4F81-B608-5C6879964D03}.Release|Win32.ActiveCfg = Release|Win32 {217B6903-CD5A-4F81-B608-5C6879964D03}.Release|Win32.Build.0 = Release|Win32 + {217B6903-CD5A-4F81-B608-5C6879964D03}.Release|x64.ActiveCfg = Release|x64 + {217B6903-CD5A-4F81-B608-5C6879964D03}.Release|x64.Build.0 = Release|x64 {49E564A9-858A-41A4-9374-E9198B861E2E}.Debug|Win32.ActiveCfg = Debug|Win32 {49E564A9-858A-41A4-9374-E9198B861E2E}.Debug|Win32.Build.0 = Debug|Win32 + {49E564A9-858A-41A4-9374-E9198B861E2E}.Debug|x64.ActiveCfg = Debug|x64 + {49E564A9-858A-41A4-9374-E9198B861E2E}.Debug|x64.Build.0 = Debug|x64 {49E564A9-858A-41A4-9374-E9198B861E2E}.Release|Win32.ActiveCfg = Release|Win32 {49E564A9-858A-41A4-9374-E9198B861E2E}.Release|Win32.Build.0 = Release|Win32 + {49E564A9-858A-41A4-9374-E9198B861E2E}.Release|x64.ActiveCfg = Release|x64 + {49E564A9-858A-41A4-9374-E9198B861E2E}.Release|x64.Build.0 = Release|x64 {0D069EE7-5E7D-412D-9D61-12092C66C025}.Debug|Win32.ActiveCfg = Debug|Win32 {0D069EE7-5E7D-412D-9D61-12092C66C025}.Debug|Win32.Build.0 = Debug|Win32 + {0D069EE7-5E7D-412D-9D61-12092C66C025}.Debug|x64.ActiveCfg = Debug|x64 + {0D069EE7-5E7D-412D-9D61-12092C66C025}.Debug|x64.Build.0 = Debug|x64 {0D069EE7-5E7D-412D-9D61-12092C66C025}.Release|Win32.ActiveCfg = Release|Win32 {0D069EE7-5E7D-412D-9D61-12092C66C025}.Release|Win32.Build.0 = Release|Win32 + {0D069EE7-5E7D-412D-9D61-12092C66C025}.Release|x64.ActiveCfg = Release|x64 + {0D069EE7-5E7D-412D-9D61-12092C66C025}.Release|x64.Build.0 = Release|x64 {52BE9E93-2F45-4FE3-8A75-F3F8293D041D}.Debug|Win32.ActiveCfg = Debug|Win32 {52BE9E93-2F45-4FE3-8A75-F3F8293D041D}.Debug|Win32.Build.0 = Debug|Win32 + {52BE9E93-2F45-4FE3-8A75-F3F8293D041D}.Debug|x64.ActiveCfg = Debug|x64 + {52BE9E93-2F45-4FE3-8A75-F3F8293D041D}.Debug|x64.Build.0 = Debug|x64 {52BE9E93-2F45-4FE3-8A75-F3F8293D041D}.Release|Win32.ActiveCfg = Release|Win32 {52BE9E93-2F45-4FE3-8A75-F3F8293D041D}.Release|Win32.Build.0 = Release|Win32 + {52BE9E93-2F45-4FE3-8A75-F3F8293D041D}.Release|x64.ActiveCfg = Release|x64 + {52BE9E93-2F45-4FE3-8A75-F3F8293D041D}.Release|x64.Build.0 = Release|x64 {C25066DD-D38E-4E7C-AE04-F9E4454B62D8}.Debug|Win32.ActiveCfg = Debug|Win32 {C25066DD-D38E-4E7C-AE04-F9E4454B62D8}.Debug|Win32.Build.0 = Debug|Win32 + {C25066DD-D38E-4E7C-AE04-F9E4454B62D8}.Debug|x64.ActiveCfg = Debug|x64 + {C25066DD-D38E-4E7C-AE04-F9E4454B62D8}.Debug|x64.Build.0 = Debug|x64 {C25066DD-D38E-4E7C-AE04-F9E4454B62D8}.Release|Win32.ActiveCfg = Release|Win32 {C25066DD-D38E-4E7C-AE04-F9E4454B62D8}.Release|Win32.Build.0 = Release|Win32 + {C25066DD-D38E-4E7C-AE04-F9E4454B62D8}.Release|x64.ActiveCfg = Release|x64 + {C25066DD-D38E-4E7C-AE04-F9E4454B62D8}.Release|x64.Build.0 = Release|x64 {732D5E59-CE6B-4C97-AEAE-F7EF20870539}.Debug|Win32.ActiveCfg = Debug|Win32 {732D5E59-CE6B-4C97-AEAE-F7EF20870539}.Debug|Win32.Build.0 = Debug|Win32 + {732D5E59-CE6B-4C97-AEAE-F7EF20870539}.Debug|x64.ActiveCfg = Debug|x64 + {732D5E59-CE6B-4C97-AEAE-F7EF20870539}.Debug|x64.Build.0 = Debug|x64 {732D5E59-CE6B-4C97-AEAE-F7EF20870539}.Release|Win32.ActiveCfg = Release|Win32 {732D5E59-CE6B-4C97-AEAE-F7EF20870539}.Release|Win32.Build.0 = Release|Win32 + {732D5E59-CE6B-4C97-AEAE-F7EF20870539}.Release|x64.ActiveCfg = Release|x64 + {732D5E59-CE6B-4C97-AEAE-F7EF20870539}.Release|x64.Build.0 = Release|x64 {BA6BD5B7-5F19-4405-ACD0-C809CB08BDF2}.Debug|Win32.ActiveCfg = Debug|Win32 {BA6BD5B7-5F19-4405-ACD0-C809CB08BDF2}.Debug|Win32.Build.0 = Debug|Win32 + {BA6BD5B7-5F19-4405-ACD0-C809CB08BDF2}.Debug|x64.ActiveCfg = Debug|x64 + {BA6BD5B7-5F19-4405-ACD0-C809CB08BDF2}.Debug|x64.Build.0 = Debug|x64 {BA6BD5B7-5F19-4405-ACD0-C809CB08BDF2}.Release|Win32.ActiveCfg = Release|Win32 {BA6BD5B7-5F19-4405-ACD0-C809CB08BDF2}.Release|Win32.Build.0 = Release|Win32 + {BA6BD5B7-5F19-4405-ACD0-C809CB08BDF2}.Release|x64.ActiveCfg = Release|x64 + {BA6BD5B7-5F19-4405-ACD0-C809CB08BDF2}.Release|x64.Build.0 = Release|x64 {8E9A1D41-5AF1-40D9-9074-6CFED91F1803}.Debug|Win32.ActiveCfg = Debug|Win32 {8E9A1D41-5AF1-40D9-9074-6CFED91F1803}.Debug|Win32.Build.0 = Debug|Win32 + {8E9A1D41-5AF1-40D9-9074-6CFED91F1803}.Debug|x64.ActiveCfg = Debug|x64 + {8E9A1D41-5AF1-40D9-9074-6CFED91F1803}.Debug|x64.Build.0 = Debug|x64 {8E9A1D41-5AF1-40D9-9074-6CFED91F1803}.Release|Win32.ActiveCfg = Release|Win32 {8E9A1D41-5AF1-40D9-9074-6CFED91F1803}.Release|Win32.Build.0 = Release|Win32 + {8E9A1D41-5AF1-40D9-9074-6CFED91F1803}.Release|x64.ActiveCfg = Release|x64 + {8E9A1D41-5AF1-40D9-9074-6CFED91F1803}.Release|x64.Build.0 = Release|x64 {1D31CFF4-888A-4433-ADB7-B836274973AB}.Debug|Win32.ActiveCfg = Debug|Win32 {1D31CFF4-888A-4433-ADB7-B836274973AB}.Debug|Win32.Build.0 = Debug|Win32 + {1D31CFF4-888A-4433-ADB7-B836274973AB}.Debug|x64.ActiveCfg = Debug|x64 + {1D31CFF4-888A-4433-ADB7-B836274973AB}.Debug|x64.Build.0 = Debug|x64 {1D31CFF4-888A-4433-ADB7-B836274973AB}.Release|Win32.ActiveCfg = Release|Win32 {1D31CFF4-888A-4433-ADB7-B836274973AB}.Release|Win32.Build.0 = Release|Win32 + {1D31CFF4-888A-4433-ADB7-B836274973AB}.Release|x64.ActiveCfg = Release|x64 + {1D31CFF4-888A-4433-ADB7-B836274973AB}.Release|x64.Build.0 = Release|x64 {10062A26-8A93-48FA-B200-7CC6FAC069D4}.Debug|Win32.ActiveCfg = Debug|Win32 {10062A26-8A93-48FA-B200-7CC6FAC069D4}.Debug|Win32.Build.0 = Debug|Win32 + {10062A26-8A93-48FA-B200-7CC6FAC069D4}.Debug|x64.ActiveCfg = Debug|x64 + {10062A26-8A93-48FA-B200-7CC6FAC069D4}.Debug|x64.Build.0 = Debug|x64 {10062A26-8A93-48FA-B200-7CC6FAC069D4}.Release|Win32.ActiveCfg = Release|Win32 {10062A26-8A93-48FA-B200-7CC6FAC069D4}.Release|Win32.Build.0 = Release|Win32 + {10062A26-8A93-48FA-B200-7CC6FAC069D4}.Release|x64.ActiveCfg = Release|x64 + {10062A26-8A93-48FA-B200-7CC6FAC069D4}.Release|x64.Build.0 = Release|x64 {4ABCE4F3-299E-42CA-82CA-4A2D401F121B}.Debug|Win32.ActiveCfg = Debug|Win32 {4ABCE4F3-299E-42CA-82CA-4A2D401F121B}.Debug|Win32.Build.0 = Debug|Win32 + {4ABCE4F3-299E-42CA-82CA-4A2D401F121B}.Debug|x64.ActiveCfg = Debug|x64 + {4ABCE4F3-299E-42CA-82CA-4A2D401F121B}.Debug|x64.Build.0 = Debug|x64 {4ABCE4F3-299E-42CA-82CA-4A2D401F121B}.Release|Win32.ActiveCfg = Release|Win32 {4ABCE4F3-299E-42CA-82CA-4A2D401F121B}.Release|Win32.Build.0 = Release|Win32 + {4ABCE4F3-299E-42CA-82CA-4A2D401F121B}.Release|x64.ActiveCfg = Release|x64 + {4ABCE4F3-299E-42CA-82CA-4A2D401F121B}.Release|x64.Build.0 = Release|x64 {D470EFEC-7CEF-4BC8-B47A-B1DEE95370BD}.Debug|Win32.ActiveCfg = Debug|Win32 {D470EFEC-7CEF-4BC8-B47A-B1DEE95370BD}.Debug|Win32.Build.0 = Debug|Win32 + {D470EFEC-7CEF-4BC8-B47A-B1DEE95370BD}.Debug|x64.ActiveCfg = Debug|x64 + {D470EFEC-7CEF-4BC8-B47A-B1DEE95370BD}.Debug|x64.Build.0 = Debug|x64 {D470EFEC-7CEF-4BC8-B47A-B1DEE95370BD}.Release|Win32.ActiveCfg = Release|Win32 {D470EFEC-7CEF-4BC8-B47A-B1DEE95370BD}.Release|Win32.Build.0 = Release|Win32 + {D470EFEC-7CEF-4BC8-B47A-B1DEE95370BD}.Release|x64.ActiveCfg = Release|x64 + {D470EFEC-7CEF-4BC8-B47A-B1DEE95370BD}.Release|x64.Build.0 = Release|x64 {850B7E98-254B-48ED-9EB0-DE6FF4669266}.Debug|Win32.ActiveCfg = Debug|Win32 {850B7E98-254B-48ED-9EB0-DE6FF4669266}.Debug|Win32.Build.0 = Debug|Win32 + {850B7E98-254B-48ED-9EB0-DE6FF4669266}.Debug|x64.ActiveCfg = Debug|x64 + {850B7E98-254B-48ED-9EB0-DE6FF4669266}.Debug|x64.Build.0 = Debug|x64 {850B7E98-254B-48ED-9EB0-DE6FF4669266}.Release|Win32.ActiveCfg = Release|Win32 {850B7E98-254B-48ED-9EB0-DE6FF4669266}.Release|Win32.Build.0 = Release|Win32 + {850B7E98-254B-48ED-9EB0-DE6FF4669266}.Release|x64.ActiveCfg = Release|x64 + {850B7E98-254B-48ED-9EB0-DE6FF4669266}.Release|x64.Build.0 = Release|x64 {30B170C7-D81B-4AE1-AB6F-3DFFB0569C21}.Debug|Win32.ActiveCfg = Debug|Win32 {30B170C7-D81B-4AE1-AB6F-3DFFB0569C21}.Debug|Win32.Build.0 = Debug|Win32 + {30B170C7-D81B-4AE1-AB6F-3DFFB0569C21}.Debug|x64.ActiveCfg = Debug|x64 + {30B170C7-D81B-4AE1-AB6F-3DFFB0569C21}.Debug|x64.Build.0 = Debug|x64 {30B170C7-D81B-4AE1-AB6F-3DFFB0569C21}.Release|Win32.ActiveCfg = Release|Win32 {30B170C7-D81B-4AE1-AB6F-3DFFB0569C21}.Release|Win32.Build.0 = Release|Win32 + {30B170C7-D81B-4AE1-AB6F-3DFFB0569C21}.Release|x64.ActiveCfg = Release|x64 + {30B170C7-D81B-4AE1-AB6F-3DFFB0569C21}.Release|x64.Build.0 = Release|x64 {E3104514-53B7-49C0-B095-8D8CA5691806}.Debug|Win32.ActiveCfg = Debug|Win32 {E3104514-53B7-49C0-B095-8D8CA5691806}.Debug|Win32.Build.0 = Debug|Win32 + {E3104514-53B7-49C0-B095-8D8CA5691806}.Debug|x64.ActiveCfg = Debug|x64 + {E3104514-53B7-49C0-B095-8D8CA5691806}.Debug|x64.Build.0 = Debug|x64 {E3104514-53B7-49C0-B095-8D8CA5691806}.Release|Win32.ActiveCfg = Release|Win32 {E3104514-53B7-49C0-B095-8D8CA5691806}.Release|Win32.Build.0 = Release|Win32 + {E3104514-53B7-49C0-B095-8D8CA5691806}.Release|x64.ActiveCfg = Release|x64 + {E3104514-53B7-49C0-B095-8D8CA5691806}.Release|x64.Build.0 = Release|x64 {0EF2810C-52E6-4898-B54F-1D62A9CF670D}.Debug|Win32.ActiveCfg = Debug|Win32 {0EF2810C-52E6-4898-B54F-1D62A9CF670D}.Debug|Win32.Build.0 = Debug|Win32 + {0EF2810C-52E6-4898-B54F-1D62A9CF670D}.Debug|x64.ActiveCfg = Debug|x64 + {0EF2810C-52E6-4898-B54F-1D62A9CF670D}.Debug|x64.Build.0 = Debug|x64 {0EF2810C-52E6-4898-B54F-1D62A9CF670D}.Release|Win32.ActiveCfg = Release|Win32 {0EF2810C-52E6-4898-B54F-1D62A9CF670D}.Release|Win32.Build.0 = Release|Win32 + {0EF2810C-52E6-4898-B54F-1D62A9CF670D}.Release|x64.ActiveCfg = Release|x64 + {0EF2810C-52E6-4898-B54F-1D62A9CF670D}.Release|x64.Build.0 = Release|x64 {A09E3242-1EC5-4901-B3F2-F3003A32DB11}.Debug|Win32.ActiveCfg = Debug|Win32 {A09E3242-1EC5-4901-B3F2-F3003A32DB11}.Debug|Win32.Build.0 = Debug|Win32 + {A09E3242-1EC5-4901-B3F2-F3003A32DB11}.Debug|x64.ActiveCfg = Debug|x64 + {A09E3242-1EC5-4901-B3F2-F3003A32DB11}.Debug|x64.Build.0 = Debug|x64 {A09E3242-1EC5-4901-B3F2-F3003A32DB11}.Release|Win32.ActiveCfg = Release|Win32 {A09E3242-1EC5-4901-B3F2-F3003A32DB11}.Release|Win32.Build.0 = Release|Win32 + {A09E3242-1EC5-4901-B3F2-F3003A32DB11}.Release|x64.ActiveCfg = Release|x64 + {A09E3242-1EC5-4901-B3F2-F3003A32DB11}.Release|x64.Build.0 = Release|x64 {6375F876-32CE-42FB-B879-453C96CBBCD1}.Debug|Win32.ActiveCfg = Debug|Win32 {6375F876-32CE-42FB-B879-453C96CBBCD1}.Debug|Win32.Build.0 = Debug|Win32 + {6375F876-32CE-42FB-B879-453C96CBBCD1}.Debug|x64.ActiveCfg = Debug|x64 + {6375F876-32CE-42FB-B879-453C96CBBCD1}.Debug|x64.Build.0 = Debug|x64 {6375F876-32CE-42FB-B879-453C96CBBCD1}.Release|Win32.ActiveCfg = Release|Win32 {6375F876-32CE-42FB-B879-453C96CBBCD1}.Release|Win32.Build.0 = Release|Win32 + {6375F876-32CE-42FB-B879-453C96CBBCD1}.Release|x64.ActiveCfg = Release|x64 + {6375F876-32CE-42FB-B879-453C96CBBCD1}.Release|x64.Build.0 = Release|x64 {EC2BBA3D-AD89-439F-9188-32B8C63B5743}.Debug|Win32.ActiveCfg = Debug|Win32 {EC2BBA3D-AD89-439F-9188-32B8C63B5743}.Debug|Win32.Build.0 = Debug|Win32 + {EC2BBA3D-AD89-439F-9188-32B8C63B5743}.Debug|x64.ActiveCfg = Debug|x64 + {EC2BBA3D-AD89-439F-9188-32B8C63B5743}.Debug|x64.Build.0 = Debug|x64 {EC2BBA3D-AD89-439F-9188-32B8C63B5743}.Release|Win32.ActiveCfg = Release|Win32 {EC2BBA3D-AD89-439F-9188-32B8C63B5743}.Release|Win32.Build.0 = Release|Win32 + {EC2BBA3D-AD89-439F-9188-32B8C63B5743}.Release|x64.ActiveCfg = Release|x64 + {EC2BBA3D-AD89-439F-9188-32B8C63B5743}.Release|x64.Build.0 = Release|x64 {647BF5FD-FB8F-41EB-8A79-17C13128F9A2}.Debug|Win32.ActiveCfg = Debug|Win32 {647BF5FD-FB8F-41EB-8A79-17C13128F9A2}.Debug|Win32.Build.0 = Debug|Win32 + {647BF5FD-FB8F-41EB-8A79-17C13128F9A2}.Debug|x64.ActiveCfg = Debug|x64 + {647BF5FD-FB8F-41EB-8A79-17C13128F9A2}.Debug|x64.Build.0 = Debug|x64 {647BF5FD-FB8F-41EB-8A79-17C13128F9A2}.Release|Win32.ActiveCfg = Release|Win32 {647BF5FD-FB8F-41EB-8A79-17C13128F9A2}.Release|Win32.Build.0 = Release|Win32 + {647BF5FD-FB8F-41EB-8A79-17C13128F9A2}.Release|x64.ActiveCfg = Release|x64 + {647BF5FD-FB8F-41EB-8A79-17C13128F9A2}.Release|x64.Build.0 = Release|x64 {079B03FB-0C5B-4BE3-99F5-6A6CBE895B1A}.Debug|Win32.ActiveCfg = Debug|Win32 {079B03FB-0C5B-4BE3-99F5-6A6CBE895B1A}.Debug|Win32.Build.0 = Debug|Win32 + {079B03FB-0C5B-4BE3-99F5-6A6CBE895B1A}.Debug|x64.ActiveCfg = Debug|x64 + {079B03FB-0C5B-4BE3-99F5-6A6CBE895B1A}.Debug|x64.Build.0 = Debug|x64 {079B03FB-0C5B-4BE3-99F5-6A6CBE895B1A}.Release|Win32.ActiveCfg = Release|Win32 {079B03FB-0C5B-4BE3-99F5-6A6CBE895B1A}.Release|Win32.Build.0 = Release|Win32 + {079B03FB-0C5B-4BE3-99F5-6A6CBE895B1A}.Release|x64.ActiveCfg = Release|x64 + {079B03FB-0C5B-4BE3-99F5-6A6CBE895B1A}.Release|x64.Build.0 = Release|x64 {5328580D-7383-4ACC-95C1-9258500B6E56}.Debug|Win32.ActiveCfg = Debug|Win32 {5328580D-7383-4ACC-95C1-9258500B6E56}.Debug|Win32.Build.0 = Debug|Win32 + {5328580D-7383-4ACC-95C1-9258500B6E56}.Debug|x64.ActiveCfg = Debug|x64 + {5328580D-7383-4ACC-95C1-9258500B6E56}.Debug|x64.Build.0 = Debug|x64 {5328580D-7383-4ACC-95C1-9258500B6E56}.Release|Win32.ActiveCfg = Release|Win32 {5328580D-7383-4ACC-95C1-9258500B6E56}.Release|Win32.Build.0 = Release|Win32 + {5328580D-7383-4ACC-95C1-9258500B6E56}.Release|x64.ActiveCfg = Release|x64 + {5328580D-7383-4ACC-95C1-9258500B6E56}.Release|x64.Build.0 = Release|x64 {76160FB6-F6B3-45D7-9FB2-EF5C586E881B}.Debug|Win32.ActiveCfg = Debug|Win32 {76160FB6-F6B3-45D7-9FB2-EF5C586E881B}.Debug|Win32.Build.0 = Debug|Win32 + {76160FB6-F6B3-45D7-9FB2-EF5C586E881B}.Debug|x64.ActiveCfg = Debug|x64 + {76160FB6-F6B3-45D7-9FB2-EF5C586E881B}.Debug|x64.Build.0 = Debug|x64 {76160FB6-F6B3-45D7-9FB2-EF5C586E881B}.Release|Win32.ActiveCfg = Release|Win32 {76160FB6-F6B3-45D7-9FB2-EF5C586E881B}.Release|Win32.Build.0 = Release|Win32 + {76160FB6-F6B3-45D7-9FB2-EF5C586E881B}.Release|x64.ActiveCfg = Release|x64 + {76160FB6-F6B3-45D7-9FB2-EF5C586E881B}.Release|x64.Build.0 = Release|x64 {5A906E9F-0CA0-4FA0-A208-4E95FDBE2C91}.Debug|Win32.ActiveCfg = Debug|Win32 {5A906E9F-0CA0-4FA0-A208-4E95FDBE2C91}.Debug|Win32.Build.0 = Debug|Win32 + {5A906E9F-0CA0-4FA0-A208-4E95FDBE2C91}.Debug|x64.ActiveCfg = Debug|x64 + {5A906E9F-0CA0-4FA0-A208-4E95FDBE2C91}.Debug|x64.Build.0 = Debug|x64 {5A906E9F-0CA0-4FA0-A208-4E95FDBE2C91}.Release|Win32.ActiveCfg = Release|Win32 {5A906E9F-0CA0-4FA0-A208-4E95FDBE2C91}.Release|Win32.Build.0 = Release|Win32 + {5A906E9F-0CA0-4FA0-A208-4E95FDBE2C91}.Release|x64.ActiveCfg = Release|x64 + {5A906E9F-0CA0-4FA0-A208-4E95FDBE2C91}.Release|x64.Build.0 = Release|x64 {8598D1D1-6820-4E25-BD54-53C982E0542E}.Debug|Win32.ActiveCfg = Debug|Win32 {8598D1D1-6820-4E25-BD54-53C982E0542E}.Debug|Win32.Build.0 = Debug|Win32 + {8598D1D1-6820-4E25-BD54-53C982E0542E}.Debug|x64.ActiveCfg = Debug|x64 + {8598D1D1-6820-4E25-BD54-53C982E0542E}.Debug|x64.Build.0 = Debug|x64 {8598D1D1-6820-4E25-BD54-53C982E0542E}.Release|Win32.ActiveCfg = Release|Win32 {8598D1D1-6820-4E25-BD54-53C982E0542E}.Release|Win32.Build.0 = Release|Win32 + {8598D1D1-6820-4E25-BD54-53C982E0542E}.Release|x64.ActiveCfg = Release|x64 + {8598D1D1-6820-4E25-BD54-53C982E0542E}.Release|x64.Build.0 = Release|x64 {C3467288-8569-4C33-BCE8-D3FD0F9266CE}.Debug|Win32.ActiveCfg = Debug|Win32 {C3467288-8569-4C33-BCE8-D3FD0F9266CE}.Debug|Win32.Build.0 = Debug|Win32 + {C3467288-8569-4C33-BCE8-D3FD0F9266CE}.Debug|x64.ActiveCfg = Debug|x64 + {C3467288-8569-4C33-BCE8-D3FD0F9266CE}.Debug|x64.Build.0 = Debug|x64 {C3467288-8569-4C33-BCE8-D3FD0F9266CE}.Release|Win32.ActiveCfg = Release|Win32 {C3467288-8569-4C33-BCE8-D3FD0F9266CE}.Release|Win32.Build.0 = Release|Win32 + {C3467288-8569-4C33-BCE8-D3FD0F9266CE}.Release|x64.ActiveCfg = Release|x64 + {C3467288-8569-4C33-BCE8-D3FD0F9266CE}.Release|x64.Build.0 = Release|x64 {9D398791-61A2-4F3F-801D-8B892D571CBE}.Debug|Win32.ActiveCfg = Debug|Win32 {9D398791-61A2-4F3F-801D-8B892D571CBE}.Debug|Win32.Build.0 = Debug|Win32 + {9D398791-61A2-4F3F-801D-8B892D571CBE}.Debug|x64.ActiveCfg = Debug|x64 + {9D398791-61A2-4F3F-801D-8B892D571CBE}.Debug|x64.Build.0 = Debug|x64 {9D398791-61A2-4F3F-801D-8B892D571CBE}.Release|Win32.ActiveCfg = Release|Win32 {9D398791-61A2-4F3F-801D-8B892D571CBE}.Release|Win32.Build.0 = Release|Win32 + {9D398791-61A2-4F3F-801D-8B892D571CBE}.Release|x64.ActiveCfg = Release|x64 + {9D398791-61A2-4F3F-801D-8B892D571CBE}.Release|x64.Build.0 = Release|x64 {F59D8293-3B30-4469-982C-F43D5F9D303A}.Debug|Win32.ActiveCfg = Debug|Win32 {F59D8293-3B30-4469-982C-F43D5F9D303A}.Debug|Win32.Build.0 = Debug|Win32 + {F59D8293-3B30-4469-982C-F43D5F9D303A}.Debug|x64.ActiveCfg = Debug|x64 + {F59D8293-3B30-4469-982C-F43D5F9D303A}.Debug|x64.Build.0 = Debug|x64 {F59D8293-3B30-4469-982C-F43D5F9D303A}.Release|Win32.ActiveCfg = Release|Win32 {F59D8293-3B30-4469-982C-F43D5F9D303A}.Release|Win32.Build.0 = Release|Win32 + {F59D8293-3B30-4469-982C-F43D5F9D303A}.Release|x64.ActiveCfg = Release|x64 + {F59D8293-3B30-4469-982C-F43D5F9D303A}.Release|x64.Build.0 = Release|x64 {C19A3155-9401-4D73-9CE1-AE2F3EE1E1A3}.Debug|Win32.ActiveCfg = Debug|Win32 {C19A3155-9401-4D73-9CE1-AE2F3EE1E1A3}.Debug|Win32.Build.0 = Debug|Win32 + {C19A3155-9401-4D73-9CE1-AE2F3EE1E1A3}.Debug|x64.ActiveCfg = Debug|x64 + {C19A3155-9401-4D73-9CE1-AE2F3EE1E1A3}.Debug|x64.Build.0 = Debug|x64 {C19A3155-9401-4D73-9CE1-AE2F3EE1E1A3}.Release|Win32.ActiveCfg = Release|Win32 {C19A3155-9401-4D73-9CE1-AE2F3EE1E1A3}.Release|Win32.Build.0 = Release|Win32 + {C19A3155-9401-4D73-9CE1-AE2F3EE1E1A3}.Release|x64.ActiveCfg = Release|x64 + {C19A3155-9401-4D73-9CE1-AE2F3EE1E1A3}.Release|x64.Build.0 = Release|x64 {3F521D73-538E-486E-9A3D-8EF8A0A25656}.Debug|Win32.ActiveCfg = Debug|Win32 {3F521D73-538E-486E-9A3D-8EF8A0A25656}.Debug|Win32.Build.0 = Debug|Win32 + {3F521D73-538E-486E-9A3D-8EF8A0A25656}.Debug|x64.ActiveCfg = Debug|x64 + {3F521D73-538E-486E-9A3D-8EF8A0A25656}.Debug|x64.Build.0 = Debug|x64 {3F521D73-538E-486E-9A3D-8EF8A0A25656}.Release|Win32.ActiveCfg = Release|Win32 {3F521D73-538E-486E-9A3D-8EF8A0A25656}.Release|Win32.Build.0 = Release|Win32 + {3F521D73-538E-486E-9A3D-8EF8A0A25656}.Release|x64.ActiveCfg = Release|x64 + {3F521D73-538E-486E-9A3D-8EF8A0A25656}.Release|x64.Build.0 = Release|x64 {A0D05807-AA99-4347-9101-4A74DBC2903F}.Debug|Win32.ActiveCfg = Debug|Win32 {A0D05807-AA99-4347-9101-4A74DBC2903F}.Debug|Win32.Build.0 = Debug|Win32 + {A0D05807-AA99-4347-9101-4A74DBC2903F}.Debug|x64.ActiveCfg = Debug|x64 + {A0D05807-AA99-4347-9101-4A74DBC2903F}.Debug|x64.Build.0 = Debug|x64 {A0D05807-AA99-4347-9101-4A74DBC2903F}.Release|Win32.ActiveCfg = Release|Win32 {A0D05807-AA99-4347-9101-4A74DBC2903F}.Release|Win32.Build.0 = Release|Win32 + {A0D05807-AA99-4347-9101-4A74DBC2903F}.Release|x64.ActiveCfg = Release|x64 + {A0D05807-AA99-4347-9101-4A74DBC2903F}.Release|x64.Build.0 = Release|x64 {BCD7360F-684A-4DE2-BA4F-C6344C9DA875}.Debug|Win32.ActiveCfg = Debug|Win32 {BCD7360F-684A-4DE2-BA4F-C6344C9DA875}.Debug|Win32.Build.0 = Debug|Win32 + {BCD7360F-684A-4DE2-BA4F-C6344C9DA875}.Debug|x64.ActiveCfg = Debug|x64 + {BCD7360F-684A-4DE2-BA4F-C6344C9DA875}.Debug|x64.Build.0 = Debug|x64 {BCD7360F-684A-4DE2-BA4F-C6344C9DA875}.Release|Win32.ActiveCfg = Release|Win32 {BCD7360F-684A-4DE2-BA4F-C6344C9DA875}.Release|Win32.Build.0 = Release|Win32 + {BCD7360F-684A-4DE2-BA4F-C6344C9DA875}.Release|x64.ActiveCfg = Release|x64 + {BCD7360F-684A-4DE2-BA4F-C6344C9DA875}.Release|x64.Build.0 = Release|x64 {6BF7E06E-4D03-4BA4-8AF2-D003441E185C}.Debug|Win32.ActiveCfg = Debug|Win32 {6BF7E06E-4D03-4BA4-8AF2-D003441E185C}.Debug|Win32.Build.0 = Debug|Win32 + {6BF7E06E-4D03-4BA4-8AF2-D003441E185C}.Debug|x64.ActiveCfg = Debug|x64 + {6BF7E06E-4D03-4BA4-8AF2-D003441E185C}.Debug|x64.Build.0 = Debug|x64 {6BF7E06E-4D03-4BA4-8AF2-D003441E185C}.Release|Win32.ActiveCfg = Release|Win32 {6BF7E06E-4D03-4BA4-8AF2-D003441E185C}.Release|Win32.Build.0 = Release|Win32 + {6BF7E06E-4D03-4BA4-8AF2-D003441E185C}.Release|x64.ActiveCfg = Release|x64 + {6BF7E06E-4D03-4BA4-8AF2-D003441E185C}.Release|x64.Build.0 = Release|x64 {AD9F8A93-9C9B-4A46-8A13-9113D72FD24A}.Debug|Win32.ActiveCfg = Debug|Win32 {AD9F8A93-9C9B-4A46-8A13-9113D72FD24A}.Debug|Win32.Build.0 = Debug|Win32 + {AD9F8A93-9C9B-4A46-8A13-9113D72FD24A}.Debug|x64.ActiveCfg = Debug|x64 + {AD9F8A93-9C9B-4A46-8A13-9113D72FD24A}.Debug|x64.Build.0 = Debug|x64 {AD9F8A93-9C9B-4A46-8A13-9113D72FD24A}.Release|Win32.ActiveCfg = Release|Win32 {AD9F8A93-9C9B-4A46-8A13-9113D72FD24A}.Release|Win32.Build.0 = Release|Win32 + {AD9F8A93-9C9B-4A46-8A13-9113D72FD24A}.Release|x64.ActiveCfg = Release|x64 + {AD9F8A93-9C9B-4A46-8A13-9113D72FD24A}.Release|x64.Build.0 = Release|x64 {E5C5BA98-F9DB-46D3-9DFB-59782C331EB2}.Debug|Win32.ActiveCfg = Debug|Win32 {E5C5BA98-F9DB-46D3-9DFB-59782C331EB2}.Debug|Win32.Build.0 = Debug|Win32 + {E5C5BA98-F9DB-46D3-9DFB-59782C331EB2}.Debug|x64.ActiveCfg = Debug|x64 + {E5C5BA98-F9DB-46D3-9DFB-59782C331EB2}.Debug|x64.Build.0 = Debug|x64 {E5C5BA98-F9DB-46D3-9DFB-59782C331EB2}.Release|Win32.ActiveCfg = Release|Win32 {E5C5BA98-F9DB-46D3-9DFB-59782C331EB2}.Release|Win32.Build.0 = Release|Win32 + {E5C5BA98-F9DB-46D3-9DFB-59782C331EB2}.Release|x64.ActiveCfg = Release|x64 + {E5C5BA98-F9DB-46D3-9DFB-59782C331EB2}.Release|x64.Build.0 = Release|x64 {9EFB2055-35E8-42E9-A274-F4987CB2A655}.Debug|Win32.ActiveCfg = Debug|Win32 {9EFB2055-35E8-42E9-A274-F4987CB2A655}.Debug|Win32.Build.0 = Debug|Win32 + {9EFB2055-35E8-42E9-A274-F4987CB2A655}.Debug|x64.ActiveCfg = Debug|x64 + {9EFB2055-35E8-42E9-A274-F4987CB2A655}.Debug|x64.Build.0 = Debug|x64 {9EFB2055-35E8-42E9-A274-F4987CB2A655}.Release|Win32.ActiveCfg = Release|Win32 {9EFB2055-35E8-42E9-A274-F4987CB2A655}.Release|Win32.Build.0 = Release|Win32 + {9EFB2055-35E8-42E9-A274-F4987CB2A655}.Release|x64.ActiveCfg = Release|x64 + {9EFB2055-35E8-42E9-A274-F4987CB2A655}.Release|x64.Build.0 = Release|x64 {5F8FC352-0076-4558-9153-CA93F50E63F4}.Debug|Win32.ActiveCfg = Debug|Win32 {5F8FC352-0076-4558-9153-CA93F50E63F4}.Debug|Win32.Build.0 = Debug|Win32 + {5F8FC352-0076-4558-9153-CA93F50E63F4}.Debug|x64.ActiveCfg = Debug|x64 + {5F8FC352-0076-4558-9153-CA93F50E63F4}.Debug|x64.Build.0 = Debug|x64 {5F8FC352-0076-4558-9153-CA93F50E63F4}.Release|Win32.ActiveCfg = Release|Win32 {5F8FC352-0076-4558-9153-CA93F50E63F4}.Release|Win32.Build.0 = Release|Win32 + {5F8FC352-0076-4558-9153-CA93F50E63F4}.Release|x64.ActiveCfg = Release|x64 + {5F8FC352-0076-4558-9153-CA93F50E63F4}.Release|x64.Build.0 = Release|x64 {B916642D-36CA-4D94-AC7D-B0FC21F14D85}.Debug|Win32.ActiveCfg = Debug|Win32 {B916642D-36CA-4D94-AC7D-B0FC21F14D85}.Debug|Win32.Build.0 = Debug|Win32 + {B916642D-36CA-4D94-AC7D-B0FC21F14D85}.Debug|x64.ActiveCfg = Debug|x64 + {B916642D-36CA-4D94-AC7D-B0FC21F14D85}.Debug|x64.Build.0 = Debug|x64 {B916642D-36CA-4D94-AC7D-B0FC21F14D85}.Release|Win32.ActiveCfg = Release|Win32 {B916642D-36CA-4D94-AC7D-B0FC21F14D85}.Release|Win32.Build.0 = Release|Win32 + {B916642D-36CA-4D94-AC7D-B0FC21F14D85}.Release|x64.ActiveCfg = Release|x64 + {B916642D-36CA-4D94-AC7D-B0FC21F14D85}.Release|x64.Build.0 = Release|x64 {AE6AE0BE-91DD-4CEF-AB70-1B1F2B6A4928}.Debug|Win32.ActiveCfg = Debug|Win32 {AE6AE0BE-91DD-4CEF-AB70-1B1F2B6A4928}.Debug|Win32.Build.0 = Debug|Win32 + {AE6AE0BE-91DD-4CEF-AB70-1B1F2B6A4928}.Debug|x64.ActiveCfg = Debug|x64 + {AE6AE0BE-91DD-4CEF-AB70-1B1F2B6A4928}.Debug|x64.Build.0 = Debug|x64 {AE6AE0BE-91DD-4CEF-AB70-1B1F2B6A4928}.Release|Win32.ActiveCfg = Release|Win32 {AE6AE0BE-91DD-4CEF-AB70-1B1F2B6A4928}.Release|Win32.Build.0 = Release|Win32 + {AE6AE0BE-91DD-4CEF-AB70-1B1F2B6A4928}.Release|x64.ActiveCfg = Release|x64 + {AE6AE0BE-91DD-4CEF-AB70-1B1F2B6A4928}.Release|x64.Build.0 = Release|x64 {2A76BC2B-B65E-4A55-BF8F-1AA6AC47EDA5}.Debug|Win32.ActiveCfg = Debug|Win32 {2A76BC2B-B65E-4A55-BF8F-1AA6AC47EDA5}.Debug|Win32.Build.0 = Debug|Win32 + {2A76BC2B-B65E-4A55-BF8F-1AA6AC47EDA5}.Debug|x64.ActiveCfg = Debug|x64 + {2A76BC2B-B65E-4A55-BF8F-1AA6AC47EDA5}.Debug|x64.Build.0 = Debug|x64 {2A76BC2B-B65E-4A55-BF8F-1AA6AC47EDA5}.Release|Win32.ActiveCfg = Release|Win32 {2A76BC2B-B65E-4A55-BF8F-1AA6AC47EDA5}.Release|Win32.Build.0 = Release|Win32 + {2A76BC2B-B65E-4A55-BF8F-1AA6AC47EDA5}.Release|x64.ActiveCfg = Release|x64 + {2A76BC2B-B65E-4A55-BF8F-1AA6AC47EDA5}.Release|x64.Build.0 = Release|x64 {1F050D2A-3D9F-4307-922A-F977634496B1}.Debug|Win32.ActiveCfg = Debug|Win32 {1F050D2A-3D9F-4307-922A-F977634496B1}.Debug|Win32.Build.0 = Debug|Win32 + {1F050D2A-3D9F-4307-922A-F977634496B1}.Debug|x64.ActiveCfg = Debug|x64 + {1F050D2A-3D9F-4307-922A-F977634496B1}.Debug|x64.Build.0 = Debug|x64 {1F050D2A-3D9F-4307-922A-F977634496B1}.Release|Win32.ActiveCfg = Release|Win32 {1F050D2A-3D9F-4307-922A-F977634496B1}.Release|Win32.Build.0 = Release|Win32 + {1F050D2A-3D9F-4307-922A-F977634496B1}.Release|x64.ActiveCfg = Release|x64 + {1F050D2A-3D9F-4307-922A-F977634496B1}.Release|x64.Build.0 = Release|x64 {D8C4F37F-2050-4B9D-BBE3-E639DB685912}.Debug|Win32.ActiveCfg = Debug|Win32 {D8C4F37F-2050-4B9D-BBE3-E639DB685912}.Debug|Win32.Build.0 = Debug|Win32 + {D8C4F37F-2050-4B9D-BBE3-E639DB685912}.Debug|x64.ActiveCfg = Debug|x64 + {D8C4F37F-2050-4B9D-BBE3-E639DB685912}.Debug|x64.Build.0 = Debug|x64 {D8C4F37F-2050-4B9D-BBE3-E639DB685912}.Release|Win32.ActiveCfg = Release|Win32 {D8C4F37F-2050-4B9D-BBE3-E639DB685912}.Release|Win32.Build.0 = Release|Win32 + {D8C4F37F-2050-4B9D-BBE3-E639DB685912}.Release|x64.ActiveCfg = Release|x64 + {D8C4F37F-2050-4B9D-BBE3-E639DB685912}.Release|x64.Build.0 = Release|x64 {F4499413-99DE-4504-AC61-E1BBC58EBD11}.Debug|Win32.ActiveCfg = Debug|Win32 {F4499413-99DE-4504-AC61-E1BBC58EBD11}.Debug|Win32.Build.0 = Debug|Win32 + {F4499413-99DE-4504-AC61-E1BBC58EBD11}.Debug|x64.ActiveCfg = Debug|x64 + {F4499413-99DE-4504-AC61-E1BBC58EBD11}.Debug|x64.Build.0 = Debug|x64 {F4499413-99DE-4504-AC61-E1BBC58EBD11}.Release|Win32.ActiveCfg = Release|Win32 {F4499413-99DE-4504-AC61-E1BBC58EBD11}.Release|Win32.Build.0 = Release|Win32 + {F4499413-99DE-4504-AC61-E1BBC58EBD11}.Release|x64.ActiveCfg = Release|x64 + {F4499413-99DE-4504-AC61-E1BBC58EBD11}.Release|x64.Build.0 = Release|x64 {F84838B5-5C1C-468D-8EB7-0024C6ADBE62}.Debug|Win32.ActiveCfg = Debug|Win32 {F84838B5-5C1C-468D-8EB7-0024C6ADBE62}.Debug|Win32.Build.0 = Debug|Win32 + {F84838B5-5C1C-468D-8EB7-0024C6ADBE62}.Debug|x64.ActiveCfg = Debug|x64 + {F84838B5-5C1C-468D-8EB7-0024C6ADBE62}.Debug|x64.Build.0 = Debug|x64 {F84838B5-5C1C-468D-8EB7-0024C6ADBE62}.Release|Win32.ActiveCfg = Release|Win32 {F84838B5-5C1C-468D-8EB7-0024C6ADBE62}.Release|Win32.Build.0 = Release|Win32 + {F84838B5-5C1C-468D-8EB7-0024C6ADBE62}.Release|x64.ActiveCfg = Release|x64 + {F84838B5-5C1C-468D-8EB7-0024C6ADBE62}.Release|x64.Build.0 = Release|x64 {7A5099B9-F3BF-4AF8-9770-82DA635407B2}.Debug|Win32.ActiveCfg = Debug|Win32 {7A5099B9-F3BF-4AF8-9770-82DA635407B2}.Debug|Win32.Build.0 = Debug|Win32 + {7A5099B9-F3BF-4AF8-9770-82DA635407B2}.Debug|x64.ActiveCfg = Debug|x64 + {7A5099B9-F3BF-4AF8-9770-82DA635407B2}.Debug|x64.Build.0 = Debug|x64 {7A5099B9-F3BF-4AF8-9770-82DA635407B2}.Release|Win32.ActiveCfg = Release|Win32 {7A5099B9-F3BF-4AF8-9770-82DA635407B2}.Release|Win32.Build.0 = Release|Win32 + {7A5099B9-F3BF-4AF8-9770-82DA635407B2}.Release|x64.ActiveCfg = Release|x64 + {7A5099B9-F3BF-4AF8-9770-82DA635407B2}.Release|x64.Build.0 = Release|x64 {30E2512A-087F-4209-83E1-59ADF46796C8}.Debug|Win32.ActiveCfg = Debug|Win32 {30E2512A-087F-4209-83E1-59ADF46796C8}.Debug|Win32.Build.0 = Debug|Win32 + {30E2512A-087F-4209-83E1-59ADF46796C8}.Debug|x64.ActiveCfg = Debug|x64 + {30E2512A-087F-4209-83E1-59ADF46796C8}.Debug|x64.Build.0 = Debug|x64 {30E2512A-087F-4209-83E1-59ADF46796C8}.Release|Win32.ActiveCfg = Release|Win32 {30E2512A-087F-4209-83E1-59ADF46796C8}.Release|Win32.Build.0 = Release|Win32 + {30E2512A-087F-4209-83E1-59ADF46796C8}.Release|x64.ActiveCfg = Release|x64 + {30E2512A-087F-4209-83E1-59ADF46796C8}.Release|x64.Build.0 = Release|x64 {001B9FCE-61C0-4CA5-B466-2E7D1A970FDD}.Debug|Win32.ActiveCfg = Debug|Win32 {001B9FCE-61C0-4CA5-B466-2E7D1A970FDD}.Debug|Win32.Build.0 = Debug|Win32 + {001B9FCE-61C0-4CA5-B466-2E7D1A970FDD}.Debug|x64.ActiveCfg = Debug|x64 + {001B9FCE-61C0-4CA5-B466-2E7D1A970FDD}.Debug|x64.Build.0 = Debug|x64 {001B9FCE-61C0-4CA5-B466-2E7D1A970FDD}.Release|Win32.ActiveCfg = Release|Win32 {001B9FCE-61C0-4CA5-B466-2E7D1A970FDD}.Release|Win32.Build.0 = Release|Win32 + {001B9FCE-61C0-4CA5-B466-2E7D1A970FDD}.Release|x64.ActiveCfg = Release|x64 + {001B9FCE-61C0-4CA5-B466-2E7D1A970FDD}.Release|x64.Build.0 = Release|x64 {706094E9-0291-44EA-B2F0-AAD0D5AE4636}.Debug|Win32.ActiveCfg = Debug|Win32 {706094E9-0291-44EA-B2F0-AAD0D5AE4636}.Debug|Win32.Build.0 = Debug|Win32 + {706094E9-0291-44EA-B2F0-AAD0D5AE4636}.Debug|x64.ActiveCfg = Debug|x64 + {706094E9-0291-44EA-B2F0-AAD0D5AE4636}.Debug|x64.Build.0 = Debug|x64 {706094E9-0291-44EA-B2F0-AAD0D5AE4636}.Release|Win32.ActiveCfg = Release|Win32 {706094E9-0291-44EA-B2F0-AAD0D5AE4636}.Release|Win32.Build.0 = Release|Win32 + {706094E9-0291-44EA-B2F0-AAD0D5AE4636}.Release|x64.ActiveCfg = Release|x64 + {706094E9-0291-44EA-B2F0-AAD0D5AE4636}.Release|x64.Build.0 = Release|x64 {9E15E856-4BD0-4A93-9868-1BD0897DF499}.Debug|Win32.ActiveCfg = Debug|Win32 {9E15E856-4BD0-4A93-9868-1BD0897DF499}.Debug|Win32.Build.0 = Debug|Win32 + {9E15E856-4BD0-4A93-9868-1BD0897DF499}.Debug|x64.ActiveCfg = Debug|x64 + {9E15E856-4BD0-4A93-9868-1BD0897DF499}.Debug|x64.Build.0 = Debug|x64 {9E15E856-4BD0-4A93-9868-1BD0897DF499}.Release|Win32.ActiveCfg = Release|Win32 {9E15E856-4BD0-4A93-9868-1BD0897DF499}.Release|Win32.Build.0 = Release|Win32 + {9E15E856-4BD0-4A93-9868-1BD0897DF499}.Release|x64.ActiveCfg = Release|x64 + {9E15E856-4BD0-4A93-9868-1BD0897DF499}.Release|x64.Build.0 = Release|x64 {10D2EF03-E8CE-4C81-BD13-AC4E92CE55E3}.Debug|Win32.ActiveCfg = Debug|Win32 {10D2EF03-E8CE-4C81-BD13-AC4E92CE55E3}.Debug|Win32.Build.0 = Debug|Win32 + {10D2EF03-E8CE-4C81-BD13-AC4E92CE55E3}.Debug|x64.ActiveCfg = Debug|x64 + {10D2EF03-E8CE-4C81-BD13-AC4E92CE55E3}.Debug|x64.Build.0 = Debug|x64 {10D2EF03-E8CE-4C81-BD13-AC4E92CE55E3}.Release|Win32.ActiveCfg = Release|Win32 {10D2EF03-E8CE-4C81-BD13-AC4E92CE55E3}.Release|Win32.Build.0 = Release|Win32 + {10D2EF03-E8CE-4C81-BD13-AC4E92CE55E3}.Release|x64.ActiveCfg = Release|x64 + {10D2EF03-E8CE-4C81-BD13-AC4E92CE55E3}.Release|x64.Build.0 = Release|x64 {028BE356-3963-4920-993E-0426B3875EA6}.Debug|Win32.ActiveCfg = Debug|Win32 {028BE356-3963-4920-993E-0426B3875EA6}.Debug|Win32.Build.0 = Debug|Win32 + {028BE356-3963-4920-993E-0426B3875EA6}.Debug|x64.ActiveCfg = Debug|x64 + {028BE356-3963-4920-993E-0426B3875EA6}.Debug|x64.Build.0 = Debug|x64 {028BE356-3963-4920-993E-0426B3875EA6}.Release|Win32.ActiveCfg = Release|Win32 {028BE356-3963-4920-993E-0426B3875EA6}.Release|Win32.Build.0 = Release|Win32 + {028BE356-3963-4920-993E-0426B3875EA6}.Release|x64.ActiveCfg = Release|x64 + {028BE356-3963-4920-993E-0426B3875EA6}.Release|x64.Build.0 = Release|x64 {E0F60198-5C6B-4779-B8E4-F1D823F1ACB5}.Debug|Win32.ActiveCfg = Debug|Win32 {E0F60198-5C6B-4779-B8E4-F1D823F1ACB5}.Debug|Win32.Build.0 = Debug|Win32 + {E0F60198-5C6B-4779-B8E4-F1D823F1ACB5}.Debug|x64.ActiveCfg = Debug|x64 + {E0F60198-5C6B-4779-B8E4-F1D823F1ACB5}.Debug|x64.Build.0 = Debug|x64 {E0F60198-5C6B-4779-B8E4-F1D823F1ACB5}.Release|Win32.ActiveCfg = Release|Win32 {E0F60198-5C6B-4779-B8E4-F1D823F1ACB5}.Release|Win32.Build.0 = Release|Win32 + {E0F60198-5C6B-4779-B8E4-F1D823F1ACB5}.Release|x64.ActiveCfg = Release|x64 + {E0F60198-5C6B-4779-B8E4-F1D823F1ACB5}.Release|x64.Build.0 = Release|x64 {E66DB777-8EE1-43FE-892C-039F22944B65}.Debug|Win32.ActiveCfg = Debug|Win32 {E66DB777-8EE1-43FE-892C-039F22944B65}.Debug|Win32.Build.0 = Debug|Win32 + {E66DB777-8EE1-43FE-892C-039F22944B65}.Debug|x64.ActiveCfg = Debug|x64 + {E66DB777-8EE1-43FE-892C-039F22944B65}.Debug|x64.Build.0 = Debug|x64 {E66DB777-8EE1-43FE-892C-039F22944B65}.Release|Win32.ActiveCfg = Release|Win32 {E66DB777-8EE1-43FE-892C-039F22944B65}.Release|Win32.Build.0 = Release|Win32 + {E66DB777-8EE1-43FE-892C-039F22944B65}.Release|x64.ActiveCfg = Release|x64 + {E66DB777-8EE1-43FE-892C-039F22944B65}.Release|x64.Build.0 = Release|x64 + {BDA1EB83-D53E-41A7-825F-0EFDC3D643E3}.Debug|Win32.ActiveCfg = Debug|Win32 + {BDA1EB83-D53E-41A7-825F-0EFDC3D643E3}.Debug|Win32.Build.0 = Debug|Win32 + {BDA1EB83-D53E-41A7-825F-0EFDC3D643E3}.Debug|x64.ActiveCfg = Debug|x64 + {BDA1EB83-D53E-41A7-825F-0EFDC3D643E3}.Debug|x64.Build.0 = Debug|x64 + {BDA1EB83-D53E-41A7-825F-0EFDC3D643E3}.Release|Win32.ActiveCfg = Release|Win32 + {BDA1EB83-D53E-41A7-825F-0EFDC3D643E3}.Release|Win32.Build.0 = Release|Win32 + {BDA1EB83-D53E-41A7-825F-0EFDC3D643E3}.Release|x64.ActiveCfg = Release|x64 + {BDA1EB83-D53E-41A7-825F-0EFDC3D643E3}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bochs.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bochs.vcxproj index 1dc0806536..bc98d0d06a 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bochs.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bochs.vcxproj @@ -217,7 +217,7 @@ .\..\obj-release\bochs.exe true false - true + false .\..\obj-release\bochs.pdb Console false @@ -268,7 +268,7 @@ .\..\obj-release\bochs.exe true false - true + false .\..\obj-release\bochs.pdb Console false @@ -352,6 +352,9 @@ {bbff892d-2f57-4561-b2d0-ed4c3a9b7051} false + + {bda1eb83-d53e-41a7-825f-0efdc3d643e3} + {b107c955-4324-4990-bb79-6cbc91c6d12a} false diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_acpi.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_acpi.vcxproj index 927dd927bc..4a93c2b6db 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_acpi.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_acpi.vcxproj @@ -170,7 +170,7 @@ ../obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ../obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_biosdev.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_biosdev.vcxproj index 5af9d1bb4d..55c75c442d 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_biosdev.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_biosdev.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_busmouse.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_busmouse.vcxproj index 69a6abd86a..f6a9809bbd 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_busmouse.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_busmouse.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_cmos.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_cmos.vcxproj index fbee519e86..372b231e72 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_cmos.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_cmos.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_dma.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_dma.vcxproj index 0584ecab35..fbd6af3a45 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_dma.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_dma.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_e1000.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_e1000.vcxproj index 00db729ac0..b24efd80f4 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_e1000.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_e1000.vcxproj @@ -171,7 +171,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -201,7 +201,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_es1370.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_es1370.vcxproj index 2fa725b226..11cc2b5f83 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_es1370.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_es1370.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_null.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_null.vcxproj index 1a1db5f023..1760a5bc73 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_null.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_null.vcxproj @@ -171,7 +171,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -201,7 +201,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_slirp.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_slirp.vcxproj index ff8bb3b89a..54b45fa92c 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_slirp.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_slirp.vcxproj @@ -102,6 +102,7 @@ Level3 true OldStyle + stdcpp20 _DEBUG;%(PreprocessorDefinitions) @@ -132,6 +133,7 @@ Level3 true OldStyle + stdcpp20 _DEBUG;%(PreprocessorDefinitions) @@ -164,6 +166,7 @@ Level3 true FastCall + stdcpp20 NDEBUG;%(PreprocessorDefinitions) @@ -171,7 +174,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -194,6 +197,7 @@ Level3 true FastCall + stdcpp20 NDEBUG;%(PreprocessorDefinitions) @@ -201,7 +205,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) @@ -211,14 +215,19 @@ - + + + + + + @@ -228,22 +237,27 @@ + + + + + + - @@ -251,6 +265,7 @@ + diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_socket.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_socket.vcxproj index 714c77834b..a52ee4fa57 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_socket.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_socket.vcxproj @@ -171,7 +171,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -201,7 +201,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_vnet.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_vnet.vcxproj index 7212677a2a..c5ebd943a8 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_vnet.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_vnet.vcxproj @@ -171,7 +171,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -201,7 +201,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_win32.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_win32.vcxproj index e429704efb..a228177274 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_win32.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_eth_win32.vcxproj @@ -171,7 +171,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -201,7 +201,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_extfpuirq.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_extfpuirq.vcxproj index 234ff01431..ae182cdef7 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_extfpuirq.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_extfpuirq.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_floppy.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_floppy.vcxproj index fa0bdbb6bc..62d69c13e0 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_floppy.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_floppy.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_gameport.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_gameport.vcxproj index 045a37842f..155eb703f9 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_gameport.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_gameport.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;winmm.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;winmm.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_harddrv.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_harddrv.vcxproj index c9c7c2172f..081f88c983 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_harddrv.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_harddrv.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_hpet.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_hpet.vcxproj index 15eac02a35..a616803d22 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_hpet.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_hpet.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_ioapic.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_ioapic.vcxproj index 5d6a9f96df..9a93f71dbc 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_ioapic.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_ioapic.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_keyboard.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_keyboard.vcxproj index 044e223937..fd8d66c892 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_keyboard.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_keyboard.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_ne2k.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_ne2k.vcxproj index 23863c2bac..88d3205217 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_ne2k.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_ne2k.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_nogui_gui.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_nogui_gui.vcxproj index 99803bd5a8..dd01de594a 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_nogui_gui.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_nogui_gui.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_parallel.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_parallel.vcxproj index f4ad8ac3db..f63baa7fd4 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_parallel.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_parallel.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci.vcxproj index 7803ac16ed..94429b3846 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci2isa.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci2isa.vcxproj index d5f82e074a..463221ec22 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci2isa.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci2isa.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci_ide.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci_ide.vcxproj index b6beea3519..4954baaa0e 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci_ide.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pci_ide.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pic.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pic.vcxproj index 1416dcae91..5be4c00795 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pic.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pic.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pit.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pit.vcxproj index 8b03c05c8f..38f3d469f4 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pit.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_pit.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_rfb_gui.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_rfb_gui.vcxproj index 20277e773b..3ea2e617b3 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_rfb_gui.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_rfb_gui.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_sb16.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_sb16.vcxproj index 674e5fb91c..cb757bf0c5 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_sb16.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_sb16.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_serial.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_serial.vcxproj index 903f8a5676..7dabc64784 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_serial.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_serial.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;ws2_32.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_sounddummy.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_sounddummy.vcxproj index 95117eb69c..c939e25550 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_sounddummy.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_sounddummy.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_soundfile.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_soundfile.vcxproj index 9166cbc595..29ef71217a 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_soundfile.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_soundfile.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_soundwin.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_soundwin.vcxproj index ad74c1a315..b11d427388 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_soundwin.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_soundwin.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;winmm.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;winmm.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_speaker.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_speaker.vcxproj index 836b68fef9..7922568696 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_speaker.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_speaker.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_svga_cirrus.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_svga_cirrus.vcxproj index 728cdb733e..7161cd809a 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_svga_cirrus.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_svga_cirrus.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_textconfig.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_textconfig.vcxproj index de6b91573d..a1d9dfa6f8 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_textconfig.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_textconfig.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_unmapped.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_unmapped.vcxproj index dec5f4e408..c98b01c3b8 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_unmapped.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_unmapped.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_ehci.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_ehci.vcxproj index baab5aa376..fd9fe432cd 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_ehci.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_ehci.vcxproj @@ -68,24 +68,24 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\usb_ehci\ - .\..\obj-debug\usb_ehci\ + .\..\obj-debug\bx_usb_ehci\ + .\..\obj-debug\bx_usb_ehci\ true false - .\..\obj-debug\usb_ehci\ - .\..\obj-debug\usb_ehci\ + .\..\obj-debug\bx_usb_ehci\ + .\..\obj-debug\bx_usb_ehci\ true false - .\..\obj-release\usb_ehci\ - .\..\obj-release\usb_ehci\ + .\..\obj-release\bx_usb_ehci\ + .\..\obj-release\bx_usb_ehci\ - .\..\obj-release\usb_ehci\ - .\..\obj-release\usb_ehci\ + .\..\obj-release\bx_usb_ehci\ + .\..\obj-release\bx_usb_ehci\ @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_floppy.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_floppy.vcxproj index 50ce87c1c4..6cd9bd0b78 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_floppy.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_floppy.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_hid.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_hid.vcxproj index 194a675992..ed7db67a87 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_hid.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_hid.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_hub.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_hub.vcxproj index c5f9a5d275..98ebe9909c 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_hub.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_hub.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_msd.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_msd.vcxproj index d60ad89862..9f3edd47fa 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_msd.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_msd.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_ohci.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_ohci.vcxproj index 3b05201c71..c724c56e83 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_ohci.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_ohci.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_printer.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_printer.vcxproj index 07351f0892..e1defdb42e 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_printer.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_printer.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_uhci.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_uhci.vcxproj index 32962d45cb..67744f1f52 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_uhci.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_uhci.vcxproj @@ -68,24 +68,24 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\usb_uhci\ - .\..\obj-debug\usb_uhci\ + .\..\obj-debug\bx_usb_uhci\ + .\..\obj-debug\bx_usb_uhci\ true false - .\..\obj-debug\usb_uhci\ - .\..\obj-debug\usb_uhci\ + .\..\obj-debug\bx_usb_uhci\ + .\..\obj-debug\bx_usb_uhci\ true false - .\..\obj-release\usb_uhci\ - .\..\obj-release\usb_uhci\ + .\..\obj-release\bx_usb_uhci\ + .\..\obj-release\bx_usb_uhci\ - .\..\obj-release\usb_uhci\ - .\..\obj-release\usb_uhci\ + .\..\obj-release\bx_usb_uhci\ + .\..\obj-release\bx_usb_uhci\ @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_xhci.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_xhci.vcxproj index 8a86c3e338..ce4795273e 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_xhci.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_usb_xhci.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vbox_img.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vbox_img.vcxproj index 5a30326977..72ff92dcea 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vbox_img.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vbox_img.vcxproj @@ -171,7 +171,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -201,7 +201,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vga.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vga.vcxproj index b082931e8c..ddbd84db79 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vga.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vga.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vmware3_img.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vmware3_img.vcxproj index 98fae19e8b..1ae7688b46 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vmware3_img.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vmware3_img.vcxproj @@ -171,7 +171,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -201,7 +201,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vmware4_img.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vmware4_img.vcxproj index f941f57ca2..a7162c57ea 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vmware4_img.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vmware4_img.vcxproj @@ -171,7 +171,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -201,7 +201,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_voodoo.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_voodoo.vcxproj index 227dc73e32..efd5641751 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_voodoo.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_voodoo.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vpc_img.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vpc_img.vcxproj index 3efe12b47a..679d555966 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vpc_img.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vpc_img.vcxproj @@ -171,7 +171,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -201,7 +201,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vvfat_img.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vvfat_img.vcxproj index 5ce9c0029a..d291a78712 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vvfat_img.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_vvfat_img.vcxproj @@ -171,7 +171,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -201,7 +201,7 @@ ..\obj-release\bochs.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_win32_gui.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_win32_gui.vcxproj index 6e64b8e3a4..8b7ead03a0 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_win32_gui.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_win32_gui.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;comctl32.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;comctl32.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_win32config.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_win32config.vcxproj index 1b557da7f7..9203ef25d3 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_win32config.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bx_win32config.vcxproj @@ -170,7 +170,7 @@ ..\obj-release\bochs.lib;comctl32.lib;%(AdditionalDependencies) - true + false Console MachineX86 .\..\obj-release\$(TargetName)$(TargetExt) @@ -200,7 +200,7 @@ ..\obj-release\bochs.lib;comctl32.lib;%(AdditionalDependencies) - true + false Console .\..\obj-release\$(TargetName)$(TargetExt) @@ -215,6 +215,7 @@ + diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bxhub.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bxhub.vcxproj index 506c346de9..3fc59240a5 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bxhub.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bxhub.vcxproj @@ -210,6 +210,7 @@ MachineX86 ws2_32.lib;%(AdditionalDependencies) + false true @@ -256,6 +257,7 @@ ws2_32.lib;%(AdditionalDependencies) + false true diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bximage.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bximage.vcxproj index 0c8f6ca38e..e0ea268e73 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/bximage.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/bximage.vcxproj @@ -207,6 +207,7 @@ false MachineX86 + false true @@ -252,6 +253,7 @@ false + false true diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/fpu.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/fpu.vcxproj index 9b5984743a..7ae1659f21 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/fpu.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/fpu.vcxproj @@ -5,14 +5,14 @@ Debug Win32 - - Debug - x64 - Release Win32 + + Debug + x64 + Release x64 @@ -22,25 +22,25 @@ {5661CD4E-BA54-4E67-A586-BB014AC94614} - + StaticLibrary v142 false MultiByte - + StaticLibrary v142 false MultiByte - + StaticLibrary v142 false MultiByte - + StaticLibrary v142 false @@ -49,19 +49,19 @@ - + - + - + - + @@ -70,19 +70,19 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\fpu\ - .\..\obj-debug\fpu\ - - - .\..\obj-debug\fpu\ + .\..\obj-debug\ .\..\obj-debug\fpu\ - .\..\obj-release\fpu\ + .\..\obj-release\ .\..\obj-release\fpu\ + + .\..\obj-debug\ + .\..\obj-debug\fpu\ + - .\..\obj-release\fpu\ + .\..\obj-release\ .\..\obj-release\fpu\ @@ -91,8 +91,8 @@ Disabled - ..;..\instrument\stubs;.\stubs;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;NDEBUG;_WINDOWS;PARANOID;DEBUGGING;NO_ASSEMBLER;USE_WITH_CPU_SIM;%(PreprocessorDefinitions) + ..;..\cpu;..\instrument\stubs;.\stubs;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions) MultiThreadedDebugDLL .\..\obj-debug\fpu\fpu.pch .\..\obj-debug\fpu\ @@ -115,68 +115,68 @@ .\..\obj-debug\fpu\fpu.bsc - + $(IntDir)BuildLog-$(TargetName).log - Disabled - ..;..\instrument\stubs;.\stubs;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;NDEBUG;_WINDOWS;PARANOID;DEBUGGING;NO_ASSEMBLER;USE_WITH_CPU_SIM;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - .\..\obj-debug\fpu\fpu.pch - .\..\obj-debug\fpu\ - .\..\obj-debug\fpu\ - .\..\obj-debug\fpu\ + MaxSpeed + OnlyExplicitInline + ..;..\cpu;..\instrument\stubs;stubs;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + + MultiThreadedDLL + true + .\..\obj-release\fpu\fpu.pch + .\..\obj-release\fpu\ + .\..\obj-release\fpu\ + .\..\obj-release\fpu\ Level3 true - OldStyle + FastCall - _DEBUG;%(PreprocessorDefinitions) + NDEBUG;%(PreprocessorDefinitions) 0x0409 - .\..\obj-debug\fpu.lib + .\..\obj-release\fpu.lib true true - .\..\obj-debug\fpu\fpu.bsc + .\..\obj-release\fpu\fpu.bsc - + $(IntDir)BuildLog-$(TargetName).log - MaxSpeed - OnlyExplicitInline - ..;..\instrument\stubs;stubs;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;PARANOID;DEBUGGING;NO_ASSEMBLER;USE_WITH_CPU_SIM;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - - MultiThreadedDLL - true - .\..\obj-release\fpu\fpu.pch - .\..\obj-release\fpu\ - .\..\obj-release\fpu\ - .\..\obj-release\fpu\ + Disabled + ..;..\cpu;..\instrument\stubs;.\stubs;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + .\..\obj-debug\fpu\fpu.pch + .\..\obj-debug\fpu\ + .\..\obj-debug\fpu\ + .\..\obj-debug\fpu\ Level3 true - FastCall + OldStyle - NDEBUG;%(PreprocessorDefinitions) + _DEBUG;%(PreprocessorDefinitions) 0x0409 - .\..\obj-release\fpu.lib + .\..\obj-debug\fpu.lib true true - .\..\obj-release\fpu\fpu.bsc + .\..\obj-debug\fpu\fpu.bsc @@ -186,8 +186,8 @@ MaxSpeed OnlyExplicitInline - ..;..\instrument\stubs;stubs;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;PARANOID;DEBUGGING;NO_ASSEMBLER;USE_WITH_CPU_SIM;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..;..\cpu;..\instrument\stubs;stubs;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true @@ -230,22 +230,12 @@ - - - - - - - - - - - + diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/gui.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/gui.vcxproj index df80f6dd3f..1145b115de 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/gui.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/gui.vcxproj @@ -221,7 +221,9 @@ + + @@ -229,10 +231,14 @@ + + + + diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/niclist.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/niclist.vcxproj index 04988b8ca7..9ab6ee07b9 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019-plugins/niclist.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/niclist.vcxproj @@ -207,6 +207,7 @@ false MachineX86 + false true @@ -251,6 +252,7 @@ false + false true diff --git a/bochs/build/win32/vs2019-workspace/vs2019-plugins/softfloat3e.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019-plugins/softfloat3e.vcxproj new file mode 100644 index 0000000000..695912086c --- /dev/null +++ b/bochs/build/win32/vs2019-workspace/vs2019-plugins/softfloat3e.vcxproj @@ -0,0 +1,440 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {bda1eb83-d53e-41a7-825f-0efdc3d643e3} + + + + StaticLibrary + v142 + false + MultiByte + + + StaticLibrary + v142 + false + MultiByte + + + StaticLibrary + v142 + false + MultiByte + + + StaticLibrary + v142 + false + MultiByte + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>12.0.21005.1 + + + .\..\obj-debug\ + .\..\obj-debug\softfloat3e\ + + + .\..\obj-release\ + .\..\obj-release\softfloat3e\ + + + .\..\obj-debug\ + .\..\obj-debug\softfloat3e\ + + + .\..\obj-release\ + .\..\obj-release\softfloat3e\ + + + + $(IntDir)BuildLog-$(TargetName).log + + + Disabled + ..;..\cpu\softfloat3e\include;..\cpu\softfloat3e\8086-SSE + WIN32;_DEBUG;_CONSOLE;INLINE_LEVEL=5;SOFTFLOAT_FAST_DIV32TO16;SOFTFLOAT_FAST_DIV64TO32;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + .\..\obj-debug\softfloat3e\softfloat3e.pch + .\..\obj-debug\softfloat3e\ + .\..\obj-debug\softfloat3e\ + .\..\obj-debug\softfloat3e\ + Level3 + true + OldStyle + CompileAsCpp + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + .\..\obj-debug\softfloat3e.lib + true + + + true + .\..\obj-debug\softfloat3e\softfloat3e.bsc + + + + + $(IntDir)BuildLog-$(TargetName).log + + + MaxSpeed + OnlyExplicitInline + ..;..\cpu\softfloat3e\include;..\cpu\softfloat3e\8086-SSE + WIN32;NDEBUG;_CONSOLE;INLINE_LEVEL=5;SOFTFLOAT_FAST_DIV32TO16;SOFTFLOAT_FAST_DIV64TO32;%(PreprocessorDefinitions) + true + + MultiThreadedDLL + true + .\..\obj-release\softfloat3e\softfloat3e.pch + .\..\obj-release\softfloat3e\ + .\..\obj-release\softfloat3e\ + .\..\obj-release\softfloat3e\ + Level3 + true + FastCall + CompileAsCpp + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + .\..\obj-release\softfloat3e.lib + true + + + true + .\..\obj-release\softfloat3e\softfloat3e.bsc + + + + + $(IntDir)BuildLog-$(TargetName).log + + + Disabled + ..;..\cpu\softfloat3e\include;..\cpu\softfloat3e\8086-SSE + _DEBUG;_CONSOLE;INLINE_LEVEL=5;SOFTFLOAT_FAST_DIV32TO16;SOFTFLOAT_FAST_DIV64TO32;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + .\..\obj-debug\softfloat3e\softfloat3e.pch + .\..\obj-debug\softfloat3e\ + .\..\obj-debug\softfloat3e\ + .\..\obj-debug\softfloat3e\ + Level3 + true + OldStyle + CompileAsCpp + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + .\..\obj-debug\softfloat3e.lib + true + + + true + .\..\obj-debug\softfloat3e\softfloat3e.bsc + + + + + $(IntDir)BuildLog-$(TargetName).log + + + MaxSpeed + OnlyExplicitInline + ..;..\cpu\softfloat3e\include;..\cpu\softfloat3e\8086-SSE + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;INLINE_LEVEL=5;SOFTFLOAT_FAST_DIV32TO16;SOFTFLOAT_FAST_DIV64TO32;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + true + .\..\obj-release\softfloat3e\softfloat3e.pch + .\..\obj-release\softfloat3e\ + .\..\obj-release\softfloat3e\ + .\..\obj-release\softfloat3e\ + Level3 + true + FastCall + CompileAsCpp + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + .\..\obj-release\softfloat3e.lib + true + + + true + .\..\obj-release\softfloat3e\softfloat3e.bsc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bochs/build/win32/vs2019-workspace/vs2019/avx.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/avx.vcxproj index 33bec075f2..6d9b8aa6da 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/avx.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/avx.vcxproj @@ -70,12 +70,19 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\ + .\..\obj-debug\avx\ + .\..\obj-debug\avx\ + + + .\..\obj-debug\avx\ .\..\obj-debug\avx\ - - .\..\obj-release\ + .\..\obj-release\avx\ + .\..\obj-release\avx\ + + + .\..\obj-release\avx\ .\..\obj-release\avx\ diff --git a/bochs/build/win32/vs2019-workspace/vs2019/bochs.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/bochs.vcxproj index 2488cfc977..10ce057653 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/bochs.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/bochs.vcxproj @@ -76,6 +76,8 @@ false + .\..\obj-debug\ + .\..\obj-debug\ true false @@ -85,6 +87,8 @@ false + .\..\obj-release\ + .\..\obj-release\ false @@ -251,7 +255,7 @@ winmm.lib;comctl32.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) .\..\obj-release\bochs.exe true - true + false .\..\obj-release\bochs.pdb Console false @@ -340,6 +344,9 @@ {bbff892d-2f57-4561-b2d0-ed4c3a9b7051} false + + {bda1eb83-d53e-41a7-825f-0efdc3d643e3} + {b107c955-4324-4990-bb79-6cbc91c6d12a} false diff --git a/bochs/build/win32/vs2019-workspace/vs2019/bx_debug.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/bx_debug.vcxproj index bc9677055b..9330e29e2b 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/bx_debug.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/bx_debug.vcxproj @@ -70,12 +70,19 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\ + .\..\obj-debug\bx_debug\ + .\..\obj-debug\bx_debug\ + + + .\..\obj-debug\bx_debug\ .\..\obj-debug\bx_debug\ - - .\..\obj-release\ + .\..\obj-release\bx_debug\ + .\..\obj-release\bx_debug\ + + + .\..\obj-release\bx_debug\ .\..\obj-release\bx_debug\ diff --git a/bochs/build/win32/vs2019-workspace/vs2019/bxhub.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/bxhub.vcxproj index a5e40360d9..c7a4cbcd11 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/bxhub.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/bxhub.vcxproj @@ -70,19 +70,23 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\ + .\..\obj-debug\bxhub\ .\..\obj-debug\bxhub\ true + .\..\obj-debug\bxhub\ + .\..\obj-debug\bxhub\ true - .\..\obj-release\ + .\..\obj-release\bxhub\ .\..\obj-release\bxhub\ false + .\..\obj-release\bxhub\ + .\..\obj-release\bxhub\ false @@ -252,6 +256,7 @@ ws2_32.lib;%(AdditionalDependencies) + false true diff --git a/bochs/build/win32/vs2019-workspace/vs2019/bximage.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/bximage.vcxproj index a407449297..6e4db9a02b 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/bximage.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/bximage.vcxproj @@ -70,19 +70,23 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\ + .\..\obj-debug\bximage\ .\..\obj-debug\bximage\ true + .\..\obj-debug\bximage\ + .\..\obj-debug\bximage\ true - .\..\obj-release\ + .\..\obj-release\bximage\ .\..\obj-release\bximage\ false + .\..\obj-release\bximage\ + .\..\obj-release\bximage\ false @@ -248,6 +252,7 @@ false + false true diff --git a/bochs/build/win32/vs2019-workspace/vs2019/cpu.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/cpu.vcxproj index 93da2dc9e3..46ea492f4e 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/cpu.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/cpu.vcxproj @@ -70,12 +70,19 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\ + .\..\obj-debug\cpu\ + .\..\obj-debug\cpu\ + + + .\..\obj-debug\cpu\ .\..\obj-debug\cpu\ - - .\..\obj-release\ + .\..\obj-release\cpu\ + .\..\obj-release\cpu\ + + + .\..\obj-release\cpu\ .\..\obj-release\cpu\ diff --git a/bochs/build/win32/vs2019-workspace/vs2019/cpudb.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/cpudb.vcxproj index 6acdc2693c..170756055a 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/cpudb.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/cpudb.vcxproj @@ -70,12 +70,19 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\ + .\..\obj-debug\cpudb\ + .\..\obj-debug\cpudb\ + + + .\..\obj-debug\cpudb\ .\..\obj-debug\cpudb\ - - .\..\obj-release\ + .\..\obj-release\cpudb\ + .\..\obj-release\cpudb\ + + + .\..\obj-release\cpudb\ .\..\obj-release\cpudb\ diff --git a/bochs/build/win32/vs2019-workspace/vs2019/fpu.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/fpu.vcxproj index 55f7f64818..6e914ab020 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/fpu.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/fpu.vcxproj @@ -70,12 +70,19 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\ + .\..\obj-debug\fpu\ .\..\obj-debug\fpu\ - - .\..\obj-release\ + .\..\obj-release\fpu\ + .\..\obj-release\fpu\ + + + .\..\obj-debug\fpu\ + .\..\obj-debug\fpu\ + + + .\..\obj-release\fpu\ .\..\obj-release\fpu\ @@ -84,8 +91,8 @@ Disabled - ..;..\instrument\stubs;.\stubs;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_WINDOWS;PARANOID;DEBUGGING;NO_ASSEMBLER;USE_WITH_CPU_SIM;%(PreprocessorDefinitions) + ..;..\cpu\..\instrument\stubs;.\stubs;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions) MultiThreadedDebug .\..\obj-debug\fpu\fpu.pch .\..\obj-debug\fpu\ @@ -115,8 +122,8 @@ MaxSpeed OnlyExplicitInline - ..;..\instrument\stubs;stubs;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;PARANOID;DEBUGGING;NO_ASSEMBLER;USE_WITH_CPU_SIM;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..;..\cpu;..\instrument\stubs;stubs;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded @@ -148,8 +155,8 @@ Disabled - ..;..\instrument\stubs;.\stubs;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_WINDOWS;PARANOID;DEBUGGING;NO_ASSEMBLER;USE_WITH_CPU_SIM;%(PreprocessorDefinitions) + ..;..\cpu;..\instrument\stubs;.\stubs;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions) MultiThreadedDebug .\..\obj-debug\fpu\fpu.pch .\..\obj-debug\fpu\ @@ -179,8 +186,8 @@ MaxSpeed OnlyExplicitInline - ..;..\instrument\stubs;stubs;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;PARANOID;DEBUGGING;NO_ASSEMBLER;USE_WITH_CPU_SIM;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..;..\cpu;..\instrument\stubs;stubs;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true @@ -223,20 +230,12 @@ - - - - - - - - - + diff --git a/bochs/build/win32/vs2019-workspace/vs2019/gui.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/gui.vcxproj index fe21ad4938..d48560375d 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/gui.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/gui.vcxproj @@ -69,14 +69,21 @@ <_ProjectFileVersion>12.0.21005.1 + + .\..\obj-debug\gui\ + .\..\obj-debug\gui\ + + + .\..\obj-debug\gui\ + .\..\obj-debug\gui\ + - .\..\obj-release\ + .\..\obj-release\gui\ .\..\obj-release\gui\ - - - .\..\obj-debug\ - .\..\obj-debug\gui\ + + .\..\obj-release\gui\ + .\..\obj-release\gui\ @@ -217,10 +224,12 @@ + + @@ -232,10 +241,13 @@ + + + diff --git a/bochs/build/win32/vs2019-workspace/vs2019/iodev.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/iodev.vcxproj index 2bd8b80283..f31d8333c7 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/iodev.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/iodev.vcxproj @@ -69,14 +69,21 @@ <_ProjectFileVersion>12.0.21005.1 + + .\..\obj-debug\iodev\ + .\..\obj-debug\iodev\ + + + .\..\obj-debug\iodev\ + .\..\obj-debug\iodev\ + - .\..\obj-release\ + .\..\obj-release\iodev\ .\..\obj-release\iodev\ - - - .\..\obj-debug\ - .\..\obj-debug\iodev\ + + .\..\obj-release\iodev\ + .\..\obj-release\iodev\ diff --git a/bochs/build/win32/vs2019-workspace/vs2019/iodev_display.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/iodev_display.vcxproj index ce63fd01c7..3c8466c8b8 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/iodev_display.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/iodev_display.vcxproj @@ -69,14 +69,21 @@ <_ProjectFileVersion>12.0.21005.1 + + .\..\obj-debug\iodev_display\ + .\..\obj-debug\iodev_display\ + + + .\..\obj-debug\iodev_display\ + .\..\obj-debug\iodev_display\ + - .\..\obj-release\ + .\..\obj-release\iodev_display\ .\..\obj-release\iodev_display\ - - - .\..\obj-debug\ - .\..\obj-debug\iodev_display\ + + .\..\obj-release\iodev_display\ + .\..\obj-release\iodev_display\ diff --git a/bochs/build/win32/vs2019-workspace/vs2019/iodev_hdimage.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/iodev_hdimage.vcxproj index 69b805bb0f..36d00b25ef 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/iodev_hdimage.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/iodev_hdimage.vcxproj @@ -69,14 +69,21 @@ <_ProjectFileVersion>12.0.21005.1 + + .\..\obj-debug\iodev_hdimage\ + .\..\obj-debug\iodev_hdimage\ + + + .\..\obj-debug\iodev_hdimage\ + .\..\obj-debug\iodev_hdimage\ + - .\..\obj-release\ + .\..\obj-release\iodev_hdimage\ .\..\obj-release\iodev_hdimage\ - - - .\..\obj-debug\ - .\..\obj-debug\iodev_hdimage\ + + .\..\obj-release\iodev_hdimage\ + .\..\obj-release\iodev_hdimage\ diff --git a/bochs/build/win32/vs2019-workspace/vs2019/iodev_network.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/iodev_network.vcxproj index 98fdc722cd..494a6df81f 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/iodev_network.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/iodev_network.vcxproj @@ -20,6 +20,7 @@ {9EFB2055-35E8-42E9-A274-F4987CB2A655} + 10.0 @@ -69,14 +70,21 @@ <_ProjectFileVersion>12.0.21005.1 + + .\..\obj-debug\iodev_network\ + .\..\obj-debug\iodev_network\ + + + .\..\obj-debug\iodev_network\ + .\..\obj-debug\iodev_network\ + - .\..\obj-release\ + .\..\obj-release\iodev_network\ .\..\obj-release\iodev_network\ - - - .\..\obj-debug\ - .\..\obj-debug\iodev_network\ + + .\..\obj-release\iodev_network\ + .\..\obj-release\iodev_network\ @@ -98,6 +106,7 @@ Level3 true FastCall + stdcpp20 NDEBUG;%(PreprocessorDefinitions) @@ -133,6 +142,7 @@ Level3 true FastCall + stdcpp20 NDEBUG;%(PreprocessorDefinitions) @@ -163,6 +173,7 @@ Level3 true OldStyle + stdcpp20 _DEBUG;%(PreprocessorDefinitions) @@ -193,6 +204,7 @@ Level3 true OldStyle + stdcpp20 _DEBUG;%(PreprocessorDefinitions) @@ -221,14 +233,19 @@ - + + + + + + @@ -238,6 +255,8 @@ + + @@ -249,16 +268,19 @@ + + + + - @@ -266,6 +288,7 @@ + diff --git a/bochs/build/win32/vs2019-workspace/vs2019/iodev_sound.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/iodev_sound.vcxproj index 66c99c2b01..49b9b79f4e 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/iodev_sound.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/iodev_sound.vcxproj @@ -69,14 +69,21 @@ <_ProjectFileVersion>12.0.21005.1 + + .\..\obj-debug\iodev_sound\ + .\..\obj-debug\iodev_sound\ + + + .\..\obj-debug\iodev_sound\ + .\..\obj-debug\iodev_sound\ + - .\..\obj-release\ + .\..\obj-release\iodev_sound\ .\..\obj-release\iodev_sound\ - - - .\..\obj-debug\ - .\..\obj-debug\iodev_sound\ + + .\..\obj-release\iodev_sound\ + .\..\obj-release\iodev_sound\ diff --git a/bochs/build/win32/vs2019-workspace/vs2019/iodev_usb.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/iodev_usb.vcxproj index 3631241acb..f4a773e0bd 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/iodev_usb.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/iodev_usb.vcxproj @@ -69,14 +69,21 @@ <_ProjectFileVersion>12.0.21005.1 + + .\..\obj-debug\iodev_usb\ + .\..\obj-debug\iodev_usb\ + + + .\..\obj-debug\iodev_usb\ + .\..\obj-debug\iodev_usb\ + - .\..\obj-release\ + .\..\obj-release\iodev_usb\ .\..\obj-release\iodev_usb\ - - - .\..\obj-debug\ - .\..\obj-debug\iodev_usb\ + + .\..\obj-release\iodev_usb\ + .\..\obj-release\iodev_usb\ diff --git a/bochs/build/win32/vs2019-workspace/vs2019/memory.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/memory.vcxproj index af9e5f71a5..e16d5584cf 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/memory.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/memory.vcxproj @@ -69,14 +69,21 @@ <_ProjectFileVersion>12.0.21005.1 + + .\..\obj-debug\memory\ + .\..\obj-debug\memory\ + + + .\..\obj-debug\memory\ + .\..\obj-debug\memory\ + - .\..\obj-release\ + .\..\obj-release\memory\ .\..\obj-release\memory\ - - - .\..\obj-debug\ - .\..\obj-debug\memory\ + + .\..\obj-release\memory\ + .\..\obj-release\memory\ diff --git a/bochs/build/win32/vs2019-workspace/vs2019/niclist.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/niclist.vcxproj index 2e86620c13..622a7fe374 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/niclist.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/niclist.vcxproj @@ -70,19 +70,23 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\ + .\..\obj-debug\niclist\ .\..\obj-debug\niclist\ true + .\..\obj-debug\niclist\ + .\..\obj-debug\niclist\ true - .\..\obj-release\ + .\..\obj-release\niclist\ .\..\obj-release\niclist\ false + .\..\obj-release\niclist\ + .\..\obj-release\niclist\ false @@ -247,6 +251,7 @@ false + false true diff --git a/bochs/build/win32/vs2019-workspace/vs2019/softfloat3e.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/softfloat3e.vcxproj index cde1645c29..857cc2647b 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/softfloat3e.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/softfloat3e.vcxproj @@ -68,12 +68,19 @@ <_ProjectFileVersion>12.0.21005.1 - .\..\obj-debug\ + .\..\obj-debug\softfloat3e\ .\..\obj-debug\softfloat3e\ - - .\..\obj-release\ + .\..\obj-release\softfloat3e\ + .\..\obj-release\softfloat3e\ + + + .\..\obj-debug\softfloat3e\ + .\..\obj-debug\softfloat3e\ + + + .\..\obj-release\softfloat3e\ .\..\obj-release\softfloat3e\ @@ -181,7 +188,7 @@ MaxSpeed OnlyExplicitInline ..;..\cpu\softfloat3e\include;..\cpu\softfloat3e\8086-SSE - WIN32;NDEBUG;_LIB;PARANOID;DEBUGGING;NO_ASSEMBLER;USE_WITH_CPU_SIM;_CRT_SECURE_NO_WARNINGS;INLINE_LEVEL=5;SOFTFLOAT_FAST_DIV32TO16;SOFTFLOAT_FAST_DIV64TO32;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;INLINE_LEVEL=5;SOFTFLOAT_FAST_DIV32TO16;SOFTFLOAT_FAST_DIV64TO32;%(PreprocessorDefinitions) true @@ -210,7 +217,7 @@ - + @@ -234,10 +241,12 @@ + + @@ -256,7 +265,6 @@ - @@ -376,10 +384,6 @@ - - - - diff --git a/bochs/build/win32/vs2019-workspace/vs2019/stubs.vcxproj b/bochs/build/win32/vs2019-workspace/vs2019/stubs.vcxproj index 4db2c409ce..f93695d6de 100644 --- a/bochs/build/win32/vs2019-workspace/vs2019/stubs.vcxproj +++ b/bochs/build/win32/vs2019-workspace/vs2019/stubs.vcxproj @@ -69,14 +69,21 @@ <_ProjectFileVersion>12.0.21005.1 + + .\..\obj-debug\stubs\ + .\..\obj-debug\stubs\ + + + .\..\obj-debug\stubs\ + .\..\obj-debug\stubs\ + - .\..\obj-release\ + .\..\obj-release\stubs\ .\..\obj-release\stubs\ - - - .\..\obj-debug\ - .\..\obj-debug\stubs\ + + .\..\obj-release\stubs\ + .\..\obj-release\stubs\ diff --git a/bochs/bx_debug/Makefile.in b/bochs/bx_debug/Makefile.in index b9d1cbca4d..a025f1abf8 100644 --- a/bochs/bx_debug/Makefile.in +++ b/bochs/bx_debug/Makefile.in @@ -121,7 +121,7 @@ dbg_main.o: dbg_main.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h ../param_names.h ../cpu/cpu.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../cpu/decoder/decoder.h \ ../cpu/decoder/features.h ../cpu/decoder/decoder.h \ - ../instrument/stubs/instrument.h ../cpu/i387.h ../cpu/fpu/softfloat.h \ + ../instrument/stubs/instrument.h ../cpu/i387.h \ ../cpu/fpu/tag_w.h ../cpu/fpu/status_w.h ../cpu/fpu/control_w.h \ ../cpu/crregs.h ../cpu/descriptor.h ../cpu/decoder/instr.h \ ../cpu/lazy_flags.h ../cpu/tlb.h ../cpu/icache.h ../cpu/xmm.h \ @@ -133,7 +133,7 @@ linux.o: linux.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h ../cpu/cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ ../cpu/decoder/decoder.h ../instrument/stubs/instrument.h ../cpu/i387.h \ - ../cpu/fpu/softfloat.h ../cpu/fpu/tag_w.h ../cpu/fpu/status_w.h \ + ../cpu/fpu/tag_w.h ../cpu/fpu/status_w.h \ ../cpu/fpu/control_w.h ../cpu/crregs.h ../cpu/descriptor.h \ ../cpu/decoder/instr.h ../cpu/lazy_flags.h ../cpu/tlb.h ../cpu/icache.h \ ../cpu/xmm.h ../cpu/vmx.h ../cpu/access.h syscalls-linux.h @@ -142,8 +142,8 @@ parser.o: parser.@CPP_SUFFIX@ debug.h ../config.h ../osdep.h \ symbols.o: symbols.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h ../cpu/cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ - ../cpu/decoder/decoder.h ../instrument/stubs/instrument.h ../cpu/i387.h \ - ../cpu/fpu/softfloat.h ../cpu/fpu/tag_w.h ../cpu/fpu/status_w.h \ + ../instrument/stubs/instrument.h ../cpu/i387.h \ + ../cpu/fpu/tag_w.h ../cpu/fpu/status_w.h \ ../cpu/fpu/control_w.h ../cpu/crregs.h ../cpu/descriptor.h \ ../cpu/decoder/instr.h ../cpu/lazy_flags.h ../cpu/tlb.h ../cpu/icache.h \ ../cpu/xmm.h ../cpu/vmx.h ../cpu/access.h diff --git a/bochs/bx_debug/dbg_main.cc b/bochs/bx_debug/dbg_main.cc index a85fba1e1a..c516983b61 100644 --- a/bochs/bx_debug/dbg_main.cc +++ b/bochs/bx_debug/dbg_main.cc @@ -875,7 +875,7 @@ void bx_dbg_print_sse_state(void) void bx_dbg_print_avx_state(unsigned cpu, unsigned vlen) { #if BX_SUPPORT_AVX - char param_name[20]; + char param_name[24]; if (BX_CPU(cpu)->is_cpu_extension_supported(BX_ISA_AVX)) { bx_dbg_print_mxcsr_state(); diff --git a/bochs/bx_debug/debug.h b/bochs/bx_debug/debug.h index 314a0f7bd9..c6ed9e3d62 100644 --- a/bochs/bx_debug/debug.h +++ b/bochs/bx_debug/debug.h @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2016 The Bochs Project +// Copyright (C) 2001-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -38,7 +38,7 @@ Bit32u crc32(const Bit8u *buf, int len); extern Bit32u dbg_cpu; -void dbg_printf(const char *fmt, ...); +BOCHSAPI_MSVCONLY void dbg_printf(const char *fmt, ...); typedef enum { @@ -69,7 +69,7 @@ extern "C" { }; // register function for 'info device' command -bool bx_dbg_register_debug_info(const char *devname, void *dev); +BOCHSAPI_MSVCONLY bool bx_dbg_register_debug_info(const char *devname, void *dev); #define EMPTY_ARG (-1) @@ -228,9 +228,9 @@ typedef enum { #define BX_DBG_PENDING_DMA 1 #define BX_DBG_PENDING_IRQ 2 -void bx_debug_break(void); +BOCHSAPI_MSVCONLY void bx_debug_break(void); -void bx_dbg_exit(int code); +BOCHSAPI_MSVCONLY void bx_dbg_exit(int code); #if BX_DBG_EXTENSIONS int bx_dbg_extensions(char *command); #else @@ -344,7 +344,7 @@ extern unsigned num_write_watchpoints; extern unsigned num_read_watchpoints; extern bx_watchpoint write_watchpoint[BX_DBG_MAX_WATCHPONTS]; extern bx_watchpoint read_watchpoint[BX_DBG_MAX_WATCHPONTS]; -extern bx_guard_t bx_guard; +BOCHSAPI_MSVCONLY extern bx_guard_t bx_guard; #define IS_CODE_32(code_32_64) ((code_32_64 & 1) != 0) #define IS_CODE_64(code_32_64) ((code_32_64 & 2) != 0) @@ -368,8 +368,8 @@ typedef struct { Bit16u limit; } bx_dbg_global_sreg_t; -void bx_dbg_dma_report(bx_phy_address addr, unsigned len, unsigned what, Bit32u val); -void bx_dbg_iac_report(unsigned vector, unsigned irq); +BOCHSAPI_MSVCONLY void bx_dbg_dma_report(bx_phy_address addr, unsigned len, unsigned what, Bit32u val); +BOCHSAPI_MSVCONLY void bx_dbg_iac_report(unsigned vector, unsigned irq); void bx_dbg_a20_report(unsigned val); void bx_dbg_io_report(Bit32u port, unsigned size, unsigned op, Bit32u val); void bx_dbg_disassemble_current(int which_cpu, int print_time); diff --git a/bochs/config.cc b/bochs/config.cc index 55c84f06f3..5bc8eb484e 100644 --- a/bochs/config.cc +++ b/bochs/config.cc @@ -31,9 +31,6 @@ #if BX_SUPPORT_PCIUSB #include "iodev/usb/usb_common.h" #endif -#if BX_USE_WIN32USBDEBUG -#include "gui/win32usb.h" -#endif #include "param_names.h" #include @@ -243,31 +240,39 @@ void bx_init_usb_options(const char *usb_name, const char *pname, int maxports, sprintf(label, "Enable %s emulation", usb_name); sprintf(descr, "Enables the %s emulation", usb_name); bx_param_bool_c *enabled = new bx_param_bool_c(menu, "enabled", label, descr, 1); - - // ehci companion type - static const char *ehci_comp_type[] = { "uhci", "ohci", NULL }; - new bx_param_enum_c(menu, - "companion", "Companion Type", - "Select Companion type to emulate", - ehci_comp_type, - 0, 0 - ); - - // xhci host controller type and number of ports - static const char *xhci_model_names[] = { "uPD720202", "uPD720201", NULL }; - new bx_param_enum_c(menu, - "model", "HC model", - "Select Host Controller to emulate", - xhci_model_names, - 0, 0 - ); - new bx_param_num_c(menu, - "n_ports", "Number of ports", - "Set the number of ports for this controller", - -1, 10, - -1, 0 // -1 as a default so that we can tell if this parameter was given - ); - + +#if BX_SUPPORT_USB_EHCI + if (!strcmp(usb_name, "EHCI")) { + // ehci companion type + static const char *ehci_comp_type[] = { "uhci", "ohci", NULL }; + new bx_param_enum_c(menu, + "companion", "Companion Type", + "Select Companion type to emulate", + ehci_comp_type, + 0, 0 + ); + } +#endif + +#if BX_SUPPORT_USB_XHCI + if (!strcmp(usb_name, "xHCI")) { + // xhci host controller type and number of ports + static const char *xhci_model_names[] = { "uPD720202", "uPD720201", NULL }; + new bx_param_enum_c(menu, + "model", "HC model", + "Select Host Controller to emulate", + xhci_model_names, + 0, 0 + ); + new bx_param_num_c(menu, + "n_ports", "Number of ports", + "Set the number of ports for this controller", + -1, 10, + -1, 0 // -1 as a default so that we can tell if this parameter was given + ); + } +#endif + deplist = new bx_list_c(NULL); for (Bit8u i = 0; i < maxports; i++) { sprintf(name, "port%u", i+1); @@ -312,6 +317,51 @@ void bx_init_usb_options(const char *usb_name, const char *pname, int maxports, } enabled->set_dependent_list(deplist); } + +#if BX_USB_DEBUGGER +void bx_init_usb_debug_options(bx_list_c *base) +{ + static const char *usb_debug_type[] = { "none", "uhci", "ohci", "ehci", "xhci", NULL }; + bx_list_c *usb_debug = new bx_list_c(base, "usb_debug", "USB Debug Options"); + bx_param_enum_c *type = new bx_param_enum_c(usb_debug, + "type", "HC type", + "Select Host Controller type", + usb_debug_type, USB_DEBUG_NONE, USB_DEBUG_NONE); + new bx_param_bool_c(usb_debug, + "reset", "Trigger on reset", + "Trigger on Reset", + 0 + ); + new bx_param_bool_c(usb_debug, + "enable", "Trigger on enable", + "Trigger on Enable", + 0 + ); + new bx_param_num_c(usb_debug, + "start_frame", "Trigger on start of frame", + "Trigger on start of frame", + BX_USB_DEBUG_SOF_NONE, BX_USB_DEBUG_SOF_TRIGGER, + BX_USB_DEBUG_SOF_NONE + ); + new bx_param_bool_c(usb_debug, + "doorbell", "Trigger on doorbell", + "Trigger on Doorbell", + 0 + ); + new bx_param_bool_c(usb_debug, + "event", "Trigger on event", + "Trigger on Event", + 0 + ); + new bx_param_bool_c(usb_debug, + "non_exist", "Trigger on non exist", + "Trigger on write to non-existant port", + 0 + ); + type->set_dependent_list(usb_debug->clone(), 1); + type->set_dependent_bitmap(USB_DEBUG_NONE, 0); +} +#endif #endif void bx_plugin_ctrl_init() @@ -914,7 +964,7 @@ void bx_init_options() "Pathname of VGA ROM image to load", "", BX_PATHNAME_LEN); path->set_format("Name of VGA BIOS image: %s"); - sprintf(name, "%s" DIRECTORY_SEPARATOR "VGABIOS-lgpl-latest", get_builtin_variable("BXSHARE")); + sprintf(name, "%s" DIRECTORY_SEPARATOR "VGABIOS-lgpl-latest.bin", get_builtin_variable("BXSHARE")); path->set_initial_val(name); vgarom->set_options(vgarom->SERIES_ASK); @@ -1664,50 +1714,12 @@ void bx_init_options() ports->set_options(ports->USE_TAB_WINDOW | ports->SHOW_PARENT); #if BX_SUPPORT_PCIUSB bx_usbdev_ctl.init(); +#if BX_USB_DEBUGGER + bx_init_usb_debug_options(ports); +#endif #endif // parallel / serial / USB options initialized in the device plugin code - // usb debugging -#if BX_USE_WIN32USBDEBUG - static const char *usb_debug_type[] = { "none", "uhci", "ohci", "ehci", "xhci", NULL }; - bx_list_c *usb_debug = new bx_list_c(root_param, "usb_debug", "USB Debug Options"); - new bx_param_enum_c(usb_debug, - "type", "HC type", - "Select Host Controller type", - usb_debug_type, 0, 0); - new bx_param_bool_c(usb_debug, - "reset", "trigger on reset", - "Trigger on Reset", - 0 - ); - new bx_param_bool_c(usb_debug, - "enable", "trigger on enable", - "Trigger on Enable", - 0 - ); - new bx_param_num_c(usb_debug, - "start_frame", "trigger on start of frame", - "Trigger on start of frame", - BX_USB_DEBUG_SOF_NONE, BX_USB_DEBUG_SOF_TRIGGER, - BX_USB_DEBUG_SOF_NONE - ); - new bx_param_bool_c(usb_debug, - "doorbell", "trigger on doorbell", - "Trigger on Doorbell", - 0 - ); - new bx_param_bool_c(usb_debug, - "event", "trigger on event", - "Trigger on Event", - 0 - ); - new bx_param_bool_c(usb_debug, - "non_exist", "trigger on non exist", - "Trigger on write to non-existant port", - 0 - ); -#endif - #if BX_NETWORKING // network subtree bx_list_c *network = new bx_list_c(root_param, "network", "Network Configuration"); @@ -2097,7 +2109,11 @@ const char *get_builtin_variable(const char *varname) if (code == ERROR_SUCCESS) { data[0] = 0; size = MAX_PATH; - if (RegQueryValueEx(hkey, "", NULL, (LPDWORD)&type, (LPBYTE)data, + if (RegQueryValueEx(hkey, "BX_SHARE_PATH", NULL, (LPDWORD)&type, (LPBYTE)data, + (LPDWORD)&size) == ERROR_SUCCESS) { + RegCloseKey(hkey); + return data; + } else if (RegQueryValueEx(hkey, "", NULL, (LPDWORD)&type, (LPBYTE)data, (LPDWORD)&size) == ERROR_SUCCESS) { RegCloseKey(hkey); return data; @@ -2274,34 +2290,6 @@ int get_floppy_type_from_image(const char *filename) } } -#if BX_USE_WIN32USBDEBUG -static Bit32s parse_usb_debug_options(const char *context, int num_params, char *params[]) -{ - for (int i=1; iget_param_bool(BXPN_USB_DEBUG_RESET)->set(1); - } else if (!strcmp(params[i], "enable")) { - SIM->get_param_bool(BXPN_USB_DEBUG_ENABLE)->set(1); - } else if (!strcmp(params[i], "start_frame")) { - SIM->get_param_num(BXPN_USB_DEBUG_START_FRAME)->set(BX_USB_DEBUG_SOF_SET); - } else if (!strcmp(params[i], "doorbell")) { - SIM->get_param_bool(BXPN_USB_DEBUG_DOORBELL)->set(1); - } else if (!strcmp(params[i], "event")) { - SIM->get_param_bool(BXPN_USB_DEBUG_EVENT)->set(1); - } else if (!strcmp(params[i], "non_exist")) { - SIM->get_param_bool(BXPN_USB_DEBUG_NON_EXIST)->set(1); - } else { - PARSE_ERR(("%s: %s directive malformed.", context, params[i])); - return -1; - } - } - - return 0; -} -#endif - static Bit32s parse_log_options(const char *context, int num_params, char *params[]) { int level, action, i; @@ -3396,27 +3384,28 @@ static int parse_line_formatted(const char *context, int num_params, char *param #else PARSE_WARN(("%s: Bochs is not compiled with iodebug support", context)); #endif -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER } else if (!strcmp(params[0], "usb_debug")) { if (num_params < 2) { PARSE_ERR(("%s: usb_debug directive malformed.", context)); } // check that we haven't already defined the type // we can only debug one controller at a time - Bit32s type = SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get(); - if (type > 0) { + bx_param_enum_c *type = SIM->get_param_enum(BXPN_USB_DEBUG_TYPE); + if (type->get() != USB_DEBUG_NONE) { PARSE_ERR(("%s: usb_debug: type='%s' previously defined.", context, - SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get_choice(type))); + type->get_selected())); } - if (parse_usb_debug_options(context, num_params, params) < 0) { - return -1; + for (i=1; iget_param(BXPN_USB_DEBUG)) < 0) { + PARSE_ERR(("%s: usb_debug directive malformed.", context)); + } } // we currently only support the xHCI controller type, so give // an error if it is something else. - type = SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get(); - if ((type == USB_DEBUG_OHCI) || (type == USB_DEBUG_EHCI)) { + if ((type->get() == USB_DEBUG_OHCI) || (type->get() == USB_DEBUG_EHCI)) { PARSE_ERR(("%s: usb_debug: type='%s' not supported yet.", context, - SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get_choice(type))); + type->get_selected())); } #endif } else if (!strcmp(params[0], "load32bitOSImage")) { @@ -3796,6 +3785,9 @@ int bx_write_configuration(const char *rc, int overwrite) bx_write_param_list(fp, (bx_list_c*) SIM->get_param(BXPN_MOUSE), NULL, 0); bx_write_param_list(fp, (bx_list_c*) SIM->get_param(BXPN_SOUNDLOW),"sound", 0); SIM->save_addon_options(fp); +#if BX_USB_DEBUGGER + bx_write_param_list(fp, (bx_list_c*) SIM->get_param(BXPN_USB_DEBUG), "usb_debug", 0); +#endif fclose(fp); return 0; } diff --git a/bochs/config.h.in b/bochs/config.h.in index 853c4d275a..257d7b4c87 100644 --- a/bochs/config.h.in +++ b/bochs/config.h.in @@ -1,5 +1,5 @@ // -// Copyright (C) 2001-2021 The Bochs Project +// Copyright (C) 2001-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -317,6 +317,8 @@ #define WX_MSW_UNICODE 0 // set to GDK major version for wxGTK #define WX_GDK_VERSION 0 +// set to GTK major version for GTK debugger +#define BX_HAVE_GTK_VERSION 0 // A certain functions must NOT be fastcall even if compiled with fastcall // option, and those are callbacks from Windows which are defined either @@ -808,14 +810,12 @@ typedef Bit32u bx_phy_address; #error To enable USB, you must also enable PCI #endif -#if (BX_SUPPORT_USB_EHCI && !BX_SUPPORT_USB_UHCI) - #error To enable EHCI, you must also enable UHCI +#if (BX_SUPPORT_USB_EHCI && !BX_SUPPORT_USB_UHCI && !BX_SUPPORT_USB_OHCI) + #error To enable EHCI, you must also enable UHCI or OHCI #endif -#ifdef WIN32 -// set to 1 to include the USB DEBUG CONFIG Interface -#define BX_USE_WIN32USBDEBUG 0 -#endif +// set to 1 to include the USB debugger interface +#define BX_USB_DEBUGGER 0 // MS bus mouse support #define BX_SUPPORT_BUSMOUSE 0 @@ -859,6 +859,8 @@ typedef Bit32u bx_phy_address; #define BX_NETMOD_SLIRP 0 #define BX_NETMOD_SOCKET 0 +#define BX_HAVE_LIBSLIRP 0 + // Soundcard and gameport support #define BX_SUPPORT_SB16 0 #define BX_SUPPORT_ES1370 0 @@ -866,11 +868,12 @@ typedef Bit32u bx_phy_address; #define BX_SUPPORT_SOUNDLOW 0 // which sound lowlevel modules will be enabled -#define BX_HAVE_SOUND_ALSA 0 -#define BX_HAVE_SOUND_OSS 0 -#define BX_HAVE_SOUND_OSX 0 -#define BX_HAVE_SOUND_SDL 0 -#define BX_HAVE_SOUND_WIN 0 +#define BX_HAVE_SOUND_ALSA 0 +#define BX_HAVE_SOUND_OSS 0 +#define BX_HAVE_SOUND_OSX 0 +#define BX_HAVE_SOUND_PULSE 0 +#define BX_HAVE_SOUND_SDL 0 +#define BX_HAVE_SOUND_WIN 0 #if BX_SUPPORT_SOUNDLOW // Determines which sound lowlevel driver is to be used as the default. @@ -878,6 +881,7 @@ typedef Bit32u bx_phy_address; // alsa Output for Linux with ALSA PCM and sequencer interface // oss Output for Linux, to /dev/dsp and /dev/midi00 // osx Output for MacOSX midi and wave device +// pulse Wave output with PulseAudio simple API // sdl Wave output with SDL/SDL2 // win Output for Windows midi and wave mappers // file Wave and midi output to file diff --git a/bochs/configure b/bochs/configure index d3422e7406..4bcfb5c317 100755 --- a/bochs/configure +++ b/bochs/configure @@ -815,7 +815,6 @@ EXT_MSVC_DLL_RULES PLUGIN_TARGET_2 PLUGIN_TARGET PLUGIN_LIB -PLUGIN_VAR IODEV_EXT_PLUGIN_OBJS IODEV_EXT_NON_PLUGIN_OBJS IODEV_PLUGIN_OBJS @@ -903,6 +902,7 @@ BUSM_OBJS GAME_OBJS SOUNDHW_DLL_TARGETS SDL_SOUND_LINK_OPTS +PULSE_SOUND_LINK_OPTS ALSA_SOUND_LINK_OPTS SOUNDLOW_OBJS SOUNDHW_OBJS @@ -911,6 +911,9 @@ CDROM_OBJS DISPLAY_DLL_TARGETS DISPLAY_EXTRA_OBJS DISPLAY_OBJS +SLIRP_LINK_OPTS +SLIRP_OBJS2 +SLIRP_OBJS NETDEV_DLL_TARGETS NETLOW_OBJS NETDEV_OBJS @@ -952,7 +955,7 @@ X_PRE_LIBS X_CFLAGS CPP XMKMF -PKGCONFIG +PKG_CONFIG LIBADD_DL LIBTOOL ac_ct_F77 @@ -1088,10 +1091,11 @@ enable_usb enable_usb_ohci enable_usb_ehci enable_usb_xhci -enable_win32usbdbg +enable_usb_debugger enable_ne2000 enable_pnic enable_e1000 +enable_using_libslirp enable_raw_serial enable_clgd54xx enable_voodoo @@ -1130,6 +1134,7 @@ CCC CXXCPP F77 FFLAGS +PKG_CONFIG XMKMF CPP' @@ -1830,11 +1835,12 @@ Optional Features: --enable-usb-ohci enable USB OHCI support (no) --enable-usb-ehci enable USB EHCI support (no) --enable-usb-xhci enable USB xHCI support (no) - --enable-win32usbdbg compile in support for Bochs Win32 USB debugger - (yes, if debugger is on and USB is on) + --enable-usb-debugger compile in support for Bochs USB debugger (yes, if + debugger is on and USB is on) --enable-ne2000 enable NE2000 support (no) --enable-pnic enable PCI pseudo NIC support (no) --enable-e1000 enable Intel(R) Gigabit Ethernet support (no) + --enable-using-libslirp enable using libslirp instead of builtin slirp (no) --enable-raw-serial use raw serial port access (no - incomplete) --enable-clgd54xx enable CLGD54XX emulation (no) --enable-voodoo enable 3dfx Voodoo Graphics emulation (no) @@ -1883,6 +1889,7 @@ Some influential environment variables: CXXCPP C++ preprocessor F77 Fortran 77 compiler command FFLAGS Fortran 77 compiler flags + PKG_CONFIG path to pkg-config utility XMKMF Path to xmkmf, Makefile generator for X Window System CPP C preprocessor @@ -3805,8 +3812,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" -ac_config_headers="$ac_config_headers ltdlconf.h" - VERSION="2.8.devel" VER_MAJOR=2 @@ -6170,7 +6175,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6173 "configure"' > conftest.$ac_ext + echo '#line 6178 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -6267,25 +6272,14 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main (void) -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO" + if ac_fn_c_try_link "$LINENO" then : - lt_cv_cc_needs_belf=yes + else $as_nop - lt_cv_cc_needs_belf=no + lt_cv_cc_needs_belf=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext + conftest$ac_exeext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -7667,11 +7661,11 @@ else $as_nop -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7670: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7664: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7674: \$? = $ac_status" >&5 + echo "$as_me:7668: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -7901,11 +7895,11 @@ else $as_nop -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7904: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7898: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7908: \$? = $ac_status" >&5 + echo "$as_me:7902: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -7969,11 +7963,11 @@ else $as_nop -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7972: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7966: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7976: \$? = $ac_status" >&5 + echo "$as_me:7970: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -9764,7 +9758,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:11974: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:11984: \$? = $ac_status" >&5 + echo "$as_me:11978: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -12045,11 +12039,11 @@ else $as_nop -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12048: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12042: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12052: \$? = $ac_status" >&5 + echo "$as_me:12046: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -13068,7 +13062,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:13980: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:13990: \$? = $ac_status" >&5 + echo "$as_me:13984: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -14051,11 +14045,11 @@ else $as_nop -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14054: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14048: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:14058: \$? = $ac_status" >&5 + echo "$as_me:14052: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -16019,11 +16013,11 @@ else $as_nop -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16022: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16016: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16026: \$? = $ac_status" >&5 + echo "$as_me:16020: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -16253,11 +16247,11 @@ else $as_nop -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16256: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16250: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16260: \$? = $ac_status" >&5 + echo "$as_me:16254: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -16321,11 +16315,11 @@ else $as_nop -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16324: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16318: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:16328: \$? = $ac_status" >&5 + echo "$as_me:16322: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -18116,7 +18110,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <>confdefs.h fi -# Autoupdate added the next two lines to ensure that your configure -# script's behavior did not change. They are probably safe to remove. - -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -printf %s "checking for egrep... " >&6; } -if test ${ac_cv_path_EGREP+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - if test -z "$EGREP"; then - ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_prog in egrep - do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_EGREP" || continue -# Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - printf %s 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - printf "%s\n" 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_EGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_EGREP=$EGREP -fi - - fi -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -printf "%s\n" "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - - ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`printf "%s\n" "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` @@ -19981,7 +19898,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +printf "%s\n" "$PKG_CONFIG" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_PKGCONFIG+y} +if test ${ac_cv_path_ac_pt_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else $as_nop - case $PKGCONFIG in + case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) - ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path. + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -20427,7 +20395,7 @@ do esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_PKGCONFIG="$as_dir$ac_word$ac_exec_ext" + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi @@ -20435,21 +20403,49 @@ done done IFS=$as_save_IFS - test -z "$ac_cv_path_PKGCONFIG" && ac_cv_path_PKGCONFIG="not_found" ;; esac fi -PKGCONFIG=$ac_cv_path_PKGCONFIG -if test -n "$PKGCONFIG"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5 -printf "%s\n" "$PKGCONFIG" >&6; } +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + PKG_CONFIG="" + fi -if test "$PKGCONFIG" = not_found; then +fi +if test "x$PKG_CONFIG" = x; then ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -22814,8 +22810,7 @@ fi printf "%s\n" "#define BX_HAVE_LTDL 1" >>confdefs.h else - PLUGIN_VAR="ltdl.o" - PLUGIN_LIB="ltdl.o" + as_fn_error $? "Plugin support requires libltdl installed on your system" "$LINENO" 5 fi fi PLUGIN_TARGET=bochs_plugins @@ -24586,6 +24581,7 @@ fi use_usb=0 +use_usb_uhci=0 USBHC_OBJS='' UHCICORE_OBJ='' USBHC_DLL_TARGETS='' @@ -24603,6 +24599,7 @@ printf "%s\n" "yes" >&6; } UHCICORE_OBJ="uhci_core.o" USBHC_DLL_TARGETS="bx_usb_uhci.dll" use_usb=1 + use_usb_uhci=1 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } @@ -24620,6 +24617,7 @@ printf "%s\n" "no" >&6; } fi +use_usb_ohci=0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for USB OHCI support" >&5 printf %s "checking for USB OHCI support... " >&6; } # Check whether --enable-usb-ohci was given. @@ -24633,6 +24631,7 @@ printf "%s\n" "yes" >&6; } USBHC_OBJS="$USBHC_OBJS usb_ohci.o" USBHC_DLL_TARGETS="$USBHC_DLL_TARGETS bx_usb_ohci.dll" use_usb=1 + use_usb_ohci=1 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } @@ -24650,6 +24649,7 @@ printf "%s\n" "no" >&6; } fi +use_usb_ehci=0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for USB EHCI support" >&5 printf %s "checking for USB EHCI support... " >&6; } # Check whether --enable-usb-ehci was given. @@ -24663,6 +24663,7 @@ printf "%s\n" "yes" >&6; } USBHC_OBJS="$USBHC_OBJS usb_ehci.o" USBHC_DLL_TARGETS="$USBHC_DLL_TARGETS bx_usb_ehci.dll" use_usb=1 + use_usb_ehci=1 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } @@ -24680,6 +24681,7 @@ printf "%s\n" "no" >&6; } fi +use_usb_xhci=0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for USB xHCI support" >&5 printf %s "checking for USB xHCI support... " >&6; } # Check whether --enable-usb-xhci was given. @@ -24693,6 +24695,7 @@ printf "%s\n" "yes" >&6; } USBHC_OBJS="$USBHC_OBJS usb_xhci.o" USBHC_DLL_TARGETS="$USBHC_DLL_TARGETS bx_usb_xhci.dll" use_usb=1 + use_usb_xhci=1 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } @@ -24711,6 +24714,11 @@ fi if test "$use_usb" = 1; then + if test "$use_usb_ehci" = 1; then + if test "$use_usb_uhci" = 0 -a "$use_usb_ohci" = 0; then + as_fn_error $? "To configure USB EHCI, you must also enable UHCI or OHCI" "$LINENO" 5 + fi + fi if test "$pci" != "1"; then as_fn_error $? "USB requires PCI support" "$LINENO" 5 fi @@ -24721,19 +24729,19 @@ fi usb_debugger=0 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking enable Bochs Win32 USB debugger" >&5 -printf %s "checking enable Bochs Win32 USB debugger... " >&6; } -# Check whether --enable-win32usbdbg was given. -if test ${enable_win32usbdbg+y} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking enable Bochs USB debugger" >&5 +printf %s "checking enable Bochs USB debugger... " >&6; } +# Check whether --enable-usb-debugger was given. +if test ${enable_usb_debugger+y} then : - enableval=$enable_win32usbdbg; if test "$enableval" = yes; then + enableval=$enable_usb_debugger; if test "$enableval" = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } usb_debugger=1 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - printf "%s\n" "#define BX_USE_WIN32USBDEBUG 0" >>confdefs.h + printf "%s\n" "#define BX_USB_DEBUGGER 0" >>confdefs.h usb_debugger=0 fi @@ -24746,7 +24754,7 @@ printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - printf "%s\n" "#define BX_USE_WIN32USBDEBUG 0" >>confdefs.h + printf "%s\n" "#define BX_USB_DEBUGGER 0" >>confdefs.h usb_debugger=0 fi @@ -24852,28 +24860,68 @@ fi NETLOW_OBJS='' +SLIRP_OBJS='' +SLIRP_OBJS2='' +SLIRP_LINK_OPTS='' if test "$networking" = yes; then NETLOW_OBJS='eth_null.o eth_vnet.o' ethernet_modules='null vnet' can_compile_slirp=0 - case "$target" in - *-cygwin* | *-mingw32* | *-msys) - can_compile_slirp=1 - DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -liphlpapi" - ;; - *-pc-windows* | *-pc-winnt*) - can_compile_slirp=1 - DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS iphlpapi.lib" - ;; - *) - ac_fn_c_check_header_compile "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for slirp networking support" >&5 +printf %s "checking for slirp networking support... " >&6; } + # Check whether --enable-using-libslirp was given. +if test ${enable_using_libslirp+y} +then : + enableval=$enable_using_libslirp; if test "$enableval" = yes; then + if test "x$PKG_CONFIG" != x; then + $PKG_CONFIG --exists slirp + if test x$? = x0; then + can_compile_slirp=1 + if test "$bx_plugins" = 1; then + SLIRP_LINK_OPTS="`$PKG_CONFIG --libs slirp`" + else + DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS `$PKG_CONFIG --libs slirp`" + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: libslirp" >&5 +printf "%s\n" "libslirp" >&6; } + printf "%s\n" "#define BX_HAVE_LIBSLIRP 1" >>confdefs.h + + fi + fi + fi +fi + + if test $can_compile_slirp = 0; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: builtin" >&5 +printf "%s\n" "builtin" >&6; } + case "$target" in + *-cygwin* | *-mingw32* | *-msys) + can_compile_slirp=1 + DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -liphlpapi" + SLIRP_OBJS='$(SLIRP_OBJS)' + ;; + *-pc-windows* | *-pc-winnt*) + can_compile_slirp=1 + DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS iphlpapi.lib" + SLIRP_OBJS='$(SLIRP_OBJS)' + ;; + *) + ac_fn_c_check_header_compile "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default" if test "x$ac_cv_header_netinet_in_h" = xyes then : - can_compile_slirp=1 + can_compile_slirp=1 fi - ;; - esac + if test $can_compile_slirp = 1; then + if test "$bx_plugins" = 1; then + SLIRP_OBJS2='$(SLIRP_OBJS:.o=.lo)' + else + SLIRP_OBJS='$(SLIRP_OBJS)' + fi + fi + ;; + esac + fi if test $can_compile_slirp = 1; then NETLOW_OBJS="$NETLOW_OBJS eth_slirp.o" ethernet_modules="$ethernet_modules slirp" @@ -25007,6 +25055,9 @@ fi + + + if test "$bx_plugins" = 0; then case $target in *-pc-windows*) @@ -25360,6 +25411,22 @@ fi fi fi + if test "$cross_configure" = 0 -a "$DEFAULT_GUI" != win32; then + if test "x$PKG_CONFIG" != x; then + $PKG_CONFIG --exists libpulse-simple + if test x$? = x0; then + SOUNDLOW_OBJS="$SOUNDLOW_OBJS soundpulse.o" + soundlow_drivers="$soundlow_drivers pulse" + printf "%s\n" "#define BX_HAVE_SOUND_PULSE 1" >>confdefs.h + + if test "$bx_plugins" = 1; then + PULSE_SOUND_LINK_OPTS="$PULSE_SOUND_LINK_OPTS `$PKG_CONFIG --libs libpulse-simple`" + else + DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS `$PKG_CONFIG --libs libpulse-simple`" + fi + fi + fi + fi if test "$MSVC_TARGET" = 0; then ac_fn_c_check_header_compile "$LINENO" "samplerate.h" "ac_cv_header_samplerate_h" "$ac_includes_default" if test "x$ac_cv_header_samplerate_h" = xyes @@ -25408,6 +25475,7 @@ fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for standard PC gameport support" >&5 printf %s "checking for standard PC gameport support... " >&6; } # Check whether --enable-gameport was given. @@ -25952,9 +26020,9 @@ then : fi - if test "$PKGCONFIG" != not_found; then - X_CFLAGS="`pkg-config --cflags x11`" - X_LIBS="`pkg-config --libs x11` $XPM_LIB $XRANDR_LIB" + if test "x$PKG_CONFIG" != x; then + X_CFLAGS="`$PKG_CONFIG --cflags x11`" + X_LIBS="`$PKG_CONFIG --libs x11` $XPM_LIB $XRANDR_LIB" else X_LIBS="$X_LIBS -lX11 $XPM_LIB $XRANDR_LIB" fi @@ -25966,7 +26034,7 @@ fi GUI_CXXFLAGS="$GUI_CXXFLAGS \$(X_CFLAGS)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_X)" # The enhanced X debugger depends on GTK2 - if test "$gui_debugger" = 1; then + if test "$gui_debugger" = 1 -o "$usb_debugger" = 1; then needs_gtk2=1 fi use_gui_console=1 @@ -25992,8 +26060,10 @@ if test "$with_sdl" = yes; then NONPLUGIN_GUI_LINK_OPTS="`sdl-config --libs`" fi # The enhanced X debugger depends on GTK2 - if test "$gui_debugger" = 1 -a "$DEFAULT_GUI" != win32; then - needs_gtk2=1 + if test "$DEFAULT_GUI" != win32; then + if test "$gui_debugger" = 1 -o "$usb_debugger" = 1; then + needs_gtk2=1 + fi fi if test "$with_win32" != yes -a "$with_wx" != yes; then case $target in @@ -26028,8 +26098,10 @@ if test "$with_sdl2" = yes; then NONPLUGIN_GUI_LINK_OPTS="`sdl2-config --libs`" fi # The enhanced X debugger depends on GTK2 - if test "$gui_debugger" = 1 -a "$DEFAULT_GUI" != win32; then - needs_gtk2=1 + if test "$DEFAULT_GUI" != win32; then + if test "$gui_debugger" = 1 -o "$usb_debugger" = 1; then + needs_gtk2=1 + fi fi if test "$with_win32" != yes -a "$with_wx" != yes; then case $target in @@ -26057,11 +26129,11 @@ if test "$with_rfb" = yes; then fi if test "$with_vncsrv" = yes; then - if test "$PKGCONFIG" != not_found; then - pkg-config --exists libvncserver + if test "$PKG_CONFIG" != not_found; then + $PKG_CONFIG --exists libvncserver if test x$? = x0; then - VNCSRV_CXXFLAGS="`pkg-config --cflags libvncserver`" - GUI_LINK_OPTS_VNCSRV="`pkg-config --libs libvncserver`" + VNCSRV_CXXFLAGS="`$PKG_CONFIG --cflags libvncserver`" + GUI_LINK_OPTS_VNCSRV="`$PKG_CONFIG --libs libvncserver`" fi else # Extract the first word of " libvncserver-config --version ", so it can be a program name with args. @@ -26222,14 +26294,14 @@ if test "$with_wx" = yes; then WX_CFLAGS="`$WX_CONFIG --cflags`" WX_CXXFLAGS="`$WX_CONFIG --cxxflags`" if test "$wx_needs_gdk_version" = 2; then - GDK_CFLAGS="`pkg-config --cflags gdk-2.0`" + GDK_CFLAGS="`$PKG_CONFIG --cflags gdk-2.0`" WX_CFLAGS="$WX_CFLAGS $GDK_CFLAGS" WX_CXXFLAGS="$WX_CXXFLAGS $GDK_CFLAGS" printf "%s\n" "#define WX_GDK_VERSION 2" >>confdefs.h fi if test "$wx_needs_gdk_version" = 3; then - GDK_CFLAGS="`pkg-config --cflags gdk-3.0`" + GDK_CFLAGS="`$PKG_CONFIG --cflags gdk-3.0`" WX_CFLAGS="$WX_CFLAGS $GDK_CFLAGS" WX_CXXFLAGS="$WX_CXXFLAGS $GDK_CFLAGS" printf "%s\n" "#define WX_GDK_VERSION 3" >>confdefs.h @@ -26261,8 +26333,10 @@ if test "$with_wx" = yes; then ;; esac # The enhanced X debugger depends on GTK2 - if test "$gui_debugger" = 1 -a "$DEFAULT_GUI" != win32; then - needs_gtk2=1 + if test "$DEFAULT_GUI" != win32; then + if test "$gui_debugger" = 1 -o "$usb_debugger" = 1; then + needs_gtk2=1 + fi fi fi @@ -26290,21 +26364,21 @@ fi bx_have_gtk_version=0 if test "$needs_gtk2" = 1; then # pkg-config is required to set TOOLKIT_CXXFLAGS and LIBS - if test "$PKGCONFIG" != not_found; then + if test "x$PKG_CONFIG" != x; then # if wxGTK is based on GTK 3.0, use it for gui debugger to avoid conflicts - if test "$with_wx" = yes -a "$wx_needs_gdk_version" = 3; then - pkg-config --exists gtk+-3.0 + if test "$with_wx" = yes -a "$wx_needs_gdk_version" = 2; then + $PKG_CONFIG --exists gtk+-2.0 if test x$? = x0; then - TOOLKIT_CXXFLAGS="`pkg-config --cflags gtk+-3.0`" - LIBS="$LIBS `pkg-config --libs gtk+-3.0`" - bx_have_gtk_version=3 + TOOLKIT_CXXFLAGS="`$PKG_CONFIG --cflags gtk+-2.0`" + LIBS="$LIBS `$PKG_CONFIG --libs gtk+-2.0`" + bx_have_gtk_version=2 fi else - pkg-config --exists gtk+-2.0 + $PKG_CONFIG --exists gtk+-3.0 if test x$? = x0; then - TOOLKIT_CXXFLAGS="`pkg-config --cflags gtk+-2.0`" - LIBS="$LIBS `pkg-config --libs gtk+-2.0`" - bx_have_gtk_version=2 + TOOLKIT_CXXFLAGS="`$PKG_CONFIG --cflags gtk+-3.0`" + LIBS="$LIBS `$PKG_CONFIG --libs gtk+-3.0`" + bx_have_gtk_version=3 fi fi else @@ -26312,6 +26386,8 @@ if test "$needs_gtk2" = 1; then echo "The gui debugger support is disabled now." fi fi +printf "%s\n" "#define BX_HAVE_GTK_VERSION $bx_have_gtk_version" >>confdefs.h + if test "$display_libs" = " wxWidgets"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for default configuration interface" >&5 @@ -26328,6 +26404,9 @@ printf "%s\n" "wxWidgets" >&6; } printf "%s\n" "#define BX_USE_TEXTCONFIG 0" >>confdefs.h + printf "%s\n" "#define HAVE_LIBREADLINE 0" >>confdefs.h + + READLINE_LIB="" else if test "$DEFAULT_GUI" = win32; then printf "%s\n" "#define BX_DEFAULT_CONFIG_INTERFACE \"win32config\"" >>confdefs.h @@ -26458,6 +26537,7 @@ case "$target" in else C_OPT="$C_OPT /EHs-c-" fi + C_OPT="$C_OPT /std:c++20" if test "$bx_plugins" = 1; then CFLAGS="/nologo /MD /W3 /DNDEBUG /DWIN32 /D_WINDOWS /D_CRT_SECURE_NO_WARNINGS $C_OPT" else @@ -26578,14 +26658,18 @@ fi USB_DBG_OBJS="" if test "$usb_debugger" = 1; then - if test "$DEFAULT_GUI" = win32 -o "$with_win32" = yes; then - USB_DBG_OBJS="win32usb.o" - printf "%s\n" "#define BX_USE_WIN32USBDEBUG 1" >>confdefs.h + if test "$bx_have_gtk_version" -ge 3; then + USB_DBG_OBJS="usb_debug.o gtk_usb_debug.o" + printf "%s\n" "#define BX_USB_DEBUGGER 1" >>confdefs.h + + elif test "$DEFAULT_GUI" = win32 -o "$with_win32" = yes; then + USB_DBG_OBJS="usb_debug.o win32usb.o" + printf "%s\n" "#define BX_USB_DEBUGGER 1" >>confdefs.h else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: The USB debugger supported only for Win32 cannot be compiled here, disabling it" >&5 -printf "%s\n" "$as_me: WARNING: The USB debugger supported only for Win32 cannot be compiled here, disabling it" >&2;} - printf "%s\n" "#define BX_USE_WIN32USBDEBUG 0" >>confdefs.h + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: The USB debugger cannot be compiled here, disabling it" >&5 +printf "%s\n" "$as_me: WARNING: The USB debugger cannot be compiled here, disabling it" >&2;} + printf "%s\n" "#define BX_USB_DEBUGGER 0" >>confdefs.h fi fi @@ -26597,7 +26681,6 @@ case $target in *-pc-windows* | *-pc-winnt*) if test "$bx_plugins" = 1; then # set variables for building DLL plugins - PLUGIN_VAR="" PLUGIN_LIBNAME_TRANSFORMATION='%.o=bx_%.dll' GUI_PLUGIN_NAME_TRANSFORMATION='%.o=bx_%_gui.dll' IMG_PLUGIN_NAME_TRANSFORMATION='%.o=bx_%_img.dll' @@ -26666,7 +26749,7 @@ esac if test "$use_curses" = yes; then - if test "$PKGCONFIG" != not_found; then + if test "x$PKG_CONFIG" != x; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mvaddch in -lcurses" >&5 printf %s "checking for mvaddch in -lcurses... " >&6; } if test ${ac_cv_lib_curses_mvaddch+y} @@ -26704,7 +26787,7 @@ fi printf "%s\n" "$ac_cv_lib_curses_mvaddch" >&6; } if test "x$ac_cv_lib_curses_mvaddch" = xyes then : - GUI_LINK_OPTS_TERM="`pkg-config --libs curses`" + GUI_LINK_OPTS_TERM="`$PKG_CONFIG --libs curses`" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mvaddch in -lncurses" >&5 @@ -26744,7 +26827,7 @@ fi printf "%s\n" "$ac_cv_lib_ncurses_mvaddch" >&6; } if test "x$ac_cv_lib_ncurses_mvaddch" = xyes then : - GUI_LINK_OPTS_TERM="`pkg-config --libs ncurses`" + GUI_LINK_OPTS_TERM="`$PKG_CONFIG --libs ncurses`" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mvaddch in -ltermlib" >&5 @@ -26784,7 +26867,7 @@ fi printf "%s\n" "$ac_cv_lib_termlib_mvaddch" >&6; } if test "x$ac_cv_lib_termlib_mvaddch" = xyes then : - GUI_LINK_OPTS_TERM="`pkg-config --libs termlib`" + GUI_LINK_OPTS_TERM="`$PKG_CONFIG --libs termlib`" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mvaddch in -lpdcurses" >&5 @@ -26824,7 +26907,7 @@ fi printf "%s\n" "$ac_cv_lib_pdcurses_mvaddch" >&6; } if test "x$ac_cv_lib_pdcurses_mvaddch" = xyes then : - GUI_LINK_OPTS_TERM="`pkg-config --libs pdcurses`" + GUI_LINK_OPTS_TERM="`$PKG_CONFIG --libs pdcurses`" fi else @@ -27461,6 +27544,7 @@ case "$target" in if test "$soundcard_present" = 1; then if test "$bx_plugins" = 1; then ALSA_SOUND_LINK_OPTS="$ALSA_SOUND_LINK_OPTS $PTHREAD_LIBS" + PULSE_SOUND_LINK_OPTS="$PULSE_SOUND_LINK_OPTS $PTHREAD_LIBS" SDL_SOUND_LINK_OPTS="$SDL_SOUND_LINK_OPTS $PTHREAD_LIBS" else DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS $PTHREAD_LIBS" @@ -27539,7 +27623,6 @@ if test ! -d build/win32/nsis; then mkdir build/win32/nsis; fi - # Extract the first word of "gzip", so it can be a program name with args. @@ -28367,7 +28450,6 @@ for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; - "ltdlconf.h") CONFIG_HEADERS="$CONFIG_HEADERS ltdlconf.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "iodev/Makefile") CONFIG_FILES="$CONFIG_FILES iodev/Makefile" ;; "iodev/display/Makefile") CONFIG_FILES="$CONFIG_FILES iodev/display/Makefile" ;; diff --git a/bochs/configure.ac b/bochs/configure.ac index 73593eb7e6..d7d300bcb1 100644 --- a/bochs/configure.ac +++ b/bochs/configure.ac @@ -5,7 +5,6 @@ AC_INIT AC_CONFIG_SRCDIR([bochs.h]) AC_REVISION([[$Id$]]) AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_HEADERS([ltdlconf.h]) dnl // Put Bochs version information right here so that it gets substituted dnl // into all the right places. @@ -157,8 +156,8 @@ else RANLIB="echo" fi -AC_PATH_PROG(PKGCONFIG, pkg-config, not_found) -if test "$PKGCONFIG" = not_found; then +PKG_PROG_PKG_CONFIG +if test "x$PKG_CONFIG" = x; then AC_PATH_XTRA fi @@ -466,8 +465,7 @@ if test "$bx_plugins" = 1; then PLUGIN_LIB="-lltdl" AC_DEFINE(BX_HAVE_LTDL,1) else - PLUGIN_VAR="ltdl.o" - PLUGIN_LIB="ltdl.o" + AC_MSG_ERROR([Plugin support requires libltdl installed on your system]) fi fi PLUGIN_TARGET=bochs_plugins @@ -1570,6 +1568,7 @@ AC_ARG_ENABLE(pcidev, ) use_usb=0 +use_usb_uhci=0 USBHC_OBJS='' UHCICORE_OBJ='' USBHC_DLL_TARGETS='' @@ -1583,6 +1582,7 @@ AC_ARG_ENABLE(usb, UHCICORE_OBJ="uhci_core.o" USBHC_DLL_TARGETS="bx_usb_uhci.dll" use_usb=1 + use_usb_uhci=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_USB_UHCI, 0) @@ -1593,6 +1593,7 @@ AC_ARG_ENABLE(usb, ] ) +use_usb_ohci=0 AC_MSG_CHECKING(for USB OHCI support) AC_ARG_ENABLE(usb-ohci, AS_HELP_STRING([--enable-usb-ohci], [enable USB OHCI support (no)]), @@ -1602,6 +1603,7 @@ AC_ARG_ENABLE(usb-ohci, USBHC_OBJS="$USBHC_OBJS usb_ohci.o" USBHC_DLL_TARGETS="$USBHC_DLL_TARGETS bx_usb_ohci.dll" use_usb=1 + use_usb_ohci=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_USB_OHCI, 0) @@ -1612,6 +1614,7 @@ AC_ARG_ENABLE(usb-ohci, ] ) +use_usb_ehci=0 AC_MSG_CHECKING(for USB EHCI support) AC_ARG_ENABLE(usb-ehci, AS_HELP_STRING([--enable-usb-ehci], [enable USB EHCI support (no)]), @@ -1621,6 +1624,7 @@ AC_ARG_ENABLE(usb-ehci, USBHC_OBJS="$USBHC_OBJS usb_ehci.o" USBHC_DLL_TARGETS="$USBHC_DLL_TARGETS bx_usb_ehci.dll" use_usb=1 + use_usb_ehci=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_USB_EHCI, 0) @@ -1631,6 +1635,7 @@ AC_ARG_ENABLE(usb-ehci, ] ) +use_usb_xhci=0 AC_MSG_CHECKING(for USB xHCI support) AC_ARG_ENABLE(usb-xhci, AS_HELP_STRING([--enable-usb-xhci], [enable USB xHCI support (no)]), @@ -1640,6 +1645,7 @@ AC_ARG_ENABLE(usb-xhci, USBHC_OBJS="$USBHC_OBJS usb_xhci.o" USBHC_DLL_TARGETS="$USBHC_DLL_TARGETS bx_usb_xhci.dll" use_usb=1 + use_usb_xhci=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_USB_XHCI, 0) @@ -1651,6 +1657,11 @@ AC_ARG_ENABLE(usb-xhci, ) if test "$use_usb" = 1; then + if test "$use_usb_ehci" = 1; then + if test "$use_usb_uhci" = 0 -a "$use_usb_ohci" = 0; then + AC_MSG_ERROR([To configure USB EHCI, you must also enable UHCI or OHCI]) + fi + fi if test "$pci" != "1"; then AC_MSG_ERROR([USB requires PCI support]) fi @@ -1661,15 +1672,15 @@ AC_SUBST(USBHC_OBJS) AC_SUBST(USBHC_DLL_TARGETS) usb_debugger=0 -AC_MSG_CHECKING(enable Bochs Win32 USB debugger) -AC_ARG_ENABLE(win32usbdbg, - AS_HELP_STRING([--enable-win32usbdbg], [compile in support for Bochs Win32 USB debugger (yes, if debugger is on and USB is on)]), +AC_MSG_CHECKING(enable Bochs USB debugger) +AC_ARG_ENABLE(usb-debugger, + AS_HELP_STRING([--enable-usb-debugger], [compile in support for Bochs USB debugger (yes, if debugger is on and USB is on)]), [if test "$enableval" = yes; then AC_MSG_RESULT(yes) usb_debugger=1 else AC_MSG_RESULT(no) - AC_DEFINE(BX_USE_WIN32USBDEBUG, 0) + AC_DEFINE(BX_USB_DEBUGGER, 0) usb_debugger=0 fi], [ @@ -1678,7 +1689,7 @@ AC_ARG_ENABLE(win32usbdbg, usb_debugger=1 else AC_MSG_RESULT(no) - AC_DEFINE(BX_USE_WIN32USBDEBUG, 0) + AC_DEFINE(BX_USB_DEBUGGER, 0) usb_debugger=0 fi ] @@ -1748,23 +1759,56 @@ AC_ARG_ENABLE(e1000, ) NETLOW_OBJS='' +SLIRP_OBJS='' +SLIRP_OBJS2='' +SLIRP_LINK_OPTS='' if test "$networking" = yes; then NETLOW_OBJS='eth_null.o eth_vnet.o' ethernet_modules='null vnet' can_compile_slirp=0 - case "$target" in - *-cygwin* | *-mingw32* | *-msys) - can_compile_slirp=1 - DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -liphlpapi" - ;; - *-pc-windows* | *-pc-winnt*) - can_compile_slirp=1 - DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS iphlpapi.lib" - ;; - *) - AC_CHECK_HEADER([netinet/in.h], [ can_compile_slirp=1 ], []) - ;; - esac + AC_MSG_CHECKING(for slirp networking support) + AC_ARG_ENABLE(using-libslirp, + AS_HELP_STRING([--enable-using-libslirp], [enable using libslirp instead of builtin slirp (no)]), + [if test "$enableval" = yes; then + if test "x$PKG_CONFIG" != x; then + $PKG_CONFIG --exists slirp + if test x$? = x0; then + can_compile_slirp=1 + if test "$bx_plugins" = 1; then + SLIRP_LINK_OPTS="`$PKG_CONFIG --libs slirp`" + else + DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS `$PKG_CONFIG --libs slirp`" + fi + AC_MSG_RESULT(libslirp) + AC_DEFINE(BX_HAVE_LIBSLIRP, 1) + fi + fi + fi], []) + if test $can_compile_slirp = 0; then + AC_MSG_RESULT(builtin) + case "$target" in + *-cygwin* | *-mingw32* | *-msys) + can_compile_slirp=1 + DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -liphlpapi" + SLIRP_OBJS='$(SLIRP_OBJS)' + ;; + *-pc-windows* | *-pc-winnt*) + can_compile_slirp=1 + DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS iphlpapi.lib" + SLIRP_OBJS='$(SLIRP_OBJS)' + ;; + *) + AC_CHECK_HEADER([netinet/in.h],[can_compile_slirp=1]) + if test $can_compile_slirp = 1; then + if test "$bx_plugins" = 1; then + SLIRP_OBJS2='$(SLIRP_OBJS:.o=.lo)' + else + SLIRP_OBJS='$(SLIRP_OBJS)' + fi + fi + ;; + esac + fi if test $can_compile_slirp = 1; then NETLOW_OBJS="$NETLOW_OBJS eth_slirp.o" ethernet_modules="$ethernet_modules slirp" @@ -1853,6 +1897,9 @@ fi AC_SUBST(NETDEV_OBJS) AC_SUBST(NETLOW_OBJS) AC_SUBST(NETDEV_DLL_TARGETS) +AC_SUBST(SLIRP_OBJS) +AC_SUBST(SLIRP_OBJS2) +AC_SUBST(SLIRP_LINK_OPTS) dnl // serial mode 'socket' needs ws2_32.dll in non-plugin mode @@ -2121,6 +2168,21 @@ if test "$soundcard_present" = 1; then AC_DEFINE(BX_HAVE_SDL2_AUDIO_CAPTURE, 1) fi fi + if test "$cross_configure" = 0 -a "$DEFAULT_GUI" != win32; then + if test "x$PKG_CONFIG" != x; then + $PKG_CONFIG --exists libpulse-simple + if test x$? = x0; then + SOUNDLOW_OBJS="$SOUNDLOW_OBJS soundpulse.o" + soundlow_drivers="$soundlow_drivers pulse" + AC_DEFINE(BX_HAVE_SOUND_PULSE, 1) + if test "$bx_plugins" = 1; then + PULSE_SOUND_LINK_OPTS="$PULSE_SOUND_LINK_OPTS `$PKG_CONFIG --libs libpulse-simple`" + else + DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS `$PKG_CONFIG --libs libpulse-simple`" + fi + fi + fi + fi if test "$MSVC_TARGET" = 0; then AC_CHECK_HEADER([samplerate.h], [bx_have_libsamplerate=1]) if test "$bx_have_libsamplerate" = 1; then @@ -2147,6 +2209,7 @@ fi AC_SUBST(SOUNDHW_OBJS) AC_SUBST(SOUNDLOW_OBJS) AC_SUBST(ALSA_SOUND_LINK_OPTS) +AC_SUBST(PULSE_SOUND_LINK_OPTS) AC_SUBST(SDL_SOUND_LINK_OPTS) AC_SUBST(SOUNDHW_DLL_TARGETS) @@ -2459,9 +2522,9 @@ if test "$with_x11" = yes; then XRANDR_LIB='-lXrandr' ]) - if test "$PKGCONFIG" != not_found; then - X_CFLAGS="`pkg-config --cflags x11`" - X_LIBS="`pkg-config --libs x11` $XPM_LIB $XRANDR_LIB" + if test "x$PKG_CONFIG" != x; then + X_CFLAGS="`$PKG_CONFIG --cflags x11`" + X_LIBS="`$PKG_CONFIG --libs x11` $XPM_LIB $XRANDR_LIB" else X_LIBS="$X_LIBS -lX11 $XPM_LIB $XRANDR_LIB" fi @@ -2472,7 +2535,7 @@ if test "$with_x11" = yes; then GUI_CXXFLAGS="$GUI_CXXFLAGS \$(X_CFLAGS)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_X)" # The enhanced X debugger depends on GTK2 - if test "$gui_debugger" = 1; then + if test "$gui_debugger" = 1 -o "$usb_debugger" = 1; then needs_gtk2=1 fi use_gui_console=1 @@ -2497,8 +2560,10 @@ if test "$with_sdl" = yes; then NONPLUGIN_GUI_LINK_OPTS="`sdl-config --libs`" fi # The enhanced X debugger depends on GTK2 - if test "$gui_debugger" = 1 -a "$DEFAULT_GUI" != win32; then - needs_gtk2=1 + if test "$DEFAULT_GUI" != win32; then + if test "$gui_debugger" = 1 -o "$usb_debugger" = 1; then + needs_gtk2=1 + fi fi if test "$with_win32" != yes -a "$with_wx" != yes; then case $target in @@ -2532,8 +2597,10 @@ if test "$with_sdl2" = yes; then NONPLUGIN_GUI_LINK_OPTS="`sdl2-config --libs`" fi # The enhanced X debugger depends on GTK2 - if test "$gui_debugger" = 1 -a "$DEFAULT_GUI" != win32; then - needs_gtk2=1 + if test "$DEFAULT_GUI" != win32; then + if test "$gui_debugger" = 1 -o "$usb_debugger" = 1; then + needs_gtk2=1 + fi fi if test "$with_win32" != yes -a "$with_wx" != yes; then case $target in @@ -2560,11 +2627,11 @@ if test "$with_rfb" = yes; then fi if test "$with_vncsrv" = yes; then - if test "$PKGCONFIG" != not_found; then - pkg-config --exists libvncserver + if test "$PKG_CONFIG" != not_found; then + $PKG_CONFIG --exists libvncserver if test x$? = x0; then - VNCSRV_CXXFLAGS="`pkg-config --cflags libvncserver`" - GUI_LINK_OPTS_VNCSRV="`pkg-config --libs libvncserver`" + VNCSRV_CXXFLAGS="`$PKG_CONFIG --cflags libvncserver`" + GUI_LINK_OPTS_VNCSRV="`$PKG_CONFIG --libs libvncserver`" fi else AC_CHECK_PROG(LIBVNCSERVER_CONFIG, [ libvncserver-config --version ], libvncserver-config, not_found) @@ -2671,13 +2738,13 @@ if test "$with_wx" = yes; then WX_CFLAGS="`$WX_CONFIG --cflags`" WX_CXXFLAGS="`$WX_CONFIG --cxxflags`" if test "$wx_needs_gdk_version" = 2; then - GDK_CFLAGS="`pkg-config --cflags gdk-2.0`" + GDK_CFLAGS="`$PKG_CONFIG --cflags gdk-2.0`" WX_CFLAGS="$WX_CFLAGS $GDK_CFLAGS" WX_CXXFLAGS="$WX_CXXFLAGS $GDK_CFLAGS" AC_DEFINE(WX_GDK_VERSION, 2) fi if test "$wx_needs_gdk_version" = 3; then - GDK_CFLAGS="`pkg-config --cflags gdk-3.0`" + GDK_CFLAGS="`$PKG_CONFIG --cflags gdk-3.0`" WX_CFLAGS="$WX_CFLAGS $GDK_CFLAGS" WX_CXXFLAGS="$WX_CXXFLAGS $GDK_CFLAGS" AC_DEFINE(WX_GDK_VERSION, 3) @@ -2708,8 +2775,10 @@ if test "$with_wx" = yes; then ;; esac # The enhanced X debugger depends on GTK2 - if test "$gui_debugger" = 1 -a "$DEFAULT_GUI" != win32; then - needs_gtk2=1 + if test "$DEFAULT_GUI" != win32; then + if test "$gui_debugger" = 1 -o "$usb_debugger" = 1; then + needs_gtk2=1 + fi fi fi @@ -2734,21 +2803,21 @@ fi bx_have_gtk_version=0 if test "$needs_gtk2" = 1; then # pkg-config is required to set TOOLKIT_CXXFLAGS and LIBS - if test "$PKGCONFIG" != not_found; then + if test "x$PKG_CONFIG" != x; then # if wxGTK is based on GTK 3.0, use it for gui debugger to avoid conflicts - if test "$with_wx" = yes -a "$wx_needs_gdk_version" = 3; then - pkg-config --exists gtk+-3.0 + if test "$with_wx" = yes -a "$wx_needs_gdk_version" = 2; then + $PKG_CONFIG --exists gtk+-2.0 if test x$? = x0; then - TOOLKIT_CXXFLAGS="`pkg-config --cflags gtk+-3.0`" - LIBS="$LIBS `pkg-config --libs gtk+-3.0`" - bx_have_gtk_version=3 + TOOLKIT_CXXFLAGS="`$PKG_CONFIG --cflags gtk+-2.0`" + LIBS="$LIBS `$PKG_CONFIG --libs gtk+-2.0`" + bx_have_gtk_version=2 fi else - pkg-config --exists gtk+-2.0 + $PKG_CONFIG --exists gtk+-3.0 if test x$? = x0; then - TOOLKIT_CXXFLAGS="`pkg-config --cflags gtk+-2.0`" - LIBS="$LIBS `pkg-config --libs gtk+-2.0`" - bx_have_gtk_version=2 + TOOLKIT_CXXFLAGS="`$PKG_CONFIG --cflags gtk+-3.0`" + LIBS="$LIBS `$PKG_CONFIG --libs gtk+-3.0`" + bx_have_gtk_version=3 fi fi else @@ -2756,6 +2825,7 @@ if test "$needs_gtk2" = 1; then echo "The gui debugger support is disabled now." fi fi +AC_DEFINE_UNQUOTED(BX_HAVE_GTK_VERSION, $bx_have_gtk_version) dnl To use wxWidgets you must select it as both the configuration interface dnl and the display library. In the simplest case where the user has @@ -2771,6 +2841,8 @@ if test "$display_libs" = " wxWidgets"; then AC_DEFINE(BX_DEFAULT_CONFIG_INTERFACE, "wx") AC_DEFINE(BX_DEFAULT_DISPLAY_LIBRARY, "wx") AC_DEFINE(BX_USE_TEXTCONFIG, 0) + AC_DEFINE(HAVE_LIBREADLINE, 0) + READLINE_LIB="" else if test "$DEFAULT_GUI" = win32; then AC_DEFINE(BX_DEFAULT_CONFIG_INTERFACE, "win32config") @@ -2837,6 +2909,7 @@ case "$target" in else C_OPT="$C_OPT /EHs-c-" fi + C_OPT="$C_OPT /std:c++20" if test "$bx_plugins" = 1; then CFLAGS="/nologo /MD /W3 /DNDEBUG /DWIN32 /D_WINDOWS /D_CRT_SECURE_NO_WARNINGS $C_OPT" else @@ -2945,12 +3018,15 @@ AC_SUBST(ENH_DBG_OBJS) USB_DBG_OBJS="" if test "$usb_debugger" = 1; then - if test "$DEFAULT_GUI" = win32 -o "$with_win32" = yes; then - USB_DBG_OBJS="win32usb.o" - AC_DEFINE(BX_USE_WIN32USBDEBUG, 1) + if test "$bx_have_gtk_version" -ge 3; then + USB_DBG_OBJS="usb_debug.o gtk_usb_debug.o" + AC_DEFINE(BX_USB_DEBUGGER, 1) + elif test "$DEFAULT_GUI" = win32 -o "$with_win32" = yes; then + USB_DBG_OBJS="usb_debug.o win32usb.o" + AC_DEFINE(BX_USB_DEBUGGER, 1) else - AC_MSG_WARN([The USB debugger supported only for Win32 cannot be compiled here, disabling it]) - AC_DEFINE(BX_USE_WIN32USBDEBUG, 0) + AC_MSG_WARN([The USB debugger cannot be compiled here, disabling it]) + AC_DEFINE(BX_USB_DEBUGGER, 0) fi fi AC_SUBST(USB_DBG_OBJS) @@ -2961,7 +3037,6 @@ case $target in *-pc-windows* | *-pc-winnt*) if test "$bx_plugins" = 1; then # set variables for building DLL plugins - PLUGIN_VAR="" PLUGIN_LIBNAME_TRANSFORMATION='%.o=bx_%.dll' GUI_PLUGIN_NAME_TRANSFORMATION='%.o=bx_%_gui.dll' IMG_PLUGIN_NAME_TRANSFORMATION='%.o=bx_%_img.dll' @@ -3030,11 +3105,11 @@ AC_SUBST(EXPORT_DYNAMIC) AC_SUBST(DLLTOOL) if test "$use_curses" = yes; then - if test "$PKGCONFIG" != not_found; then - AC_CHECK_LIB(curses, mvaddch, GUI_LINK_OPTS_TERM="`pkg-config --libs curses`") - AC_CHECK_LIB(ncurses, mvaddch, GUI_LINK_OPTS_TERM="`pkg-config --libs ncurses`") - AC_CHECK_LIB(termlib, mvaddch, GUI_LINK_OPTS_TERM="`pkg-config --libs termlib`") - AC_CHECK_LIB(pdcurses, mvaddch, GUI_LINK_OPTS_TERM="`pkg-config --libs pdcurses`") + if test "x$PKG_CONFIG" != x; then + AC_CHECK_LIB(curses, mvaddch, GUI_LINK_OPTS_TERM="`$PKG_CONFIG --libs curses`") + AC_CHECK_LIB(ncurses, mvaddch, GUI_LINK_OPTS_TERM="`$PKG_CONFIG --libs ncurses`") + AC_CHECK_LIB(termlib, mvaddch, GUI_LINK_OPTS_TERM="`$PKG_CONFIG --libs termlib`") + AC_CHECK_LIB(pdcurses, mvaddch, GUI_LINK_OPTS_TERM="`$PKG_CONFIG --libs pdcurses`") else AC_CHECK_LIB(curses, mvaddch, GUI_LINK_OPTS_TERM='-lcurses') AC_CHECK_LIB(ncurses, mvaddch, GUI_LINK_OPTS_TERM='-lncurses') @@ -3301,6 +3376,7 @@ case "$target" in if test "$soundcard_present" = 1; then if test "$bx_plugins" = 1; then ALSA_SOUND_LINK_OPTS="$ALSA_SOUND_LINK_OPTS $PTHREAD_LIBS" + PULSE_SOUND_LINK_OPTS="$PULSE_SOUND_LINK_OPTS $PTHREAD_LIBS" SDL_SOUND_LINK_OPTS="$SDL_SOUND_LINK_OPTS $PTHREAD_LIBS" else DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS $PTHREAD_LIBS" @@ -3381,7 +3457,6 @@ AC_SUBST(IODEV_NON_PLUGIN_OBJS) AC_SUBST(IODEV_PLUGIN_OBJS) AC_SUBST(IODEV_EXT_NON_PLUGIN_OBJS) AC_SUBST(IODEV_EXT_PLUGIN_OBJS) -AC_SUBST(PLUGIN_VAR) AC_SUBST(PLUGIN_LIB) AC_SUBST(PLUGIN_TARGET) AC_SUBST(PLUGIN_TARGET_2) diff --git a/bochs/cpu/3dnow.cc b/bochs/cpu/3dnow.cc index e629e8d580..1c95d8f150 100644 --- a/bochs/cpu/3dnow.cc +++ b/bochs/cpu/3dnow.cc @@ -28,12 +28,15 @@ #if BX_SUPPORT_3DNOW -BX_CPP_INLINE void prepare_softfloat_status_word(float_status_t &status, int rounding_mode) +#include "softfloat3e/include/softfloat.h" + +BX_CPP_INLINE void prepare_softfloat_status_word(softfloat_status_t &status, int rounding_mode) { - status.float_exception_flags = 0; // clear exceptions before execution - status.float_nan_handling_mode = float_first_operand_nan; - status.float_rounding_mode = rounding_mode; - status.flush_underflow_to_zero = 0; + status.softfloat_exceptionFlags = 0; // clear exceptions before execution + status.softfloat_roundingMode = rounding_mode; + status.softfloat_flush_underflow_to_zero = 0; + status.softfloat_suppressException = 0; + status.softfloat_denormals_are_zeros = 0; } void BX_CPP_AttrRegparmN(1) BX_CPU_C::PFPNACC_PqQq(bxInstruction_c *i) @@ -65,8 +68,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::PI2FW_PqQq(bxInstruction_c *i) BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ - float_status_t status; - prepare_softfloat_status_word(status, float_round_to_zero); + softfloat_status_t status; + prepare_softfloat_status_word(status, softfloat_round_to_zero); MMXUD0(result) = i32_to_f32((Bit32s)(MMXSW0(op)), &status); MMXUD1(result) = i32_to_f32((Bit32s)(MMXSW2(op)), &status); @@ -98,8 +101,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::PI2FD_PqQq(bxInstruction_c *i) BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ - float_status_t status; - prepare_softfloat_status_word(status, float_round_to_zero); + softfloat_status_t status; + prepare_softfloat_status_word(status, softfloat_round_to_zero); MMXUD0(op) = i32_to_f32(MMXSD0(op), &status); MMXUD1(op) = i32_to_f32(MMXSD1(op), &status); @@ -140,8 +143,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::PF2ID_PqQq(bxInstruction_c *i) BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ - float_status_t status; - prepare_softfloat_status_word(status, float_round_to_zero); + softfloat_status_t status; + prepare_softfloat_status_word(status, softfloat_round_to_zero); MMXSD0(op) = f32_to_i32_round_to_zero(MMXUD0(op), &status); MMXSD1(op) = f32_to_i32_round_to_zero(MMXUD1(op), &status); diff --git a/bochs/cpu/Makefile.in b/bochs/cpu/Makefile.in index 683efdd892..4fe4cd1b6d 100644 --- a/bochs/cpu/Makefile.in +++ b/bochs/cpu/Makefile.in @@ -120,7 +120,6 @@ OBJS = \ bit16.o \ bit32.o \ bmi32.o \ - cmpccxadd32.o \ string.o \ faststring.o \ paging.o \ @@ -140,6 +139,7 @@ OBJS64 = \ bit64.o \ stack64.o \ bmi64.o \ + cmpccxadd32.o \ cmpccxadd64.o \ vapic.o \ uintr.o \ @@ -177,621 +177,707 @@ dist-clean: clean 3dnow.o: 3dnow.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h \ + softfloat3e/include/softfloat.h softfloat3e/include/softfloat_types.h \ + softfloat3e/include/softfloat-extra.h softfloat3e/include/internals.h access.o: access.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h access2.o: access2.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h aes.o: aes.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h simd_int.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h simd_int.h apic.o: apic.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h apic.h \ - scalar_arith.h ../iodev/iodev.h ../plugin.h ../extplugin.h \ - ../param_names.h ../pc_system.h ../memory/memory-bochs.h \ - ../gui/siminterface.h ../gui/paramtree.h ../gui/gui.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h apic.h scalar_arith.h \ + ../iodev/iodev.h ../plugin.h ../extplugin.h ../param_names.h \ + ../pc_system.h ../memory/memory-bochs.h ../gui/siminterface.h \ + ../gui/paramtree.h ../gui/gui.h arith16.o: arith16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h arith32.o: arith32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h arith64.o: arith64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h arith8.o: arith8.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h bcd.o: bcd.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h bit.o: bit.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h bit16.o: bit16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h bit32.o: bit32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h bit64.o: bit64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h bmi32.o: bmi32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h bmi64.o: bmi64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h \ wide_int.h call_far.o: call_far.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cet.o: cet.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h msr.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h msr.h cmpccxadd32.o: cmpccxadd32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cmpccxadd64.o: cmpccxadd64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cpu.o: cpu.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h \ ../memory/memory-bochs.h ../pc_system.h cpustats.h decoder/ia_opcodes.h \ decoder/ia_opcodes.def cpuid.o: cpuid.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h access.h ../gui/siminterface.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h access.h ../gui/siminterface.h \ ../gui/paramtree.h ../param_names.h cpuid.h decoder/features.h crc32.o: crc32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h crregs.o: crregs.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h cpuid.h svm.h \ - apic.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cpuid.h svm.h apic.h ctrl_xfer16.o: ctrl_xfer16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h svm.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h ctrl_xfer32.o: ctrl_xfer32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h svm.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h ctrl_xfer64.o: ctrl_xfer64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h svm.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h ctrl_xfer_pro.o: ctrl_xfer_pro.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h data_xfer16.o: data_xfer16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h data_xfer32.o: data_xfer32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h data_xfer64.o: data_xfer64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h data_xfer8.o: data_xfer8.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h debugstuff.o: debugstuff.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h \ ../memory/memory-bochs.h ../pc_system.h event.o: event.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h apic.h svm.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h apic.h svm.h \ ../iodev/iodev.h ../plugin.h ../extplugin.h ../param_names.h \ ../pc_system.h ../memory/memory-bochs.h ../gui/siminterface.h \ ../gui/paramtree.h ../gui/gui.h exception.o: exception.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h svm.h \ - ../param_names.h ../iodev/iodev.h ../plugin.h ../extplugin.h \ - ../pc_system.h ../memory/memory-bochs.h ../gui/siminterface.h \ - ../gui/paramtree.h ../gui/gui.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h ../param_names.h \ + ../iodev/iodev.h ../plugin.h ../extplugin.h ../pc_system.h \ + ../memory/memory-bochs.h ../gui/siminterface.h ../gui/paramtree.h \ + ../gui/gui.h faststring.o: faststring.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h ../pc_system.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h ../pc_system.h flag_ctrl.o: flag_ctrl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h svm.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h flag_ctrl_pro.o: flag_ctrl_pro.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h svm.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h fpu_emu.o: fpu_emu.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h generic_cpuid.o: generic_cpuid.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h ../gui/siminterface.h ../gui/paramtree.h \ cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h access.h ../param_names.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h access.h ../param_names.h \ generic_cpuid.h cpuid.h svm.h gf2.o: gf2.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h icache.o: icache.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h \ - ../gui/siminterface.h ../gui/paramtree.h ../param_names.h cpustats.h \ - decoder/ia_opcodes.h decoder/ia_opcodes.def + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h ../gui/siminterface.h \ + ../gui/paramtree.h ../param_names.h cpustats.h decoder/ia_opcodes.h \ + decoder/ia_opcodes.def init.o: init.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h \ - ../gui/siminterface.h ../gui/paramtree.h ../param_names.h cpustats.h \ - apic.h avx/amx.h ../cpu/xmm.h svm.h generic_cpuid.h cpuid.h ../cpudb.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h ../gui/siminterface.h \ + ../gui/paramtree.h ../param_names.h cpustats.h apic.h avx/amx.h \ + ../cpu/xmm.h svm.h generic_cpuid.h cpuid.h ../cpudb.h io.o: io.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h ../misc/bswap.h \ cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h svm.h \ - ../iodev/iodev.h ../plugin.h ../extplugin.h ../param_names.h \ - ../pc_system.h ../memory/memory-bochs.h ../gui/siminterface.h \ - ../gui/paramtree.h ../gui/gui.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h ../iodev/iodev.h \ + ../plugin.h ../extplugin.h ../param_names.h ../pc_system.h \ + ../memory/memory-bochs.h ../gui/siminterface.h ../gui/paramtree.h \ + ../gui/gui.h iret.o: iret.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h jmp_far.o: jmp_far.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h load.o: load.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h simd_int.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h simd_int.h logical16.o: logical16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h logical32.o: logical32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h logical64.o: logical64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h logical8.o: logical8.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h mmx.o: mmx.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h msr.o: msr.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h cpuid.h msr.h \ - svm.h apic.h scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cpuid.h msr.h svm.h \ + apic.h scalar_arith.h mult16.o: mult16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h mult32.o: mult32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h mult64.o: mult64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h wide_int.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h wide_int.h mult8.o: mult8.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h mwait.o: mwait.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h ../gui/siminterface.h ../gui/paramtree.h \ ../param_names.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h svm.h apic.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h apic.h \ ../pc_system.h decoder/ia_opcodes.h decoder/ia_opcodes.def paging.o: paging.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h cpuid.h msr.h \ - apic.h svm.h ../memory/memory-bochs.h ../pc_system.h cpustats.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cpuid.h msr.h apic.h \ + svm.h ../memory/memory-bochs.h ../pc_system.h cpustats.h proc_ctrl.o: proc_ctrl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h cpuid.h svm.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cpuid.h svm.h \ ../pc_system.h ../gui/gui.h ../gui/siminterface.h ../gui/paramtree.h \ wide_int.h decoder/ia_opcodes.h decoder/ia_opcodes.def protect_ctrl.o: protect_ctrl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h svm.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h rdrand.o: rdrand.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h ret_far.o: ret_far.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h segment_ctrl.o: segment_ctrl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h segment_ctrl_pro.o: segment_ctrl_pro.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ decoder/decoder.h ../instrument/stubs/instrument.h i387.h \ - fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h crregs.h \ - descriptor.h decoder/instr.h lazy_flags.h tlb.h icache.h xmm.h vmx.h \ - stack.h access.h + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h sha.o: sha.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h sha512.o: sha512.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h shift16.o: shift16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h \ decoder/ia_opcodes.h decoder/ia_opcodes.def shift32.o: shift32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h \ decoder/ia_opcodes.h decoder/ia_opcodes.def shift64.o: shift64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h \ decoder/ia_opcodes.h decoder/ia_opcodes.def shift8.o: shift8.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h \ decoder/ia_opcodes.h decoder/ia_opcodes.def sm3.o: sm3.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h sm4.o: sm4.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h scalar_arith.h smm.o: smm.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h smm.h svm.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h smm.h svm.h soft_int.o: soft_int.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h cpuid.h svm.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cpuid.h svm.h sse.o: sse.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h simd_int.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h simd_int.h sse_move.o: sse_move.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h simd_int.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h simd_int.h sse_pfp.o: sse_pfp.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h \ - fpu/softfloat.h simd_pfp.h simd_int.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h \ + softfloat3e/include/softfloat-compare.h softfloat3e/include/softfloat.h \ + softfloat3e/include/softfloat_types.h \ + softfloat3e/include/softfloat-extra.h softfloat3e/include/internals.h \ + simd_pfp.h simd_int.h sse_rcp.o: sse_rcp.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h \ - fpu/softfloat-specialize.h fpu/softfloat.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h \ + softfloat3e/include/softfloat.h softfloat3e/include/softfloat_types.h \ + softfloat3e/include/softfloat-extra.h softfloat3e/include/internals.h \ + fpu/softfloat-specialize.h fpu/../softfloat3e/include/softfloat_types.h sse_string.o: sse_string.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h stack.o: stack.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h cpustats.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cpustats.h stack16.o: stack16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h stack32.o: stack32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h stack64.o: stack64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h string.o: string.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h ../pc_system.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h ../pc_system.h svm.o: svm.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h svm.h cpuid.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h cpuid.h \ ../gui/paramtree.h decoder/ia_opcodes.h decoder/ia_opcodes.def tasking.o: tasking.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h svm.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h svm.h uintr.o: uintr.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h apic.h \ - scalar_arith.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h apic.h scalar_arith.h vapic.o: vapic.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h \ ../memory/memory-bochs.h apic.h scalar_arith.h vm8086.o: vm8086.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h vmcs.o: vmcs.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h cpuid.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cpuid.h vmexit.o: vmexit.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h ../pc_system.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h ../pc_system.h \ decoder/ia_opcodes.h decoder/ia_opcodes.def vmfunc.o: vmfunc.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h cpuid.h + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cpuid.h vmx.o: vmx.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h cpuid.h msr.h \ - apic.h ../iodev/iodev.h ../plugin.h ../extplugin.h ../param_names.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h cpuid.h msr.h apic.h \ + ../iodev/iodev.h ../plugin.h ../extplugin.h ../param_names.h \ ../pc_system.h ../memory/memory-bochs.h ../gui/siminterface.h \ ../gui/paramtree.h ../gui/gui.h decoder/ia_opcodes.h \ decoder/ia_opcodes.def scalar_arith.h @@ -799,40 +885,45 @@ wide_int.o: wide_int.@CPP_SUFFIX@ wide_int.h ../config.h xsave.o: xsave.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h decoder/decoder.h \ - ../instrument/stubs/instrument.h i387.h fpu/softfloat.h fpu/tag_w.h \ - fpu/status_w.h fpu/control_w.h crregs.h descriptor.h decoder/instr.h \ - lazy_flags.h tlb.h icache.h xmm.h vmx.h stack.h access.h msr.h svm.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h vmx_ctrls.h stack.h access.h msr.h svm.h \ decoder/ia_opcodes.h decoder/ia_opcodes.def avx/amx.h ../cpu/xmm.h -decoder/disasm.o: decoder/disasm.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ - ../misc/bswap.h decoder/../cpu.h ../bx_debug/debug.h ../config.h \ +disasm.o: decoder/disasm.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ + ../misc/bswap.h cpu.h ../bx_debug/debug.h ../config.h \ ../osdep.h ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ - decoder/../decoder/decoder.h ../instrument/stubs/instrument.h \ - decoder/../i387.h decoder/../fpu/softfloat.h decoder/../fpu/tag_w.h \ - decoder/../fpu/status_w.h decoder/../fpu/control_w.h decoder/../crregs.h \ - decoder/../descriptor.h decoder/../decoder/instr.h \ - decoder/../lazy_flags.h decoder/../tlb.h decoder/../icache.h \ - decoder/../xmm.h decoder/../vmx.h decoder/../access.h decoder/instr.h \ + decoder/decoder.h ../instrument/stubs/instrument.h \ + i387.h softfloat3e/include/softfloat_types.h \ + fpu/tag_w.h fpu/status_w.h \ + fpu/control_w.h crregs.h descriptor.h \ + decoder/instr.h lazy_flags.h tlb.h \ + icache.h xmm.h vmx.h \ + vmx_ctrls.h access.h decoder/instr.h \ decoder/decoder.h decoder/fetchdecode.h decoder/ia_opcodes.h \ - decoder/ia_opcodes.def decoder/../../bx_debug/debug.h -decoder/fetchdecode32.o: decoder/fetchdecode32.@CPP_SUFFIX@ ../bochs.h ../config.h \ - ../osdep.h ../logio.h ../misc/bswap.h decoder/../cpu.h \ + decoder/ia_opcodes.def ../bx_debug/debug.h +fetchdecode32.o: decoder/fetchdecode32.@CPP_SUFFIX@ ../bochs.h ../config.h \ + ../osdep.h ../logio.h ../misc/bswap.h cpu.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../cpu/decoder/decoder.h \ - ../cpu/decoder/features.h decoder/../decoder/decoder.h \ - ../instrument/stubs/instrument.h decoder/../i387.h \ - decoder/../fpu/softfloat.h decoder/../fpu/tag_w.h \ - decoder/../fpu/status_w.h decoder/../fpu/control_w.h decoder/../crregs.h \ - decoder/../descriptor.h decoder/../decoder/instr.h \ - decoder/../lazy_flags.h decoder/../tlb.h decoder/../icache.h \ - decoder/../xmm.h decoder/../vmx.h decoder/../stack.h decoder/../access.h \ - decoder/../cpu_templates.h decoder/../cpu_templates_pfp.h \ - decoder/../simd_int.h decoder/decoder.h decoder/instr.h \ - decoder/fetchdecode.h decoder/ia_opcodes.h decoder/ia_opcodes.def \ - decoder/fetchdecode_opmap.h decoder/fetchdecode_opmap_0f38.h \ - decoder/fetchdecode_opmap_0f3a.h decoder/fetchdecode_x87.h \ - decoder/fetchdecode_avx.h decoder/fetchdecode_xop.h \ - decoder/fetchdecode_evex.h ../cpu/simd_int.h ../cpu/fpu/softfloat.h \ + ../cpu/decoder/features.h decoder/decoder.h \ + ../instrument/stubs/instrument.h i387.h \ + softfloat3e/include/softfloat_types.h fpu/tag_w.h \ + fpu/status_w.h fpu/control_w.h crregs.h \ + descriptor.h decoder/instr.h \ + lazy_flags.h tlb.h icache.h \ + xmm.h vmx.h vmx_ctrls.h \ + stack.h access.h cpu_templates.h \ + cpu_templates_pfp.h ../cpu/softfloat3e/include/softfloat.h \ + ../cpu/softfloat3e/include/softfloat_types.h \ + ../cpu/softfloat3e/include/softfloat-extra.h \ + ../cpu/softfloat3e/include/internals.h simd_int.h \ + decoder/decoder.h decoder/instr.h decoder/fetchdecode.h \ + decoder/ia_opcodes.h decoder/ia_opcodes.def decoder/fetchdecode_opmap.h \ + decoder/fetchdecode_opmap_0f38.h decoder/fetchdecode_opmap_0f3a.h \ + decoder/fetchdecode_x87.h decoder/fetchdecode_avx.h \ + decoder/fetchdecode_xop.h decoder/fetchdecode_evex.h ../cpu/simd_int.h \ ../cpu/simd_pfp.h ../cpu/simd_compare.h ../cpu/simd_vnni.h -decoder/fetchdecode64.o: decoder/fetchdecode64.@CPP_SUFFIX@ ../bochs.h ../config.h \ +fetchdecode64.o: decoder/fetchdecode64.@CPP_SUFFIX@ ../bochs.h ../config.h \ ../osdep.h ../logio.h ../misc/bswap.h decoder/instr.h decoder/decoder.h \ decoder/features.h decoder/fetchdecode.h decoder/ia_opcodes.h \ decoder/ia_opcodes.def decoder/fetchdecode_opmap.h \ diff --git a/bochs/cpu/apic.cc b/bochs/cpu/apic.cc index 434b8fdbd5..bedd06f18f 100644 --- a/bochs/cpu/apic.cc +++ b/bochs/cpu/apic.cc @@ -687,7 +687,7 @@ void bx_local_apic_c::send_ipi(apic_dest_t dest, Bit32u lo_cmd) accepted = apic_bus_broadcast_interrupt(vector, delivery_mode, trig_mode, get_id()); break; default: - BX_PANIC(("Invalid desination shorthand %#x", dest_shorthand)); + BX_PANIC(("Invalid destination shorthand %#x", dest_shorthand)); } if(! accepted) { diff --git a/bochs/cpu/avx/Makefile.in b/bochs/cpu/avx/Makefile.in index faf22fb061..633ca946f7 100644 --- a/bochs/cpu/avx/Makefile.in +++ b/bochs/cpu/avx/Makefile.in @@ -101,242 +101,325 @@ amx.o: amx.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h amx.h \ - ../../cpu/xmm.h bf16.h ../fpu/softfloat-specialize.h ../fpu/softfloat.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h amx.h ../../cpu/xmm.h \ + bf16.h ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h avx.o: avx.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h ../../logio.h \ ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../simd_int.h avx2.o: avx2.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h ../../logio.h \ ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../simd_int.h avx512.o: avx512.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h ../simd_compare.h \ - ../scalar_arith.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../simd_int.h \ + ../simd_compare.h ../scalar_arith.h avx512_bf16.o: avx512_bf16.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h bf16.h \ - ../fpu/softfloat-specialize.h ../fpu/softfloat.h ../simd_int.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h bf16.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h ../simd_int.h avx512_bitalg.o: avx512_bitalg.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../simd_int.h \ ../scalar_arith.h avx512_broadcast.o: avx512_broadcast.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../simd_int.h avx512_cvt.o: avx512_cvt.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h -avx512_cvt16.o: avx512_cvt16.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ - ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ - ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../simd_int.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h +avx512_cvt16.o: avx512_cvt16.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ + ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ + ../../bx_debug/debug.h ../../config.h ../../osdep.h \ + ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ + ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h ../simd_int.h avx512_fma.o: avx512_fma.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h ../simd_pfp.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h ../simd_int.h ../simd_pfp.h avx512_helpers.o: avx512_helpers.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../simd_int.h avx512_mask16.o: avx512_mask16.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h avx512_mask32.o: avx512_mask32.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h avx512_mask64.o: avx512_mask64.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h avx512_mask8.o: avx512_mask8.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h avx512_move.o: avx512_move.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../simd_int.h avx512_pfp.o: avx512_pfp.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h \ - ../fpu/softfloat.h ../simd_int.h ../simd_pfp.h \ - ../fpu/softfloat-specialize.h -avx512_pfp16.o: avx512_pfp16.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ - ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ - ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h \ - ../fpu/softfloat.h ../simd_int.h ../simd_pfp.h \ - ../fpu/softfloat-specialize.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat-compare.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h ../simd_int.h ../simd_pfp.h \ + ../fpu/softfloat-specialize.h \ + ../fpu/../softfloat3e/include/softfloat_types.h +avx512_pfp16.o: avx512_pfp16.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ + ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ + ../../bx_debug/debug.h ../../config.h ../../osdep.h \ + ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ + ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat-compare.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h ../simd_int.h \ + ../simd_pfp.h ../fpu/softfloat-specialize.h \ + ../fpu/../softfloat3e/include/softfloat_types.h \ + ../../cpu/decoder/ia_opcodes.h ../../cpu/decoder/ia_opcodes.def avx512_rcp14.o: avx512_rcp14.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h \ - ../fpu/softfloat-specialize.h ../fpu/softfloat.h \ - ../fpu/softfloat-round-pack.h ../simd_int.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h ../fpu/softfloat-specialize.h \ + ../fpu/../softfloat3e/include/softfloat_types.h ../simd_int.h avx512_rsqrt14.o: avx512_rsqrt14.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h \ - ../fpu/softfloat-specialize.h ../fpu/softfloat.h \ - ../fpu/softfloat-round-pack.h ../simd_int.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h ../fpu/softfloat-specialize.h \ + ../fpu/../softfloat3e/include/softfloat_types.h ../simd_int.h avx_cvt.o: avx_cvt.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h avx_fma.o: avx_fma.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_pfp.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h ../simd_pfp.h avx_ifma52.o: avx_ifma52.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h ../wide_int.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../wide_int.h avx_ne_convert.o: avx_ne_convert.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h bf16.h \ - ../fpu/softfloat-specialize.h ../fpu/softfloat.h ../simd_int.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h bf16.h ../simd_int.h avx_pfp.o: avx_pfp.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h \ - ../fpu/softfloat.h ../simd_pfp.h ../simd_int.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat-compare.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h ../simd_pfp.h \ + ../simd_int.h gather.o: gather.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h tbm32.o: tbm32.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h ../scalar_arith.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../scalar_arith.h tbm64.o: tbm64.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../stack.h ../access.h ../scalar_arith.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h ../scalar_arith.h xop.o: xop.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h ../../logio.h \ ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../stack.h ../access.h ../simd_int.h \ - ../simd_compare.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../stack.h ../access.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h ../simd_int.h ../simd_compare.h diff --git a/bochs/cpu/avx/amx.cc b/bochs/cpu/avx/amx.cc index a2a02a1efe..175f9bad35 100644 --- a/bochs/cpu/avx/amx.cc +++ b/bochs/cpu/avx/amx.cc @@ -117,7 +117,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::TILELOADD_TnnnMdq(bxInstruction_c *i) } if (BX_CPU_THIS_PTR amx->start_row >= rows) { - BX_ERROR(("%s: invalid (start_row=%d) >= (rows=%d)", i->getIaOpcodeNameShort(), tile, BX_CPU_THIS_PTR amx->start_row, rows)); + BX_ERROR(("%s: invalid tile %d (start_row=%d) >= (rows=%d)", i->getIaOpcodeNameShort(), tile, BX_CPU_THIS_PTR amx->start_row, rows)); exception(BX_UD_EXCEPTION, 0); } @@ -177,7 +177,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::TILESTORED_MdqTnnn(bxInstruction_c *i) } if (BX_CPU_THIS_PTR amx->start_row >= rows) { - BX_ERROR(("TILESTORED: invalid (start_row=%d) >= (rows=%d)", tile, BX_CPU_THIS_PTR amx->start_row, rows)); + BX_ERROR(("TILESTORED: invalid tile %d (start_row=%d) >= (rows=%d)", tile, BX_CPU_THIS_PTR amx->start_row, rows)); exception(BX_UD_EXCEPTION, 0); } @@ -488,7 +488,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::TDPBUUD_TnnnTrmTreg(bxInstruction_c *i) #include "bf16.h" -extern float_status_t prepare_ne_softfloat_status_helper(); +extern softfloat_status_t prepare_ne_softfloat_status_helper(); void BX_CPP_AttrRegparmN(1) BX_CPU_C::TDPBF16PS_TnnnTrmTreg(bxInstruction_c *i) { @@ -509,8 +509,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::TDPBF16PS_TnnnTrmTreg(bxInstruction_c *i) // "round to nearest even" rounding mode is used when doing each accumulation of the FMA. // output denormals are always flushed to zero and input denormals are always treated as zero. - float_status_t status = prepare_ne_softfloat_status_helper(); - status.denormals_are_zeros = true; + softfloat_status_t status = prepare_ne_softfloat_status_helper(); + status.softfloat_denormals_are_zeros = true; for (unsigned m=0; m < max_m; m++) { float32 tmp[32]; // new empty array @@ -564,8 +564,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::TDPFP16PS_TnnnTrmTreg(bxInstruction_c *i) // "round to nearest even" rounding mode is used when doing each accumulation of the FMA. // output FP32 denormals are always flushed to zero and input denormals are always treated as zero. - float_status_t status = prepare_ne_softfloat_status_helper(); - status.denormals_are_zeros = true; + softfloat_status_t status = prepare_ne_softfloat_status_helper(); + status.softfloat_denormals_are_zeros = true; for (unsigned m=0; m < max_m; m++) { float32 tmp[32]; // new empty array @@ -617,8 +617,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::TCMMRLFP16PS_TnnnTrmTreg(bxInstruction_c * // "round to nearest even" rounding mode is used when doing each accumulation of the FMA. // output FP32 denormals are always flushed to zero and input denormals are always treated as zero. - float_status_t status = prepare_ne_softfloat_status_helper(); - status.denormals_are_zeros = true; + softfloat_status_t status = prepare_ne_softfloat_status_helper(); + status.softfloat_denormals_are_zeros = true; for (unsigned m=0; m < max_m; m++) { float32 tmp[32]; // new empty array @@ -670,8 +670,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::TCMMIMFP16PS_TnnnTrmTreg(bxInstruction_c * // "round to nearest even" rounding mode is used when doing each accumulation of the FMA. // output FP32 denormals are always flushed to zero and input denormals are always treated as zero. - float_status_t status = prepare_ne_softfloat_status_helper(); - status.denormals_are_zeros = true; + softfloat_status_t status = prepare_ne_softfloat_status_helper(); + status.softfloat_denormals_are_zeros = true; for (unsigned m=0; m < max_m; m++) { float32 tmp[32]; // new empty array diff --git a/bochs/cpu/avx/avx512_bf16.cc b/bochs/cpu/avx/avx512_bf16.cc index ee1a8d2714..9e53258745 100644 --- a/bochs/cpu/avx/avx512_bf16.cc +++ b/bochs/cpu/avx/avx512_bf16.cc @@ -78,7 +78,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTNE2PS2BF16_MASK_Vbf16HpsWpsR(bxInstruc BX_NEXT_INSTR(i); } -extern float_status_t prepare_ne_softfloat_status_helper(); +extern softfloat_status_t prepare_ne_softfloat_status_helper(); void BX_CPP_AttrRegparmN(1) BX_CPU_C::VDPBF16PS_MASK_VpsHdqWdqR(bxInstruction_c *i) { @@ -88,8 +88,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VDPBF16PS_MASK_VpsHdqWdqR(bxInstruction_c // "round to nearest even" rounding mode is used when doing each accumulation of the FMA. // output denormals are always flushed to zero and input denormals are always treated as zero. - float_status_t status = prepare_ne_softfloat_status_helper(); - status.denormals_are_zeros = true; + softfloat_status_t status = prepare_ne_softfloat_status_helper(); + status.softfloat_denormals_are_zeros = true; for (unsigned n=0, tmp_mask = mask; n < DWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { if (tmp_mask & 0x1) { diff --git a/bochs/cpu/avx/avx512_cvt.cc b/bochs/cpu/avx/avx512_cvt.cc index aaee882b43..bca6d5cad9 100644 --- a/bochs/cpu/avx/avx512_cvt.cc +++ b/bochs/cpu/avx/avx512_cvt.cc @@ -28,20 +28,22 @@ #if BX_SUPPORT_EVEX -extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); #include "simd_int.h" +#include "softfloat3e/include/softfloat.h" + // scalar void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSS2USI_GdWssR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32u result = f32_to_ui32(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), result); BX_NEXT_INSTR(i); @@ -51,10 +53,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSS2USI_GqWssR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64u result = f32_to_ui64(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), result); BX_NEXT_INSTR(i); @@ -64,10 +66,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTSS2USI_GdWssR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32u result = f32_to_ui32_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), result); BX_NEXT_INSTR(i); @@ -77,10 +79,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTSS2USI_GqWssR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64u result = f32_to_ui64_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), result); BX_NEXT_INSTR(i); @@ -90,10 +92,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSD2USI_GdWsdR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32u result = f64_to_ui32(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), result); BX_NEXT_INSTR(i); @@ -103,10 +105,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSD2USI_GqWsdR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64u result = f64_to_ui64(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), result); BX_NEXT_INSTR(i); @@ -116,10 +118,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTSD2USI_GdWsdR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32u result = f64_to_ui32_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), result); BX_NEXT_INSTR(i); @@ -129,10 +131,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTSD2USI_GqWsdR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64u result = f64_to_ui64_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), result); BX_NEXT_INSTR(i); @@ -142,10 +144,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTUSI2SS_VssEdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = ui32_to_f32(BX_READ_32BIT_REG(i->src2()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -155,10 +157,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTUSI2SS_VssEqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = ui64_to_f32(BX_READ_64BIT_REG(i->src2()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -177,10 +179,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTUSI2SD_VsdEqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = ui64_to_f64(BX_READ_64BIT_REG(i->src2()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -192,10 +194,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSD2SS_MASK_VssWsdR(bxInstruction_c *i) if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = f64_to_f32(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -214,10 +216,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSS2SD_MASK_VsdWssR(bxInstruction_c *i) if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = f32_to_f64(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -238,14 +240,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSS2SD_MASK_VsdWssR(bxInstruction_c *i) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()), result; \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { \ result.vmm32u(n) = (func)(op.vmm64u(n), &status); \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (len == BX_VL128) { \ BX_WRITE_XMM_REG_LO_QWORD_CLEAR_HIGH(i->dst(), result.vmm64u(0)); \ @@ -268,7 +270,7 @@ AVX512_CVT64_TO_32(VCVTUQQ2PS_VpsWdqR, ui64_to_f32) unsigned opmask = BX_READ_8BIT_OPMASK(i->opmask()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < QWORD_ELEMENTS(len); n++, opmask >>= 1) { \ @@ -278,7 +280,7 @@ AVX512_CVT64_TO_32(VCVTUQQ2PS_VpsWdqR, ui64_to_f32) result.vmm32u(n) = 0; \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (len == BX_VL128) { \ BX_WRITE_XMM_REG_LO_QWORD_CLEAR_HIGH(i->dst(), result.vmm64u(0)); \ @@ -303,14 +305,14 @@ AVX512_CVT64_TO_32_MASK(VCVTUQQ2PS_MASK_VpsWdqR, ui64_to_f32) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { \ op.vmm32u(n) = (func)(op.vmm32u(n), &status); \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ BX_WRITE_AVX_REGZ(i->dst(), op, len); \ BX_NEXT_INSTR(i); \ } @@ -326,7 +328,7 @@ AVX512_CVT32_TO_32(VCVTUDQ2PS_VpsWdqR, ui32_to_f32) unsigned len = i->getVL(); \ Bit32u opmask = BX_READ_16BIT_OPMASK(i->opmask()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0, mask = 0x1; n < DWORD_ELEMENTS(len); n++, mask <<= 1) { \ @@ -336,7 +338,7 @@ AVX512_CVT32_TO_32(VCVTUDQ2PS_VpsWdqR, ui32_to_f32) op.vmm32u(n) = 0; \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (! i->isZeroMasking()) { \ for (unsigned n=0; n < len; n++, opmask >>= 4) \ @@ -363,14 +365,14 @@ AVX512_CVT32_TO_32_MASK(VCVTUDQ2PS_MASK_VpsWdqR, ui32_to_f32) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { \ op.vmm64s(n) = (func)(op.vmm64u(n), &status); \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ BX_WRITE_AVX_REGZ(i->dst(), op, len); \ BX_NEXT_INSTR(i); \ } @@ -389,7 +391,7 @@ AVX512_CVT64_TO_64(VCVTUQQ2PD_VpdWdqR, ui64_to_f64) unsigned len = i->getVL(); \ Bit32u opmask = BX_READ_8BIT_OPMASK(i->opmask()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0, mask = 0x1; n < QWORD_ELEMENTS(len); n++, mask <<= 1) { \ @@ -399,7 +401,7 @@ AVX512_CVT64_TO_64(VCVTUQQ2PD_VpdWdqR, ui64_to_f64) op.vmm64u(n) = 0; \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (! i->isZeroMasking()) { \ for (unsigned n=0; n < len; n++, opmask >>= 2) \ @@ -427,14 +429,14 @@ AVX512_CVT64_TO_64_MASK(VCVTUQQ2PD_MASK_VpdWdqR, ui64_to_f64) BxPackedYmmRegister op = BX_READ_YMM_REG(i->src()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { \ result.vmm64u(n) = (func)(op.ymm32u(n), &status); \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_AVX_REGZ(i->dst(), result, len); \ BX_NEXT_INSTR(i); \ @@ -453,7 +455,7 @@ AVX512_CVT32_TO_64(VCVTTPS2UQQ_VdqWpsR, f32_to_ui64_round_to_zero) unsigned opmask = BX_READ_8BIT_OPMASK(i->opmask()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0, tmp_mask = opmask; n < QWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { \ @@ -463,7 +465,7 @@ AVX512_CVT32_TO_64(VCVTTPS2UQQ_VdqWpsR, f32_to_ui64_round_to_zero) result.vmm64u(n) = 0; \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (! i->isZeroMasking()) { \ for (unsigned n=0; n < len; n++, opmask >>= 2) \ @@ -559,10 +561,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPH2PS_MASK_VpsWpsR(bxInstruction_c *i) else result = BX_READ_AVX_REG(i->dst()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); - status.denormals_are_zeros = 0; // ignore MXCSR.DAZ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + status.softfloat_denormals_are_zeros = 0; // ignore MXCSR.DAZ // no denormal exception is reported on MXCSR - status.float_suppress_exception = float_flag_denormal; + status.softfloat_suppressException = softfloat_flag_denormal; Bit32u opmask = BX_READ_16BIT_OPMASK(i->opmask()); @@ -571,7 +573,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPH2PS_MASK_VpsWpsR(bxInstruction_c *i) result.vmm32u(n) = f16_to_f32(op.ymm16u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); @@ -581,15 +583,15 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPS2PH_MASK_WpsVpsIbR(bxInstruction_c * { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()), dst = BX_READ_AVX_REG(i->dst()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); unsigned len = i->getVL(); Bit8u control = i->Ib(); - status.flush_underflow_to_zero = 0; // ignore MXCSR.FUZ + status.softfloat_flush_underflow_to_zero = 0; // ignore MXCSR.FUZ // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) - status.float_rounding_mode = control & 0x3; + status.softfloat_roundingMode = control & 0x3; Bit32u opmask = BX_READ_16BIT_OPMASK(i->opmask()); @@ -600,7 +602,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPS2PH_MASK_WpsVpsIbR(bxInstruction_c * dst.vmm16u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (len == BX_VL128) { BX_WRITE_XMM_REG_LO_QWORD_CLEAR_HIGH(i->dst(), dst.vmm64u(0)); @@ -616,15 +618,15 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPS2PH_MASK_WpsVpsIbM(bxInstruction_c * { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()), result; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); unsigned len = i->getVL(); Bit8u control = i->Ib(); - status.flush_underflow_to_zero = 0; // ignore MXCSR.FUZ + status.softfloat_flush_underflow_to_zero = 0; // ignore MXCSR.FUZ // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) - status.float_rounding_mode = control & 0x3; + status.softfloat_roundingMode = control & 0x3; Bit32u opmask = BX_READ_16BIT_OPMASK(i->opmask()); opmask &= CUT_OPMASK_TO(DWORD_ELEMENTS(len)); @@ -634,7 +636,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPS2PH_MASK_WpsVpsIbM(bxInstruction_c * result.vmm16u(n) = f32_to_f16(op.vmm32u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); bx_address eaddr = BX_CPU_RESOLVE_ADDR(i); avx_masked_store16(i, eaddr, &result, opmask); diff --git a/bochs/cpu/avx/avx512_cvt16.cc b/bochs/cpu/avx/avx512_cvt16.cc index 8d3fc51c9a..e76936d577 100644 --- a/bochs/cpu/avx/avx512_cvt16.cc +++ b/bochs/cpu/avx/avx512_cvt16.cc @@ -28,10 +28,10 @@ #if BX_SUPPORT_EVEX -extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +#include "softfloat3e/include/softfloat.h" #include "simd_int.h" -#include "fpu/softfloat16.h" // scalar @@ -40,10 +40,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSD2SH_VshWsdR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = f64_to_f16(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -55,10 +55,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSD2SH_MASK_VshWsdR(bxInstruction_c *i) if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = f64_to_f16(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -76,10 +76,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSS2SH_VshWssR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = f32_to_f16(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -91,10 +91,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSS2SH_MASK_VshWssR(bxInstruction_c *i) if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = f32_to_f16(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -112,10 +112,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSH2SD_VsdWshR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = f16_to_f64(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -127,10 +127,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSH2SD_MASK_VsdWshR(bxInstruction_c *i) if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = f16_to_f64(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -148,10 +148,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSH2SS_VssWshR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = f16_to_f32(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -163,10 +163,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSH2SS_MASK_VssWshR(bxInstruction_c *i) if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = f16_to_f32(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -183,10 +183,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSH2SI_GdWshR(bxInstruction_c *i) { float16 op = BX_READ_XMM_REG_LO_WORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32s result = f16_to_i32(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) result); BX_NEXT_INSTR(i); @@ -196,10 +196,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSH2SI_GqWshR(bxInstruction_c *i) { float16 op = BX_READ_XMM_REG_LO_WORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64s result = f16_to_i64(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), (Bit64u) result); BX_NEXT_INSTR(i); @@ -209,10 +209,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSH2USI_GdWshR(bxInstruction_c *i) { float16 op = BX_READ_XMM_REG_LO_WORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32u result = f16_to_ui32(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), result); BX_NEXT_INSTR(i); @@ -222,10 +222,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSH2USI_GqWshR(bxInstruction_c *i) { float16 op = BX_READ_XMM_REG_LO_WORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64u result = f16_to_ui64(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), result); BX_NEXT_INSTR(i); @@ -235,10 +235,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTSH2SI_GdWshR(bxInstruction_c *i) { float16 op = BX_READ_XMM_REG_LO_WORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32s result = f16_to_i32_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) result); BX_NEXT_INSTR(i); @@ -248,10 +248,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTSH2SI_GqWshR(bxInstruction_c *i) { float16 op = BX_READ_XMM_REG_LO_WORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64s result = f16_to_i64_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), (Bit64u) result); BX_NEXT_INSTR(i); @@ -261,10 +261,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTSH2USI_GdWshR(bxInstruction_c *i) { float16 op = BX_READ_XMM_REG_LO_WORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32u result = f16_to_ui32_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), result); BX_NEXT_INSTR(i); @@ -274,10 +274,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTSH2USI_GqWshR(bxInstruction_c *i) { float16 op = BX_READ_XMM_REG_LO_WORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64u result = f16_to_ui64_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), result); BX_NEXT_INSTR(i); @@ -287,10 +287,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSI2SH_VshEdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = i32_to_f16(BX_READ_32BIT_REG(i->src2()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -300,10 +300,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSI2SH_VshEqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = i64_to_f16(BX_READ_64BIT_REG(i->src2()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -313,10 +313,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTUSI2SH_VshEdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = ui32_to_f16(BX_READ_32BIT_REG(i->src2()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -326,10 +326,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTUSI2SH_VshEqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = ui64_to_f16(BX_READ_64BIT_REG(i->src2()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -346,14 +346,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTUSI2SH_VshEqR(bxInstruction_c *i) BxPackedXmmRegister result; \ result.xmm64u(0) = 0; \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { \ result.xmm16u(n) = (func)(op.vmm64u(n), &status); \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (len != BX_VL512) { \ BX_WRITE_XMM_REG_LO_QWORD_CLEAR_HIGH(i->dst(), result.xmm64u(0)); \ @@ -376,7 +376,7 @@ AVX512_CVT64_TO_16(VCVTUQQ2PH_VphWdqR, ui64_to_f16) unsigned opmask = BX_READ_8BIT_OPMASK(i->opmask()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < QWORD_ELEMENTS(len); n++, opmask >>= 1) { \ @@ -386,7 +386,7 @@ AVX512_CVT64_TO_16(VCVTUQQ2PH_VphWdqR, ui64_to_f16) result.xmm16u(n) = 0; \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (len == BX_VL128) { \ BX_WRITE_XMM_REG_LO_DWORD_CLEAR_HIGH(i->dst(), result.xmm32u(0)); \ @@ -409,14 +409,14 @@ AVX512_CVT64_TO_16_MASK(VCVTUQQ2PH_MASK_VphWdqR, ui64_to_f16) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()), result; \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { \ result.vmm16u(n) = (func)(op.vmm32u(n), &status); \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (len == BX_VL128) { \ BX_WRITE_XMM_REG_LO_QWORD_CLEAR_HIGH(i->dst(), result.vmm64u(0)); \ @@ -438,7 +438,7 @@ AVX512_CVT32_TO_16(VCVTUDQ2PH_VphWdqR, ui32_to_f16) unsigned opmask = BX_READ_16BIT_OPMASK(i->opmask()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < DWORD_ELEMENTS(len); n++, opmask >>= 1) { \ @@ -448,7 +448,7 @@ AVX512_CVT32_TO_16(VCVTUDQ2PH_VphWdqR, ui32_to_f16) result.vmm16u(n) = 0; \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (len == BX_VL128) { \ BX_WRITE_XMM_REG_LO_QWORD_CLEAR_HIGH(i->dst(), result.vmm64u(0)); \ @@ -469,14 +469,14 @@ AVX512_CVT32_TO_16_MASK(VCVTUDQ2PH_MASK_VphWdqR, ui32_to_f16) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < WORD_ELEMENTS(len); n++) { \ op.vmm16u(n) = (func)(op.vmm16u(n), &status); \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ BX_WRITE_AVX_REGZ(i->dst(), op, len); \ BX_NEXT_INSTR(i); \ } @@ -495,7 +495,7 @@ AVX512_CVT16_TO_16(VCVTW2PH_VphWdqR, i16_to_f16) unsigned len = i->getVL(); \ Bit32u opmask = BX_READ_32BIT_OPMASK(i->opmask()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0, mask = 0x1; n < WORD_ELEMENTS(len); n++, mask <<= 1) { \ @@ -505,7 +505,7 @@ AVX512_CVT16_TO_16(VCVTW2PH_VphWdqR, i16_to_f16) op.vmm16u(n) = 0; \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (! i->isZeroMasking()) { \ for (unsigned n=0; n < len; n++, opmask >>= 8) \ @@ -533,14 +533,14 @@ AVX512_CVT16_TO_16_MASK(VCVTW2PH_MASK_VphWdqR, i16_to_f16) BxPackedYmmRegister op = BX_READ_YMM_REG(i->src()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { \ result.vmm32u(n) = (func)(op.ymm16u(n), &status); \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_AVX_REGZ(i->dst(), result, len); \ BX_NEXT_INSTR(i); \ @@ -560,7 +560,7 @@ AVX512_CVT16_TO_32(VCVTTPH2UDQ_VdqWphR, f16_to_ui32_round_to_zero) unsigned opmask = BX_READ_16BIT_OPMASK(i->opmask()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0, tmp_mask = opmask; n < DWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { \ @@ -570,7 +570,7 @@ AVX512_CVT16_TO_32(VCVTTPH2UDQ_VdqWphR, f16_to_ui32_round_to_zero) result.vmm32u(n) = 0; \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (! i->isZeroMasking()) { \ for (unsigned n=0; n < len; n++, opmask >>= 4) \ @@ -597,14 +597,14 @@ AVX512_CVT16_TO_32_MASK(VCVTTPH2UDQ_MASK_VdqWphR, f16_to_ui32_round_to_zero) BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { \ result.vmm64u(n) = (func)(op.xmm16u(n), &status); \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_AVX_REGZ(i->dst(), result, len); \ BX_NEXT_INSTR(i); \ @@ -624,7 +624,7 @@ AVX512_CVT16_TO_64(VCVTTPH2UQQ_VdqWphR, f16_to_ui64_round_to_zero) unsigned opmask = BX_READ_8BIT_OPMASK(i->opmask()); \ unsigned len = i->getVL(); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ for (unsigned n=0, tmp_mask = opmask; n < QWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { \ @@ -634,7 +634,7 @@ AVX512_CVT16_TO_64(VCVTTPH2UQQ_VdqWphR, f16_to_ui64_round_to_zero) result.vmm64u(n) = 0; \ } \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ if (! i->isZeroMasking()) { \ for (unsigned n=0; n < len; n++, opmask >>= 2) \ diff --git a/bochs/cpu/avx/avx512_fma.cc b/bochs/cpu/avx/avx512_fma.cc index 0da1c944e0..6d3d0124a6 100644 --- a/bochs/cpu/avx/avx512_fma.cc +++ b/bochs/cpu/avx/avx512_fma.cc @@ -28,7 +28,7 @@ #if BX_SUPPORT_EVEX -extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); #include "softfloat3e/include/softfloat.h" #include "simd_int.h" @@ -46,10 +46,10 @@ extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); \ float32 op3 = BX_READ_XMM_REG_LO_DWORD(i->src3()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ op1 = (func)(op1, op2, op3, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); \ } \ @@ -75,10 +75,10 @@ EVEX_FMA_SCALAR_SINGLE(VFNMSUBSS_MASK_VpsHssWssR, f32_fnmsub) float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); \ float64 op3 = BX_READ_XMM_REG_LO_QWORD(i->src3()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ op1 = (func)(op1, op2, op3, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); \ } \ @@ -108,10 +108,10 @@ EVEX_FMA_SCALAR_DOUBLE(VFNMSUBSD_MASK_VpdHsdWsdR, f64_fnmsub) float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); \ float16 op3 = BX_READ_XMM_REG_LO_WORD(i->src3()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ op1 = (func)(op1, op2, op3, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_XMM_REG_LO_WORD(i->dst(), op1); \ } \ diff --git a/bochs/cpu/avx/avx512_pfp.cc b/bochs/cpu/avx/avx512_pfp.cc index 8775493ddb..6d223f968c 100644 --- a/bochs/cpu/avx/avx512_pfp.cc +++ b/bochs/cpu/avx/avx512_pfp.cc @@ -28,8 +28,8 @@ #if BX_SUPPORT_EVEX -extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); -extern void mxcsr_to_softfloat_status_word_imm_override(float_status_t &status, Bit8u immb); +extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +extern void mxcsr_to_softfloat_status_word_imm_override(softfloat_status_t &status, Bit8u immb); #include "softfloat3e/include/softfloat-compare.h" #include "simd_int.h" @@ -43,10 +43,10 @@ extern void mxcsr_to_softfloat_status_word_imm_override(float_status_t &status, if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { \ float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ op1.xmm32u(0) = (func)(op1.xmm32u(0), op2, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ } \ else { \ if (i->isZeroMasking()) \ @@ -75,10 +75,10 @@ EVEX_OP_SCALAR_SINGLE(VSCALEFSS_MASK_VssHpsWssR, f32_scalef) if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { \ float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ op1.xmm64u(0) = (func)(op1.xmm64u(0), op2, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ } \ else { \ if (i->isZeroMasking()) \ @@ -106,10 +106,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VSQRTSS_MASK_VssHpsWssR(bxInstruction_c *i if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = f32_sqrt(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -129,10 +129,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VSQRTSD_MASK_VsdHpdWsdR(bxInstruction_c *i if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = f64_sqrt(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -158,7 +158,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPS_MASK_KGwHpsWpsIbR(bxInstruction_c * Bit32u opmask = i->opmask() ? BX_READ_16BIT_OPMASK(i->opmask()) : (Bit32u) -1; Bit32u result = 0; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int ib = i->Ib() & 0x1F; @@ -168,7 +168,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPS_MASK_KGwHpsWpsIbR(bxInstruction_c * } } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_OPMASK(i->dst(), result); BX_NEXT_INSTR(i); @@ -182,7 +182,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPD_MASK_KGbHpdWpdIbR(bxInstruction_c * Bit32u opmask = i->opmask() ? BX_READ_8BIT_OPMASK(i->opmask()) : (Bit32u) -1; Bit32u result = 0; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int ib = i->Ib() & 0x1F; @@ -192,7 +192,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPD_MASK_KGbHpdWpdIbR(bxInstruction_c * } } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_OPMASK(i->dst(), result); BX_NEXT_INSTR(i); @@ -206,10 +206,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPSD_MASK_KGbHsdWsdIbR(bxInstruction_c * float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); if (avx_compare64[i->Ib() & 0x1F](op1, op2, &status)) result = 1; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } BX_WRITE_OPMASK(i->dst(), result); @@ -224,10 +224,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPSS_MASK_KGbHssWssIbR(bxInstruction_c * float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); if (avx_compare32[i->Ib() & 0x1F](op1, op2, &status)) result = 1; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } BX_WRITE_OPMASK(i->dst(), result); @@ -257,7 +257,7 @@ const float64 float64_value_90 = BX_CONST64(0x4056800000000000); const float64 float64_pi_half = BX_CONST64(0x3ff921fb54442d18); const float64 float64_positive_half = BX_CONST64(0x3fe0000000000000); -float32 float32_fixupimm(float32 dst, float32 op1, Bit32u op2, unsigned imm8, float_status_t &status) +float32 float32_fixupimm(float32 dst, float32 op1, Bit32u op2, unsigned imm8, softfloat_status_t &status) { float32 tmp_op1 = op1; if (softfloat_denormalsAreZeros(&status)) @@ -317,10 +317,10 @@ float32 float32_fixupimm(float32 dst, float32 op1, Bit32u op2, unsigned imm8, fl } if (imm8 & ie_fault_mask) - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); if (imm8 & divz_fault_mask) - float_raise(status, float_flag_divbyzero); + softfloat_raiseFlags(&status, softfloat_flag_divbyzero); // access response table, each response is encoded with 4-bit value in the op2 unsigned token_response = (op2 >> (token*4)) & 0xf; @@ -352,7 +352,7 @@ float32 float32_fixupimm(float32 dst, float32 op1, Bit32u op2, unsigned imm8, fl return op1; } -float64 float64_fixupimm(float64 dst, float64 op1, Bit32u op2, unsigned imm8, float_status_t &status) +float64 float64_fixupimm(float64 dst, float64 op1, Bit32u op2, unsigned imm8, softfloat_status_t &status) { float64 tmp_op1 = op1; if (softfloat_denormalsAreZeros(&status)) @@ -412,10 +412,10 @@ float64 float64_fixupimm(float64 dst, float64 op1, Bit32u op2, unsigned imm8, fl } if (imm8 & ie_fault_mask) - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); if (imm8 & divz_fault_mask) - float_raise(status, float_flag_divbyzero); + softfloat_raiseFlags(&status, softfloat_flag_divbyzero); // access response table, each response is encoded with 4-bit value in the op2 unsigned token_response = (op2 >> (token*4)) & 0xf; @@ -455,10 +455,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFIXUPIMMSS_MASK_VssHssWssIbR(bxInstructio if (i->opmask() == 0 || BX_SCALAR_ELEMENT_MASK(i->opmask())) { Bit32u op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = float32_fixupimm(op_dst, op1.xmm32u(0), op2, i->Ib(), status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -479,10 +479,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFIXUPIMMSD_MASK_VsdHsdWsdIbR(bxInstructio if (i->opmask() == 0 || BX_SCALAR_ELEMENT_MASK(i->opmask())) { Bit32u op2 = (Bit32u) BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = float64_fixupimm(op_dst, op1.xmm64u(0), op2, i->Ib(), status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -500,14 +500,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFIXUPIMMPS_VpsHpsWpsIbR(bxInstruction_c * BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()), dst = BX_READ_AVX_REG(i->dst()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { op1.vmm32u(n) = float32_fixupimm(dst.vmm32u(n), op1.vmm32u(n), op2.vmm32u(n), i->Ib(), status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); @@ -519,7 +519,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFIXUPIMMPS_MASK_VpsHpsWpsIbR(bxInstructio Bit32u mask = BX_READ_16BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < DWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { @@ -529,7 +529,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFIXUPIMMPS_MASK_VpsHpsWpsIbR(bxInstructio op1.vmm32u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 4) @@ -549,14 +549,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFIXUPIMMPD_VpdHpdWpdIbR(bxInstruction_c * BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()), dst = BX_READ_AVX_REG(i->dst()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { op1.vmm64u(n) = float64_fixupimm(dst.vmm64u(n), op1.vmm64u(n), (Bit32u) op2.vmm64u(n), i->Ib(), status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); @@ -568,7 +568,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFIXUPIMMPD_MASK_VpdHpdWpdIbR(bxInstructio Bit32u mask = BX_READ_8BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < QWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { @@ -578,7 +578,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFIXUPIMMPD_MASK_VpdHpdWpdIbR(bxInstructio op1.vmm64u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 2) @@ -692,10 +692,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETEXPSS_VssHpsWssR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = f32_getExp(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -708,10 +708,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETEXPSS_MASK_VssHpsWssR(bxInstruction_c if (! i->opmask() || BX_SCALAR_ELEMENT_MASK(i->opmask())) { float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = f32_getExp(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -729,10 +729,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETEXPSD_VsdHpdWsdR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = f64_getExp(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -745,10 +745,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETEXPSD_MASK_VsdHpdWsdR(bxInstruction_c if (! i->opmask() || BX_SCALAR_ELEMENT_MASK(i->opmask())) { float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = f64_getExp(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -773,10 +773,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETMANTSS_MASK_VssHpsWssIbR(bxInstruction int sign_ctrl = (i->Ib() >> 2) & 0x3; int interv = i->Ib() & 0x3; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = f32_getMant(op2, &status, sign_ctrl, interv); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -799,10 +799,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETMANTSD_MASK_VsdHpdWsdIbR(bxInstruction int sign_ctrl = (i->Ib() >> 2) & 0x3; int interv = i->Ib() & 0x3; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = f64_getMant(op2, &status, sign_ctrl, interv); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -821,7 +821,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETMANTPS_MASK_VpsWpsIbR(bxInstruction_c Bit32u opmask = i->opmask() ? BX_READ_16BIT_OPMASK(i->opmask()) : (Bit32u) -1; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int sign_ctrl = (i->Ib() >> 2) & 0x3; @@ -834,7 +834,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETMANTPS_MASK_VpsWpsIbR(bxInstruction_c op.vmm32u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 4) @@ -854,7 +854,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETMANTPD_MASK_VpdWpdIbR(bxInstruction_c Bit32u opmask = i->opmask() ? BX_READ_8BIT_OPMASK(i->opmask()) : (Bit32u) -1; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int sign_ctrl = (i->Ib() >> 2) & 0x3; @@ -867,7 +867,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETMANTPD_MASK_VpdWpdIbR(bxInstruction_c op.vmm64u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 2) @@ -890,7 +890,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRNDSCALEPS_MASK_VpsWpsIbR(bxInstruction_c unsigned len = i->getVL(); Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); @@ -901,7 +901,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRNDSCALEPS_MASK_VpsWpsIbR(bxInstruction_c op.vmm32u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 4) @@ -924,13 +924,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRNDSCALESS_MASK_VssHpsWssIbR(bxInstructio Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); op1.xmm32u(0) = f32_roundToInt(op2, scale, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -951,7 +951,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRNDSCALEPD_MASK_VpdWpdIbR(bxInstruction_c Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); @@ -962,7 +962,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRNDSCALEPD_MASK_VpdWpdIbR(bxInstruction_c op.vmm64u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 2) @@ -985,13 +985,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRNDSCALESD_MASK_VsdHpdWsdIbR(bxInstructio Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); op1.xmm64u(0) = f64_roundToInt(op2, scale, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -1012,7 +1012,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRANGEPS_MASK_VpsHpsWpsIbR(bxInstruction_c Bit32u opmask = i->opmask() ? BX_READ_16BIT_OPMASK(i->opmask()) : (Bit32u) -1; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); bool is_max = i->Ib() & 0x1; @@ -1026,7 +1026,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRANGEPS_MASK_VpsHpsWpsIbR(bxInstruction_c op1.vmm32u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 4) @@ -1046,7 +1046,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRANGEPD_MASK_VpdHpdWpdIbR(bxInstruction_c Bit32u opmask = i->opmask() ? BX_READ_8BIT_OPMASK(i->opmask()) : (Bit32u) -1; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); bool is_max = i->Ib() & 0x1; @@ -1060,7 +1060,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRANGEPD_MASK_VpdHpdWpdIbR(bxInstruction_c op1.vmm64u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 2) @@ -1085,10 +1085,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRANGESS_MASK_VssHpsWssIbR(bxInstruction_c bool is_abs = (i->Ib() & 0x2) != 0; int sign_ctrl = (i->Ib() >> 2) & 0x3; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = f32_range(op1.xmm32u(0), op2, is_max, is_abs, sign_ctrl, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -1112,10 +1112,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRANGESD_MASK_VsdHpdWsdIbR(bxInstruction_c bool is_abs = (i->Ib() & 0x2) != 0; int sign_ctrl = (i->Ib() >> 2) & 0x3; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = f64_range(op1.xmm64u(0), op2, is_max, is_abs, sign_ctrl, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -1130,7 +1130,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRANGESD_MASK_VsdHpdWsdIbR(bxInstruction_c // reduce -static BX_CPP_INLINE float32 float32_reduce(float32 a, Bit8u scale, float_status_t &status) +static BX_CPP_INLINE float32 float32_reduce(float32 a, Bit8u scale, softfloat_status_t &status) { if (a == float32_negative_inf || a == float32_positive_inf) return 0; @@ -1139,7 +1139,7 @@ static BX_CPP_INLINE float32 float32_reduce(float32 a, Bit8u scale, float_status return f32_sub(a, tmp, &status); } -static BX_CPP_INLINE float64 float64_reduce(float64 a, Bit8u scale, float_status_t &status) +static BX_CPP_INLINE float64 float64_reduce(float64 a, Bit8u scale, softfloat_status_t &status) { if (a == float64_negative_inf || a == float64_positive_inf) return 0; @@ -1156,10 +1156,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VREDUCEPS_MASK_VpsWpsIbR(bxInstruction_c * Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); - status.float_suppress_exception |= float_flag_denormal | float_flag_underflow | float_flag_overflow; + status.softfloat_suppressException |= softfloat_flag_denormal | softfloat_flag_underflow | softfloat_flag_overflow; for (unsigned n=0, mask = 0x1; n < DWORD_ELEMENTS(len); n++, mask <<= 1) { if (opmask & mask) @@ -1168,7 +1168,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VREDUCEPS_MASK_VpsWpsIbR(bxInstruction_c * op.vmm32u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 4) @@ -1191,14 +1191,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VREDUCESS_MASK_VssHpsWssIbR(bxInstruction_ Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); - status.float_suppress_exception |= float_flag_denormal | float_flag_underflow | float_flag_overflow; + status.softfloat_suppressException |= softfloat_flag_denormal | softfloat_flag_underflow | softfloat_flag_overflow; op1.xmm32u(0) = float32_reduce(op2, scale, status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -1219,10 +1219,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VREDUCEPD_MASK_VpdWpdIbR(bxInstruction_c * Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); - status.float_suppress_exception |= float_flag_denormal | float_flag_underflow | float_flag_overflow; + status.softfloat_suppressException |= softfloat_flag_denormal | softfloat_flag_underflow | softfloat_flag_overflow; for (unsigned n=0, mask = 0x1; n < QWORD_ELEMENTS(len); n++, mask <<= 1) { if (opmask & mask) @@ -1231,7 +1231,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VREDUCEPD_MASK_VpdWpdIbR(bxInstruction_c * op.vmm64u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 2) @@ -1254,14 +1254,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VREDUCESD_MASK_VsdHpdWsdIbR(bxInstruction_ Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); - status.float_suppress_exception |= float_flag_denormal | float_flag_underflow | float_flag_overflow; + status.softfloat_suppressException |= softfloat_flag_denormal | softfloat_flag_underflow | softfloat_flag_overflow; op1.xmm64u(0) = float64_reduce(op2, scale, status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) diff --git a/bochs/cpu/avx/avx512_pfp16.cc b/bochs/cpu/avx/avx512_pfp16.cc index 4008d6a157..f1bcb13011 100644 --- a/bochs/cpu/avx/avx512_pfp16.cc +++ b/bochs/cpu/avx/avx512_pfp16.cc @@ -28,11 +28,10 @@ #if BX_SUPPORT_EVEX -extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); -extern void mxcsr_to_softfloat_status_word_imm_override(float_status_t &status, Bit8u immb); +extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +extern void mxcsr_to_softfloat_status_word_imm_override(softfloat_status_t &status, Bit8u immb); #include "softfloat3e/include/softfloat-compare.h" -#include "fpu/softfloat16.h" #include "simd_int.h" #include "simd_pfp.h" @@ -42,10 +41,10 @@ extern void mxcsr_to_softfloat_status_word_imm_override(float_status_t &status, BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); \ \ float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ op1.xmm16u(0) = (func)(op1.xmm16u(0), op2, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); \ BX_NEXT_INSTR(i); \ @@ -66,10 +65,10 @@ EVEX_OP_SCALAR_HALF(VSCALEFSH_VshHphWshR, f16_scalef) \ if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { \ float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ op1.xmm16u(0) = (func)(op1.xmm16u(0), op2, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ } \ else { \ if (i->isZeroMasking()) \ @@ -100,10 +99,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPSH_MASK_KGbHshWshIbR(bxInstruction_c * float16 op1 = BX_READ_XMM_REG_LO_WORD(i->src1()); float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); if (avx_compare16[i->Ib() & 0x1F](op1, op2, &status)) result = 1; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } BX_WRITE_OPMASK(i->dst(), result); @@ -118,7 +117,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPH_MASK_KGdHphWphIbR(bxInstruction_c * Bit32u opmask = i->opmask() ? BX_READ_32BIT_OPMASK(i->opmask()) : (Bit32u) -1; Bit32u result = 0; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int ib = i->Ib() & 0x1F; @@ -128,7 +127,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPH_MASK_KGdHphWphIbR(bxInstruction_c * } } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_OPMASK(i->dst(), result); BX_NEXT_INSTR(i); @@ -138,10 +137,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::UCOMISH_VshWshR(bxInstruction_c *i) { float16 op1 = BX_READ_XMM_REG_LO_WORD(i->dst()), op2 = BX_READ_XMM_REG_LO_WORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int rc = f16_compare_quiet(op1, op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); BX_NEXT_INSTR(i); @@ -151,10 +150,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::COMISH_VshWshR(bxInstruction_c *i) { float16 op1 = BX_READ_XMM_REG_LO_WORD(i->dst()), op2 = BX_READ_XMM_REG_LO_WORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int rc = f16_compare(op1, op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); BX_NEXT_INSTR(i); @@ -208,10 +207,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VSQRTSH_VshHphWshR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = f16_sqrt(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -224,10 +223,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VSQRTSH_MASK_VshHphWshR(bxInstruction_c *i if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = f16_sqrt(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -245,10 +244,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETEXPSH_VshHphWshR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = f16_getExp(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -261,10 +260,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETEXPSH_MASK_VshHphWshR(bxInstruction_c if (BX_SCALAR_ELEMENT_MASK(i->opmask())) { float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = f16_getExp(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -287,10 +286,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETMANTSH_MASK_VshHphWshIbR(bxInstruction int sign_ctrl = (i->Ib() >> 2) & 0x3; int interv = i->Ib() & 0x3; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm16u(0) = f16_getMant(op2, &status, sign_ctrl, interv); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -309,7 +308,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETMANTPH_MASK_VphWphIbR(bxInstruction_c Bit32u opmask = i->opmask() ? BX_READ_32BIT_OPMASK(i->opmask()) : (Bit32u) -1; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int sign_ctrl = (i->Ib() >> 2) & 0x3; @@ -322,7 +321,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETMANTPH_MASK_VphWphIbR(bxInstruction_c op.vmm16u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 8) @@ -336,7 +335,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGETMANTPH_MASK_VphWphIbR(bxInstruction_c BX_NEXT_INSTR(i); } -static BX_CPP_INLINE float16 float16_reduce(float16 a, Bit8u scale, float_status_t &status) +static BX_CPP_INLINE float16 float16_reduce(float16 a, Bit8u scale, softfloat_status_t &status) { if (a == float16_negative_inf || a == float16_positive_inf) return 0; @@ -352,10 +351,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VREDUCEPH_MASK_VphWphIbR(bxInstruction_c * unsigned len = i->getVL(); Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); - status.float_suppress_exception |= float_flag_denormal | float_flag_underflow | float_flag_overflow; + status.softfloat_suppressException |= softfloat_flag_denormal | softfloat_flag_underflow | softfloat_flag_overflow; for (unsigned n=0, mask = 0x1; n < WORD_ELEMENTS(len); n++, mask <<= 1) { if (opmask & mask) @@ -364,7 +363,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VREDUCEPH_MASK_VphWphIbR(bxInstruction_c * op.vmm16u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 8) @@ -387,14 +386,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VREDUCESH_MASK_VshHphWshIbR(bxInstruction_ Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); - status.float_suppress_exception |= float_flag_denormal | float_flag_underflow | float_flag_overflow; + status.softfloat_suppressException |= softfloat_flag_denormal | softfloat_flag_underflow | softfloat_flag_overflow; op1.xmm16u(0) = float16_reduce(op2, scale, status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -415,7 +414,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRNDSCALEPH_MASK_VphWphIbR(bxInstruction_c Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); @@ -426,7 +425,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRNDSCALEPH_MASK_VphWphIbR(bxInstruction_c op.vmm16u(n) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, opmask >>= 8) @@ -449,13 +448,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRNDSCALESH_MASK_VshHphWshIbR(bxInstructio Bit8u control = i->Ib(), scale = control >> 4; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); mxcsr_to_softfloat_status_word_imm_override(status, control); op1.xmm16u(0) = f16_roundToInt(op2, scale, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); } else { if (i->isZeroMasking()) @@ -481,9 +480,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFCMULCSH_MASK_VshHphWshR(bxInstruction_c dst.xmm32u(0) = BX_READ_XMM_REG_LO_DWORD(i->dst()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); - status.float_exception_masks = float_all_exceptions_mask; + status.softfloat_exceptionMasks = softfloat_all_exceptions_mask; int fma_control1 = (i->getIaOpcode() == BX_IA_V512_VFMULCSH_VshHphWsh_Kmask) ? softfloat_muladd_negate_product : 0; int fma_control2 = (i->getIaOpcode() == BX_IA_V512_VFMULCSH_VshHphWsh_Kmask) ? 0 : softfloat_muladd_negate_product; @@ -498,7 +497,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFCMULCSH_MASK_VshHphWshR(bxInstruction_c dst.xmm32u(0) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), dst); BX_NEXT_INSTR(i); } @@ -514,9 +513,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFCMULCPH_MASK_VphHphWphR(bxInstruction_c unsigned len = i->getVL(), n; Bit32u mask = (i->opmask() != 0) ? BX_READ_16BIT_OPMASK(i->opmask()) : 0xffff, tmp_mask; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); - status.float_exception_masks = float_all_exceptions_mask; + status.softfloat_exceptionMasks = softfloat_all_exceptions_mask; for (n=0, tmp_mask = mask; n < DWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { if (tmp_mask & 0x1) { @@ -538,7 +537,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFCMULCPH_MASK_VphHphWphR(bxInstruction_c } } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), dst, len); BX_NEXT_INSTR(i); } @@ -554,9 +553,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFCMADDCSH_MASK_VshHphWshR(bxInstruction_c dst.xmm32u(0) = BX_READ_XMM_REG_LO_DWORD(i->dst()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); - status.float_exception_masks = float_all_exceptions_mask; + status.softfloat_exceptionMasks = softfloat_all_exceptions_mask; int fma_control1 = (i->getIaOpcode() == BX_IA_V512_VFMADDCSH_VshHphWsh_Kmask) ? softfloat_muladd_negate_product : 0; int fma_control2 = (i->getIaOpcode() == BX_IA_V512_VFMADDCSH_VshHphWsh_Kmask) ? 0 : softfloat_muladd_negate_product; @@ -571,7 +570,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFCMADDCSH_MASK_VshHphWshR(bxInstruction_c dst.xmm32u(0) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), dst); BX_NEXT_INSTR(i); } @@ -587,9 +586,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFCMADDCPH_MASK_VphHphWphR(bxInstruction_c unsigned len = i->getVL(), n; Bit32u mask = (i->opmask() != 0) ? BX_READ_16BIT_OPMASK(i->opmask()) : 0xffff, tmp_mask; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); - status.float_exception_masks = float_all_exceptions_mask; + status.softfloat_exceptionMasks = softfloat_all_exceptions_mask; for (n=0, tmp_mask = mask; n < DWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { if (tmp_mask & 0x1) { @@ -611,7 +610,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFCMADDCPH_MASK_VphHphWphR(bxInstruction_c } } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), dst, len); BX_NEXT_INSTR(i); } diff --git a/bochs/cpu/avx/avx512_rcp14.cc b/bochs/cpu/avx/avx512_rcp14.cc index ff653f4a81..01e225382a 100644 --- a/bochs/cpu/avx/avx512_rcp14.cc +++ b/bochs/cpu/avx/avx512_rcp14.cc @@ -8231,10 +8231,11 @@ static const Bit16u rcp14_table[65536] = { 0x0003, 0x0003, 0x0002, 0x0002, 0x0001, 0x0001, 0x0000, 0x0000, // 65528 }; -extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +#include "softfloat3e/include/softfloat.h" + +extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); #include "fpu/softfloat-specialize.h" -#include "fpu/softfloat-round-pack.h" #include "simd_int.h" static Bit32u rcp14_table_lookup(Bit32u mant, unsigned bias, Bit16s *exp) @@ -8265,7 +8266,7 @@ static Bit32u rcp14_table_lookup(Bit32u mant, unsigned bias, Bit16s *exp) } // approximate 14-bit reciprocal of scalar half precision FP -float16 approximate_rcp14(float16 op, const float_status_t &status) +float16 approximate_rcp14(float16 op, const softfloat_status_t &status) { softfloat_class_t op_class = f16_class(op); @@ -8275,19 +8276,19 @@ float16 approximate_rcp14(float16 op, const float_status_t &status) struct exp8_sig16 normExpSig; switch(op_class) { - case float_zero: + case softfloat_zero: return packFloat16(sign, 0x1F, 0); - case float_negative_inf: - case float_positive_inf: + case softfloat_negative_inf: + case softfloat_positive_inf: return packFloat16(sign, 0, 0); - case float_SNaN: - case float_QNaN: + case softfloat_SNaN: + case softfloat_QNaN: return convert_to_QNaN(op); // the rcp14 handle denormals properly - case float_denormal: + case softfloat_denormal: if (softfloat_denormalsAreZeros(&status)) return packFloat16(sign, 0x1F, 0); @@ -8298,7 +8299,7 @@ float16 approximate_rcp14(float16 op, const float_status_t &status) fraction &= 0x3ff; // fall through - case float_normalized: + case softfloat_normalized: break; } @@ -8332,7 +8333,7 @@ float16 approximate_rcp14(float16 op, const float_status_t &status) } // approximate 14-bit reciprocal of scalar single precision FP -float32 approximate_rcp14(float32 op, const float_status_t &status) +float32 approximate_rcp14(float32 op, const softfloat_status_t &status) { softfloat_class_t op_class = f32_class(op); @@ -8389,7 +8390,7 @@ float32 approximate_rcp14(float32 op, const float_status_t &status) } // approximate 14-bit reciprocal of scalar double precision FP -float64 approximate_rcp14(float64 op, const float_status_t &status) +float64 approximate_rcp14(float64 op, const softfloat_status_t &status) { softfloat_class_t op_class = f64_class(op); @@ -8457,11 +8458,11 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRCP14PS_MASK_VpsWpsR(bxInstruction_c *i) Bit32u mask = i->opmask() ? BX_READ_16BIT_OPMASK(i->opmask()) : (Bit32u) -1; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); for (unsigned n=0, tmp_mask = mask; n < DWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { if (tmp_mask & 0x1) - op.vmm32u(n) = approximate_rcp14(op.vmm32u(n), status); + op.vmm32u(n) = approximate_rcp14((float32) op.vmm32u(n), status); else op.vmm32u(n) = 0; } @@ -8484,11 +8485,11 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRCP14PD_MASK_VpdWpdR(bxInstruction_c *i) Bit32u mask = i->opmask() ? BX_READ_8BIT_OPMASK(i->opmask()) : (Bit32u) -1; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); for (unsigned n=0, tmp_mask = mask; n < QWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { if (tmp_mask & 0x1) - op.vmm64u(n) = approximate_rcp14(op.vmm64u(n), status); + op.vmm64u(n) = approximate_rcp14((float64) op.vmm64u(n), status); else op.vmm64u(n) = 0; } @@ -8512,7 +8513,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRCP14SS_MASK_VssHpsWssR(bxInstruction_c * if (! i->opmask() || BX_SCALAR_ELEMENT_MASK(i->opmask())) { float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op1.xmm32u(0) = approximate_rcp14(op2, status); } else { @@ -8533,7 +8534,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRCP14SD_MASK_VsdHpdWsdR(bxInstruction_c * if (! i->opmask() || BX_SCALAR_ELEMENT_MASK(i->opmask())) { float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op1.xmm64u(0) = approximate_rcp14(op2, status); } else { @@ -8554,7 +8555,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRCPSH_MASK_VshHphWshR(bxInstruction_c *i) if (! i->opmask() || BX_SCALAR_ELEMENT_MASK(i->opmask())) { float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op1.xmm16u(0) = approximate_rcp14(op2, status); } else { @@ -8574,11 +8575,11 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRCPPH_MASK_VphWphR(bxInstruction_c *i) Bit32u mask = i->opmask() ? BX_READ_32BIT_OPMASK(i->opmask()) : (Bit32u) -1; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); for (unsigned n=0, tmp_mask = mask; n < WORD_ELEMENTS(len); n++, tmp_mask >>= 1) { if (tmp_mask & 0x1) - op.vmm16u(n) = approximate_rcp14(op.vmm16u(n), status); + op.vmm16u(n) = approximate_rcp14((float16) op.vmm16u(n), status); else op.vmm16u(n) = 0; } diff --git a/bochs/cpu/avx/avx512_rsqrt14.cc b/bochs/cpu/avx/avx512_rsqrt14.cc index 4697697af1..fa472831b2 100644 --- a/bochs/cpu/avx/avx512_rsqrt14.cc +++ b/bochs/cpu/avx/avx512_rsqrt14.cc @@ -8234,8 +8234,8 @@ static const Bit16u rsqrt14_table1[32768] = { 0x6a0e, 0x6a0d, 0x6a0c, 0x6a0c, 0x6a0b, 0x6a0a, 0x6a09, 0x6a09 // 32760 }; +#include "softfloat3e/include/softfloat.h" #include "fpu/softfloat-specialize.h" -#include "fpu/softfloat-round-pack.h" #include "simd_int.h" // approximate 14-bit sqrt reciprocal of scalar single precision FP @@ -8249,20 +8249,20 @@ float16 approximate_rsqrt14(float16 op, bool daz) struct exp8_sig16 normExpSig; switch(op_class) { - case float_zero: + case softfloat_zero: return packFloat16(sign, 0x1F, 0); - case float_positive_inf: + case softfloat_positive_inf: return 0; - case float_negative_inf: + case softfloat_negative_inf: return float16_default_nan; - case float_SNaN: - case float_QNaN: + case softfloat_SNaN: + case softfloat_QNaN: return convert_to_QNaN(op); - case float_denormal: + case softfloat_denormal: if (daz) return packFloat16(sign, 0x1F, 0); normExpSig = softfloat_normSubnormalF16Sig(fraction); @@ -8272,7 +8272,7 @@ float16 approximate_rsqrt14(float16 op, bool daz) fraction &= 0x3ff; // fall through - case float_normalized: + case softfloat_normalized: break; }; @@ -8428,7 +8428,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRSQRT14PS_MASK_VpsWpsR(bxInstruction_c *i for (unsigned n=0, tmp_mask = mask; n < DWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { if (tmp_mask & 0x1) - op.vmm32u(n) = approximate_rsqrt14(op.vmm32u(n), MXCSR.get_DAZ()); + op.vmm32u(n) = approximate_rsqrt14((float32) op.vmm32u(n), MXCSR.get_DAZ()); else op.vmm32u(n) = 0; } @@ -8453,7 +8453,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRSQRT14PD_MASK_VpdWpdR(bxInstruction_c *i for (unsigned n=0, tmp_mask = mask; n < QWORD_ELEMENTS(len); n++, tmp_mask >>= 1) { if (tmp_mask & 0x1) - op.vmm64u(n) = approximate_rsqrt14(op.vmm64u(n), MXCSR.get_DAZ()); + op.vmm64u(n) = approximate_rsqrt14((float64) op.vmm64u(n), MXCSR.get_DAZ()); else op.vmm64u(n) = 0; } @@ -8514,7 +8514,6 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRSQRTSH_MASK_VshHphWshR(bxInstruction_c * if (! i->opmask() || BX_SCALAR_ELEMENT_MASK(i->opmask())) { float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); - op1.xmm16u(0) = approximate_rsqrt14(op2, MXCSR.get_DAZ()); } else { @@ -8536,7 +8535,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRSQRTPH_MASK_VphWphR(bxInstruction_c *i) for (unsigned n=0, tmp_mask = mask; n < WORD_ELEMENTS(len); n++, tmp_mask >>= 1) { if (tmp_mask & 0x1) - op.vmm16u(n) = approximate_rsqrt14(op.vmm16u(n), MXCSR.get_DAZ()); + op.vmm16u(n) = approximate_rsqrt14((float16) op.vmm16u(n), MXCSR.get_DAZ()); else op.vmm16u(n) = 0; } diff --git a/bochs/cpu/avx/avx_cvt.cc b/bochs/cpu/avx/avx_cvt.cc index 6c693a16ce..0c3b89b2c2 100644 --- a/bochs/cpu/avx/avx_cvt.cc +++ b/bochs/cpu/avx/avx_cvt.cc @@ -28,19 +28,21 @@ #if BX_SUPPORT_AVX -extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +#include "softfloat3e/include/softfloat.h" + +extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); /* Opcode: VEX.F3.0F 2A (VEX.W=0) */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSI2SS_VssEdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = i32_to_f32(BX_READ_32BIT_REG(i->src2()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -51,12 +53,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSI2SS_VssEqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = i64_to_f32(BX_READ_64BIT_REG(i->src2()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -77,12 +79,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSI2SD_VsdEqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = i64_to_f64(BX_READ_64BIT_REG(i->src2()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -95,14 +97,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPS2PD_VpdWpsR(bxInstruction_c *i) BxPackedYmmRegister op = BX_READ_YMM_REG(i->src()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { result.vmm64u(n) = f32_to_f64(op.ymm32u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); @@ -114,14 +116,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPD2PS_VpsWpdR(bxInstruction_c *i) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()), result; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { result.vmm32u(n) = f64_to_f32(op.vmm64u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (len == BX_VL128) { BX_WRITE_XMM_REG_LO_QWORD_CLEAR_HIGH(i->dst(), result.vmm64u(0)); @@ -139,10 +141,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSS2SD_VsdWssR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = f32_to_f64(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -154,10 +156,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSD2SS_VssWsdR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = f64_to_f32(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -169,14 +171,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTDQ2PS_VpsWdqR(bxInstruction_c *i) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { op.vmm32u(n) = i32_to_f32(op.vmm32s(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); @@ -188,14 +190,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPS2DQ_VdqWpsR(bxInstruction_c *i) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { op.vmm32s(n) = f32_to_i32(op.vmm32u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); @@ -207,14 +209,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTPS2DQ_VdqWpsR(bxInstruction_c *i) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { op.vmm32s(n) = f32_to_i32_round_to_zero(op.vmm32u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); @@ -226,14 +228,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTPD2DQ_VdqWpdR(bxInstruction_c *i) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()), result; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { result.vmm32s(n) = f64_to_i32_round_to_zero(op.vmm64u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (len == BX_VL128) { BX_WRITE_XMM_REG_LO_QWORD_CLEAR_HIGH(i->dst(), result.vmm64u(0)); @@ -251,14 +253,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPD2DQ_VdqWpdR(bxInstruction_c *i) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()), result; unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { result.vmm32s(n) = f64_to_i32(op.vmm64u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (len == BX_VL128) { BX_WRITE_XMM_REG_LO_QWORD_CLEAR_HIGH(i->dst(), result.vmm64u(0)); @@ -294,16 +296,16 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPH2PS_VpsWpsR(bxInstruction_c *i) BxPackedYmmRegister op = BX_READ_YMM_REG(i->src()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); - status.denormals_are_zeros = 0; // ignore MXCSR.DAZ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + status.softfloat_denormals_are_zeros = 0; // ignore MXCSR.DAZ // no denormal exception is reported on MXCSR - status.float_suppress_exception = float_flag_denormal; + status.softfloat_suppressException = softfloat_flag_denormal; for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { result.vmm32u(n) = f16_to_f32(op.ymm16u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); @@ -314,21 +316,21 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPS2PH_WpsVpsIb(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()), result; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); unsigned len = i->getVL(); Bit8u control = i->Ib(); - status.flush_underflow_to_zero = 0; // ignore MXCSR.FUZ + status.softfloat_flush_underflow_to_zero = 0; // ignore MXCSR.FUZ // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) - status.float_rounding_mode = control & 0x3; + status.softfloat_roundingMode = control & 0x3; for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { result.vmm16u(n) = f32_to_f16(op.vmm32u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (i->modC0()) { if (len == BX_VL128) { diff --git a/bochs/cpu/avx/avx_fma.cc b/bochs/cpu/avx/avx_fma.cc index 3882a1d04f..2d05180311 100644 --- a/bochs/cpu/avx/avx_fma.cc +++ b/bochs/cpu/avx/avx_fma.cc @@ -28,7 +28,9 @@ #if BX_SUPPORT_AVX -extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +#include "softfloat3e/include/softfloat.h" + +extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); #include "simd_pfp.h" @@ -43,10 +45,10 @@ extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); \ float32 op3 = BX_READ_XMM_REG_LO_DWORD(i->src3()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ op1 = (func)(op1, op2, op3, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); \ BX_CLEAR_AVX_HIGH128(i->dst()); \ @@ -66,10 +68,10 @@ AVX2_FMA_SCALAR_SINGLE(VFNMSUBSS_VpsHssWssR, f32_fnmsub) float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); \ float64 op3 = BX_READ_XMM_REG_LO_QWORD(i->src3()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ op1 = (func)(op1, op2, op3, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); \ BX_CLEAR_AVX_HIGH128(i->dst()); \ @@ -91,10 +93,10 @@ AVX2_FMA_SCALAR_DOUBLE(VFNMSUBSD_VpdHsdWsdR, f64_fnmsub) float16 op2 = BX_READ_XMM_REG_LO_WORD(i->src2()); \ float16 op3 = BX_READ_XMM_REG_LO_WORD(i->src3()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ op1 = (func)(op1, op2, op3, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_XMM_REG_LO_WORD(i->dst(), op1); \ BX_CLEAR_AVX_HIGH128(i->dst()); \ @@ -120,13 +122,13 @@ AVX2_FMA_SCALAR_HALF_PRECISION(VFNMSUBSH_VphHshWshR, f16_fnmsub) float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); \ float32 op3 = BX_READ_XMM_REG_LO_DWORD(i->src3()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ \ BxPackedXmmRegister dest; \ dest.xmm64u(0) = (func)(op1, op2, op3, &status); \ dest.xmm64u(1) = 0; \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), dest); \ \ @@ -146,13 +148,13 @@ FMA4_SINGLE_SCALAR(VFNMSUBSS_VssHssWssVIbR, f32_fnmsub) float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); \ float64 op3 = BX_READ_XMM_REG_LO_QWORD(i->src3()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ \ BxPackedXmmRegister dest; \ dest.xmm64u(0) = (func)(op1, op2, op3, &status); \ dest.xmm64u(1) = 0; \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ \ BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), dest); \ \ diff --git a/bochs/cpu/avx/avx_ne_convert.cc b/bochs/cpu/avx/avx_ne_convert.cc index cdb7f39ef8..82cd69ceb6 100644 --- a/bochs/cpu/avx/avx_ne_convert.cc +++ b/bochs/cpu/avx/avx_ne_convert.cc @@ -28,29 +28,30 @@ #if BX_SUPPORT_AVX +#include "softfloat3e/include/softfloat.h" + // FP32: s|eeeeeeee|mmmmmmmmmmmmmmmmmmmmmmm // BF16: s|eeeeeeee|mmmmmmm // F16: s|eeeee|mmmmmmmmmm -float_status_t prepare_ne_softfloat_status_helper() +softfloat_status_t prepare_ne_softfloat_status_helper() { - float_status_t status; - - status.float_rounding_mode = float_round_nearest_even; - status.float_exception_flags = 0; - status.float_exception_masks = float_all_exceptions_mask; - status.float_suppress_exception = float_all_exceptions_mask; - status.float_nan_handling_mode = float_first_operand_nan; - status.flush_underflow_to_zero = true; + softfloat_status_t status; + + status.softfloat_roundingMode = softfloat_round_near_even; + status.softfloat_exceptionFlags = 0; + status.softfloat_exceptionMasks = softfloat_all_exceptions_mask; + status.softfloat_suppressException = softfloat_all_exceptions_mask; + status.softfloat_flush_underflow_to_zero = true; // input denormals not converted to zero and handled normally - status.denormals_are_zeros = false; + status.softfloat_denormals_are_zeros = false; return status; } float32 convert_ne_fp16_to_fp32(float16 op) { - static float_status_t status = prepare_ne_softfloat_status_helper(); + static softfloat_status_t status = prepare_ne_softfloat_status_helper(); return f16_to_f32(op, &status); } diff --git a/bochs/cpu/avx/avx_pfp.cc b/bochs/cpu/avx/avx_pfp.cc index e562935a19..d1b22682ed 100644 --- a/bochs/cpu/avx/avx_pfp.cc +++ b/bochs/cpu/avx/avx_pfp.cc @@ -28,8 +28,8 @@ #if BX_SUPPORT_AVX -extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); -extern void mxcsr_to_softfloat_status_word_imm_override(float_status_t &status, Bit8u immb); +extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +extern void mxcsr_to_softfloat_status_word_imm_override(softfloat_status_t &status, Bit8u immb); extern float32 approximate_rsqrt(float32 op); extern float32 approximate_rcp(float32 op); @@ -174,10 +174,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VSQRTSS_VssHpsWssR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm32u(0) = f32_sqrt(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -189,10 +189,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VSQRTSD_VsdHpdWsdR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); op1.xmm64u(0) = f64_sqrt(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -256,12 +256,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VRCPSS_VssHpsWssR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); \ float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ op1.xmm32u(0) = (func)(op1.xmm32u(0), op2, &status); \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); \ \ BX_NEXT_INSTR(i); \ @@ -283,12 +283,12 @@ AVX_SCALAR_SINGLE_FP(VSCALEFSS_VssHpsWssR, f32_scalef); BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); \ float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ softfloat_status_word_rc_override(status, i); \ \ op1.xmm64u(0) = (func)(op1.xmm64u(0), op2, &status); \ \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); \ \ BX_NEXT_INSTR(i); \ @@ -310,14 +310,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPS_VpsHpsWpsIbR(bxInstruction_c *i) BxPackedYmmRegister op1 = BX_READ_YMM_REG(i->src1()), op2 = BX_READ_YMM_REG(i->src2()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); int ib = i->Ib() & 0x1F; for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { op1.ymm32u(n) = avx_compare32[ib](op1.ymm32u(n), op2.ymm32u(n), &status) ? 0xFFFFFFFF : 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_YMM_REGZ_VLEN(i->dst(), op1, len); BX_NEXT_INSTR(i); @@ -329,7 +329,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPD_VpdHpdWpdIbR(bxInstruction_c *i) BxPackedYmmRegister op1 = BX_READ_YMM_REG(i->src1()), op2 = BX_READ_YMM_REG(i->src2()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); int ib = i->Ib() & 0x1F; for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { @@ -337,7 +337,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPD_VpdHpdWpdIbR(bxInstruction_c *i) BX_CONST64(0xFFFFFFFFFFFFFFFF) : 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_YMM_REGZ_VLEN(i->dst(), op1, len); BX_NEXT_INSTR(i); @@ -349,7 +349,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPSD_VsdHpdWsdIbR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); int ib = i->Ib() & 0x1F; if(avx_compare64[ib](op1.xmm64u(0), op2, &status)) { @@ -358,7 +358,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPSD_VsdHpdWsdIbR(bxInstruction_c *i) op1.xmm64u(0) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -370,7 +370,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPSS_VssHpsWssIbR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); int ib = i->Ib() & 0x1F; if(avx_compare32[ib](op1.xmm32u(0), op2, &status)) { @@ -379,7 +379,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPSS_VssHpsWssIbR(bxInstruction_c *i) op1.xmm32u(0) = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); @@ -433,14 +433,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VROUNDPS_VpsWpsIbR(bxInstruction_c *i) BxPackedYmmRegister op = BX_READ_YMM_REG(i->src()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); mxcsr_to_softfloat_status_word_imm_override(status, i->Ib()); for(unsigned n=0; n < DWORD_ELEMENTS(len); n++) { op.ymm32u(n) = f32_roundToInt(op.ymm32u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_YMM_REGZ_VLEN(i->dst(), op, len); @@ -453,14 +453,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VROUNDPD_VpdWpdIbR(bxInstruction_c *i) BxPackedYmmRegister op = BX_READ_YMM_REG(i->src()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); mxcsr_to_softfloat_status_word_imm_override(status, i->Ib()); for(unsigned n=0; n < QWORD_ELEMENTS(len); n++) { op.ymm64u(n) = f64_roundToInt(op.ymm64u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_YMM_REGZ_VLEN(i->dst(), op, len); @@ -473,12 +473,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VROUNDSS_VssHpsWssIbR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); mxcsr_to_softfloat_status_word_imm_override(status, i->Ib()); op1.xmm32u(0) = f32_roundToInt(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); @@ -491,12 +491,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VROUNDSD_VsdHpdWsdIbR(bxInstruction_c *i) BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); mxcsr_to_softfloat_status_word_imm_override(status, i->Ib()); op1.xmm64u(0) = f64_roundToInt(op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); @@ -510,7 +510,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VDPPS_VpsHpsWpsIbR(bxInstruction_c *i) unsigned len = i->getVL(); Bit8u mask = i->Ib(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); for (unsigned n=0; n < len; n++) { @@ -533,7 +533,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VDPPS_VpsHpsWpsIbR(bxInstruction_c *i) xmm_addps_mask(&op2.ymm128(n), &op1.ymm128(n), status, mask); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_YMM_REGZ_VLEN(i->dst(), op2, len); diff --git a/bochs/cpu/avx/xop.cc b/bochs/cpu/avx/xop.cc index 4d383a4d79..e2ed7fee99 100644 --- a/bochs/cpu/avx/xop.cc +++ b/bochs/cpu/avx/xop.cc @@ -28,7 +28,9 @@ #if BX_SUPPORT_AVX -extern float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +#include "softfloat3e/include/softfloat.h" + +extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); #include "simd_int.h" #include "simd_compare.h" @@ -204,14 +206,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VPPERM_VdqHdqWdqVIb(bxInstruction_c *i) } #define XOP_SHIFT_ROTATE(HANDLER, func) \ - void BX_CPP_AttrRegparmN(1) BX_CPU_C:: HANDLER (bxInstruction_c *i) \ + void BX_CPP_AttrRegparmN(1) BX_CPU_C:: HANDLER (bxInstruction_c *i) \ { \ BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); \ \ (func)(&op1, &op2); \ \ BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); \ - \ BX_NEXT_INSTR(i); \ } @@ -611,13 +612,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFRCZPS_VpsWpsR(bxInstruction_c *i) BxPackedYmmRegister op = BX_READ_YMM_REG(i->src()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); for (unsigned n=0; n < DWORD_ELEMENTS(len); n++) { op.ymm32u(n) = f32_frc(op.ymm32u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_YMM_REGZ_VLEN(i->dst(), op, len); BX_NEXT_INSTR(i); @@ -628,13 +629,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFRCZPD_VpdWpdR(bxInstruction_c *i) BxPackedYmmRegister op = BX_READ_YMM_REG(i->src()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); for (unsigned n=0; n < QWORD_ELEMENTS(len); n++) { op.ymm64u(n) = f64_frc(op.ymm64u(n), &status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_YMM_REGZ_VLEN(i->dst(), op, len); @@ -646,12 +647,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFRCZSS_VssWssR(bxInstruction_c *i) float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); BxPackedXmmRegister r; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); r.xmm64u(0) = (Bit64u) f32_frc(op, &status); r.xmm64u(1) = 0; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), r); BX_NEXT_INSTR(i); @@ -662,12 +663,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VFRCZSD_VsdWsdR(bxInstruction_c *i) float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); BxPackedXmmRegister r; - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); r.xmm64u(0) = f64_frc(op, &status); r.xmm64u(1) = 0; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), r); BX_NEXT_INSTR(i); diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index 89040d46ec..24fa7cd917 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -4944,7 +4944,6 @@ class BOCHSAPI BX_CPU_C : public logfunctions { BX_SMF bx_address fpu_save_environment(bxInstruction_c *i); BX_SMF bx_address fpu_load_environment(bxInstruction_c *i); BX_SMF Bit8u pack_FPU_TW(Bit16u tag_word); - BX_SMF Bit16u unpack_FPU_TW(Bit16u tag_byte); BX_SMF Bit16u x87_get_FCS(void); BX_SMF Bit16u x87_get_FDS(void); #endif diff --git a/bochs/cpu/cpu_templates_pfp.h b/bochs/cpu/cpu_templates_pfp.h index 44093de713..598794d24c 100644 --- a/bochs/cpu/cpu_templates_pfp.h +++ b/bochs/cpu/cpu_templates_pfp.h @@ -22,16 +22,24 @@ #ifndef BX_CPU_PFP_TEMPLATES_H #define BX_CPU_PFP_TEMPLATES_H +#include "cpu/softfloat3e/include/softfloat.h" + extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr); +#if BX_SUPPORT_EVEX == 0 +#define softfloat_status_word_rc_override(status, i) +#else +extern void softfloat_status_word_rc_override(softfloat_status_t &status, bxInstruction_c *i); +#endif + template void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_SSE_PFP_1OP(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); (func)(&op, status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); @@ -43,9 +51,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_SSE_PFP_2OP(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); (func)(&op1, &op2, status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op1); #endif @@ -60,14 +68,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX_PFP_1OP(bxInstruction_c *i) BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < len; n++) { (func)(&op.vmm128(n), status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } @@ -78,14 +86,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX_PFP_2OP(bxInstruction_c *i) BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < len; n++) { (func)(&op1.vmm128(n), &op2.vmm128(n), status); } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } @@ -98,13 +106,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX_PFP_3OP(bxInstruction_c *i) BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0; n < len; n++) (func)(&op1.vmm128(n), &op2.vmm128(n), &op3.vmm128(n), status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } @@ -120,13 +128,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_1OP_HALF(bxInstruct unsigned mask = BX_READ_32BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 8) (func)(&op.vmm128(n), status, tmp_mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 8) @@ -147,13 +155,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_1OP_SINGLE(bxInstru unsigned mask = BX_READ_16BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 4) (func)(&op.vmm128(n), status, tmp_mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 4) @@ -174,13 +182,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_1OP_DOUBLE(bxInstru unsigned mask = BX_READ_8BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 2) (func)(&op.vmm128(n), status, tmp_mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 2) @@ -201,13 +209,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_2OP_SINGLE(bxInstru unsigned mask = BX_READ_16BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 4) (func)(&op1.vmm128(n), &op2.vmm128(n), status, tmp_mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 4) @@ -229,13 +237,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_2OP_DOUBLE(bxInstru unsigned mask = BX_READ_8BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 2) (func)(&op1.vmm128(n), &op2.vmm128(n), status, tmp_mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 2) @@ -257,13 +265,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_2OP_HALF(bxInstruct unsigned mask = BX_READ_32BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 8) (func)(&op1.vmm128(n), &op2.vmm128(n), status, tmp_mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 8) @@ -287,13 +295,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_3OP_SINGLE(bxInstru unsigned mask = BX_READ_16BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 4) (func)(&op1.vmm128(n), &op2.vmm128(n), &op3.vmm128(n), status, tmp_mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 4) @@ -317,13 +325,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_3OP_DOUBLE(bxInstru unsigned mask = BX_READ_8BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 2) (func)(&op1.vmm128(n), &op2.vmm128(n), &op3.vmm128(n), status, tmp_mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 2) @@ -347,13 +355,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_3OP_HALF(bxInstruct unsigned mask = BX_READ_32BIT_OPMASK(i->opmask()); unsigned len = i->getVL(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 8) (func)(&op1.vmm128(n), &op2.vmm128(n), &op3.vmm128(n), status, tmp_mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); if (! i->isZeroMasking()) { for (unsigned n=0; n < len; n++, mask >>= 8) diff --git a/bochs/cpu/cpudb/Makefile.in b/bochs/cpu/cpudb/Makefile.in index bf8a8ab48f..0d7ac97b0e 100644 --- a/bochs/cpu/cpudb/Makefile.in +++ b/bochs/cpu/cpudb/Makefile.in @@ -91,281 +91,302 @@ dist-clean: clean ########################################### # dependencies generated by -# gcc -MM -I.. -I../.. -I../../instrument/stubs *.cc | sed 's/\.cc/.@CPP_SUFFIX@/g' +# gcc -MM -I.. -I../.. -I../../instrument/stubs */*.cc | sed 's/\.cc/.@CPP_SUFFIX@/g' ########################################### amd/amd_k6_2_chomper.o: amd/amd_k6_2_chomper.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - amd/amd_k6_2_chomper.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h amd/amd_k6_2_chomper.h \ + ../../cpu/cpuid.h amd/athlon64_clawhammer.o: amd/athlon64_clawhammer.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - amd/athlon64_clawhammer.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h amd/athlon64_clawhammer.h \ + ../../cpu/cpuid.h amd/athlon64_venice.o: amd/athlon64_venice.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - amd/athlon64_venice.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h amd/athlon64_venice.h \ + ../../cpu/cpuid.h amd/phenomx3_8650_toliman.o: amd/phenomx3_8650_toliman.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - amd/phenomx3_8650_toliman.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h amd/phenomx3_8650_toliman.h \ + ../../cpu/cpuid.h amd/ryzen.o: amd/ryzen.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - amd/ryzen.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h amd/ryzen.h ../../cpu/cpuid.h amd/trinity_apu.o: amd/trinity_apu.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - amd/trinity_apu.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h amd/trinity_apu.h \ + ../../cpu/cpuid.h amd/turion64_tyler.o: amd/turion64_tyler.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - amd/turion64_tyler.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h amd/turion64_tyler.h \ + ../../cpu/cpuid.h amd/zambezi.o: amd/zambezi.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - amd/zambezi.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h amd/zambezi.h \ + ../../cpu/cpuid.h intel/atom_n270.o: intel/atom_n270.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/atom_n270.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h intel/atom_n270.h \ + ../../cpu/cpuid.h intel/broadwell_ult.o: intel/broadwell_ult.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/broadwell_ult.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h intel/broadwell_ult.h \ + ../../cpu/cpuid.h intel/core2_penryn_t9600.o: intel/core2_penryn_t9600.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/core2_penryn_t9600.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h intel/core2_penryn_t9600.h \ + ../../cpu/cpuid.h intel/core_duo_t2400_yonah.o: intel/core_duo_t2400_yonah.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/core_duo_t2400_yonah.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h intel/core_duo_t2400_yonah.h \ + ../../cpu/cpuid.h intel/corei3_cnl.o: intel/corei3_cnl.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/corei3_cnl.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h intel/corei3_cnl.h \ + ../../cpu/cpuid.h intel/corei5_arrandale_m520.o: intel/corei5_arrandale_m520.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/corei5_arrandale_m520.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h intel/corei5_arrandale_m520.h \ + ../../cpu/cpuid.h intel/corei5_lynnfield_750.o: intel/corei5_lynnfield_750.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/corei5_lynnfield_750.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h intel/corei5_lynnfield_750.h \ + ../../cpu/cpuid.h intel/corei7_haswell_4770.o: intel/corei7_haswell_4770.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/corei7_haswell_4770.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h intel/corei7_haswell_4770.h \ + ../../cpu/cpuid.h intel/corei7_icelake-u.o: intel/corei7_icelake-u.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h \ ../../cpu/cpu.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../../cpu/decoder/decoder.h ../../instrument/stubs/instrument.h \ - ../../cpu/i387.h ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h \ - ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ - ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ - ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h \ - ../../cpu/vmx.h ../../cpu/svm.h ../../cpu/cpuid.h ../../cpu/access.h \ + ../../cpu/i387.h ../../cpu/softfloat3e/include/softfloat_types.h \ + ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h \ + ../../cpu/crregs.h ../../cpu/descriptor.h ../../cpu/decoder/instr.h \ + ../../cpu/lazy_flags.h ../../cpu/tlb.h ../../cpu/icache.h \ + ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/vmx_ctrls.h ../../cpu/access.h \ ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/corei7_icelake-u.h + intel/corei7_icelake-u.h ../../cpu/cpuid.h intel/corei7_ivy_bridge_3770K.o: intel/corei7_ivy_bridge_3770K.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/corei7_ivy_bridge_3770K.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h \ + intel/corei7_ivy_bridge_3770K.h ../../cpu/cpuid.h intel/corei7_sandy_bridge_2600K.o: intel/corei7_sandy_bridge_2600K.@CPP_SUFFIX@ \ ../../bochs.h ../../config.h ../../osdep.h ../../logio.h \ ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/corei7_sandy_bridge_2600K.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h \ + intel/corei7_sandy_bridge_2600K.h ../../cpu/cpuid.h intel/corei7_skylake-x.o: intel/corei7_skylake-x.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/corei7_skylake-x.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../param_names.h intel/corei7_skylake-x.h \ + ../../cpu/cpuid.h intel/p2_klamath.o: intel/p2_klamath.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - intel/p2_klamath.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h intel/p2_klamath.h ../../cpu/cpuid.h intel/p3_katmai.o: intel/p3_katmai.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - intel/p3_katmai.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h intel/p3_katmai.h ../../cpu/cpuid.h intel/p4_prescott_celeron_336.o: intel/p4_prescott_celeron_336.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - intel/p4_prescott_celeron_336.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h intel/p4_prescott_celeron_336.h \ + ../../cpu/cpuid.h intel/p4_willamette.o: intel/p4_willamette.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - intel/p4_willamette.h + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h intel/p4_willamette.h \ + ../../cpu/cpuid.h intel/pentium.o: intel/pentium.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../decoder/decoder.h \ - ../../instrument/stubs/instrument.h ../i387.h ../fpu/softfloat.h \ - ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h ../crregs.h \ - ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h \ - ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - intel/pentium.h + ../../instrument/stubs/instrument.h ../i387.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h intel/pentium.h ../../cpu/cpuid.h intel/pentium_mmx.o: intel/pentium_mmx.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../decoder/decoder.h ../../instrument/stubs/instrument.h ../i387.h \ - ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ - ../crregs.h ../descriptor.h ../decoder/instr.h ../lazy_flags.h ../tlb.h \ - ../icache.h ../xmm.h ../vmx.h ../cpuid.h ../access.h \ - intel/pentium_mmx.h -intel/tigerlake.o: intel/tigerlake.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ + ../softfloat3e/include/softfloat_types.h ../fpu/tag_w.h \ + ../fpu/status_w.h ../fpu/control_w.h ../crregs.h ../descriptor.h \ + ../decoder/instr.h ../lazy_flags.h ../tlb.h ../icache.h ../xmm.h \ + ../vmx.h ../vmx_ctrls.h ../access.h intel/pentium_mmx.h \ + ../../cpu/cpuid.h +intel/sapphire_rapids.o: intel/sapphire_rapids.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../../cpu/cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ - ../../instrument/stubs/instrument.h \ - ../../cpu/i387.h ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h \ - ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ - ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ - ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h \ - ../../cpu/vmx.h ../../cpu/svm.h ../../cpu/cpuid.h ../../cpu/access.h \ + ../../cpu/decoder/decoder.h ../../instrument/stubs/instrument.h \ + ../../cpu/i387.h ../../cpu/softfloat3e/include/softfloat_types.h \ + ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h \ + ../../cpu/crregs.h ../../cpu/descriptor.h ../../cpu/decoder/instr.h \ + ../../cpu/lazy_flags.h ../../cpu/tlb.h ../../cpu/icache.h \ + ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/vmx_ctrls.h ../../cpu/access.h \ ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/tigerlake.h -intel/sapphire_rapids.o: intel/sapphire_rapids.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ + intel/sapphire_rapids.h ../../cpu/cpuid.h +intel/tigerlake.o: intel/tigerlake.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../../cpu/cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ - ../../instrument/stubs/instrument.h \ - ../../cpu/i387.h ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h \ - ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ - ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ - ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h \ - ../../cpu/vmx.h ../../cpu/svm.h ../../cpu/cpuid.h ../../cpu/access.h \ + ../../cpu/decoder/decoder.h ../../instrument/stubs/instrument.h \ + ../../cpu/i387.h ../../cpu/softfloat3e/include/softfloat_types.h \ + ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h \ + ../../cpu/crregs.h ../../cpu/descriptor.h ../../cpu/decoder/instr.h \ + ../../cpu/lazy_flags.h ../../cpu/tlb.h ../../cpu/icache.h \ + ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/vmx_ctrls.h ../../cpu/access.h \ ../../gui/siminterface.h ../../gui/paramtree.h ../../param_names.h \ - intel/sapphire_rapids.h + intel/tigerlake.h ../../cpu/cpuid.h diff --git a/bochs/cpu/cpudb/amd/phenomx3_8650_toliman.cc b/bochs/cpu/cpudb/amd/phenomx3_8650_toliman.cc index f38f2a3ed5..1192609e93 100644 --- a/bochs/cpu/cpudb/amd/phenomx3_8650_toliman.cc +++ b/bochs/cpu/cpudb/amd/phenomx3_8650_toliman.cc @@ -134,7 +134,7 @@ void phenom_8650_toliman_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, return; #if BX_SUPPORT_MONITOR_MWAIT case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0); return; #endif default: @@ -264,33 +264,7 @@ void phenom_8650_toliman_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const #endif } -#if BX_SUPPORT_MONITOR_MWAIT - -// leaf 0x00000005 // -void phenom_8650_toliman_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0; -} - -#endif +// leaf 0x00000005 MONITOR/MWAIT Leaf // // leaf 0x80000000 // void phenom_8650_toliman_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/amd/phenomx3_8650_toliman.h b/bochs/cpu/cpudb/amd/phenomx3_8650_toliman.h index 93efad60af..e2bb199516 100644 --- a/bochs/cpu/cpudb/amd/phenomx3_8650_toliman.h +++ b/bochs/cpu/cpudb/amd/phenomx3_8650_toliman.h @@ -47,9 +47,6 @@ class phenom_8650_toliman_t : public bx_cpuid_t { private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; -#if BX_SUPPORT_MONITOR_MWAIT - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; -#endif void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/amd/ryzen.cc b/bochs/cpu/cpudb/amd/ryzen.cc index 1c4894fd68..0e8c62d2b0 100644 --- a/bochs/cpu/cpudb/amd/ryzen.cc +++ b/bochs/cpu/cpudb/amd/ryzen.cc @@ -173,13 +173,11 @@ void ryzen_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function case 0x00000001: get_std_cpuid_leaf_1(leaf); return; -#if BX_SUPPORT_MONITOR_MWAIT case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0); return; -#endif - case 0x00000006: - get_std_cpuid_leaf_6(leaf); + case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf + get_leaf(leaf, 0x00000004, 0x00000000, 0x00000001, 0x00000000); return; case 0x00000007: get_std_cpuid_leaf_7(subfunction, leaf); @@ -318,43 +316,8 @@ void ryzen_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const #endif } -#if BX_SUPPORT_MONITOR_MWAIT - -// leaf 0x00000005 // -void ryzen_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0; -} - -#endif - -// leaf 0x00000006 // -void ryzen_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000006 - Thermal and Power Management Leaf - leaf->eax = 0x00000004; - leaf->ebx = 0x00000000; - leaf->ecx = 0x00000001; - leaf->edx = 0x00000000; -} +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 // void ryzen_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/amd/ryzen.h b/bochs/cpu/cpudb/amd/ryzen.h index 18f55dbbfd..ea0edafb3a 100644 --- a/bochs/cpu/cpudb/amd/ryzen.h +++ b/bochs/cpu/cpudb/amd/ryzen.h @@ -47,10 +47,6 @@ class ryzen_t : public bx_cpuid_t { private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; -#if BX_SUPPORT_MONITOR_MWAIT - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; -#endif - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/amd/trinity_apu.cc b/bochs/cpu/cpudb/amd/trinity_apu.cc index aebb03a4c5..c7d4db55d0 100644 --- a/bochs/cpu/cpudb/amd/trinity_apu.cc +++ b/bochs/cpu/cpudb/amd/trinity_apu.cc @@ -157,13 +157,11 @@ void trinity_apu_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_fu case 0x00000001: get_std_cpuid_leaf_1(leaf); return; -#if BX_SUPPORT_MONITOR_MWAIT case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0); return; -#endif - case 0x00000006: - get_std_cpuid_leaf_6(leaf); + case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf + get_leaf(leaf, 0x00000000, 0x00000000, 0x00000001, 0x00000000); return; case 0x00000007: get_std_cpuid_leaf_7(subfunction, leaf); @@ -302,43 +300,8 @@ void trinity_apu_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const #endif } -#if BX_SUPPORT_MONITOR_MWAIT - -// leaf 0x00000005 // -void trinity_apu_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0; -} - -#endif - -// leaf 0x00000006 // -void trinity_apu_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000006 - Thermal and Power Management Leaf - leaf->eax = 0x00000000; - leaf->ebx = 0x00000000; - leaf->ecx = 0x00000001; - leaf->edx = 0x00000000; -} +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 // void trinity_apu_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/amd/trinity_apu.h b/bochs/cpu/cpudb/amd/trinity_apu.h index b2e409c2e3..1c77e3ac7f 100644 --- a/bochs/cpu/cpudb/amd/trinity_apu.h +++ b/bochs/cpu/cpudb/amd/trinity_apu.h @@ -47,10 +47,6 @@ class trinity_apu_t : public bx_cpuid_t { private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; -#if BX_SUPPORT_MONITOR_MWAIT - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; -#endif - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/amd/zambezi.cc b/bochs/cpu/cpudb/amd/zambezi.cc index 0de835db90..763e7af589 100644 --- a/bochs/cpu/cpudb/amd/zambezi.cc +++ b/bochs/cpu/cpudb/amd/zambezi.cc @@ -153,13 +153,11 @@ void zambezi_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_functi case 0x00000001: get_std_cpuid_leaf_1(leaf); return; -#if BX_SUPPORT_MONITOR_MWAIT case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0); return; -#endif - case 0x00000006: - get_std_cpuid_leaf_6(leaf); + case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf + get_leaf(leaf, 0x00000000, 0x00000000, 0x00000001, 0x00000000); return; case 0x0000000D: get_std_cpuid_xsave_leaf(subfunction, leaf); @@ -295,45 +293,9 @@ void zambezi_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const #endif } -#if BX_SUPPORT_MONITOR_MWAIT - -// leaf 0x00000005 // -void zambezi_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0; -} - -#endif - -// leaf 0x00000006 // -void zambezi_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000006 - Thermal and Power Management Leaf - leaf->eax = 0x00000000; - leaf->ebx = 0x00000000; - leaf->ecx = 0x00000001; - leaf->edx = 0x00000000; -} - -// leaf 0x0000000D - XSAVE // +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // +// leaf 0x0000000D XSAVE // // leaf 0x80000000 // void zambezi_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/amd/zambezi.h b/bochs/cpu/cpudb/amd/zambezi.h index 381ed873ee..358ab2ee60 100644 --- a/bochs/cpu/cpudb/amd/zambezi.h +++ b/bochs/cpu/cpudb/amd/zambezi.h @@ -47,10 +47,6 @@ class zambezi_t : public bx_cpuid_t { private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; -#if BX_SUPPORT_MONITOR_MWAIT - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; -#endif - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/atom_n270.cc b/bochs/cpu/cpudb/intel/atom_n270.cc index f0f452f583..4ed1619db2 100644 --- a/bochs/cpu/cpudb/intel/atom_n270.cc +++ b/bochs/cpu/cpudb/intel/atom_n270.cc @@ -115,7 +115,7 @@ void atom_n270_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_func get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x00020220); return; case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf get_leaf(leaf, 0x00000001, 0x00000002, 0x00000001, 0x00000000); @@ -301,37 +301,7 @@ void atom_n270_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *lea } } -// leaf 0x00000005 // -void atom_n270_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x00020220; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - +// leaf 0x00000005 Monitor-Mwait Leaf // // leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // diff --git a/bochs/cpu/cpudb/intel/atom_n270.h b/bochs/cpu/cpudb/intel/atom_n270.h index b4890def8c..a9e52fee5e 100644 --- a/bochs/cpu/cpudb/intel/atom_n270.h +++ b/bochs/cpu/cpudb/intel/atom_n270.h @@ -46,7 +46,6 @@ class atom_n270_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/broadwell_ult.cc b/bochs/cpu/cpudb/intel/broadwell_ult.cc index fa0b4df9cd..be6a1e67b5 100644 --- a/bochs/cpu/cpudb/intel/broadwell_ult.cc +++ b/bochs/cpu/cpudb/intel/broadwell_ult.cc @@ -151,10 +151,10 @@ void broadwell_ult_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_ get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x11142120); return; - case 0x00000006: - get_std_cpuid_leaf_6(leaf); + case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf + get_leaf(leaf, 0x00000077, 0x00000002, 0x00000009, 0x00000000); return; case 0x00000007: get_std_cpuid_leaf_7(subfunction, leaf); @@ -412,46 +412,8 @@ void broadwell_ult_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t } } -// leaf 0x00000005 // -void broadwell_ult_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x11142120; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - -// leaf 0x00000006 // -void broadwell_ult_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000006 - Thermal and Power Management Leaf - leaf->eax = 0x00000077; - leaf->ebx = 0x00000002; - leaf->ecx = 0x00000009; - leaf->edx = 0x00000000; -} +// leaf 0x00000005 - - MONITOR/MWAIT Leaf // +// leaf 0x00000006 - Thermal and Power Management Leaf // // leaf 0x00000007 // void broadwell_ult_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/intel/broadwell_ult.h b/bochs/cpu/cpudb/intel/broadwell_ult.h index bb13784488..47e87d55df 100644 --- a/bochs/cpu/cpudb/intel/broadwell_ult.h +++ b/bochs/cpu/cpudb/intel/broadwell_ult.h @@ -50,8 +50,6 @@ class broadwell_ult_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/core2_penryn_t9600.cc b/bochs/cpu/cpudb/intel/core2_penryn_t9600.cc index 89dd77d4ee..3c9c514028 100644 --- a/bochs/cpu/cpudb/intel/core2_penryn_t9600.cc +++ b/bochs/cpu/cpudb/intel/core2_penryn_t9600.cc @@ -123,10 +123,10 @@ void core2_penryn_t9600_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, c get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x03122220); return; - case 0x00000006: - get_std_cpuid_leaf_6(leaf); + case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf + get_leaf(leaf, 0x00000003, 0x00000002, 0x00000003, 0x00000000); return; case 0x00000007: case 0x00000008: @@ -353,47 +353,8 @@ void core2_penryn_t9600_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_functi } } -// leaf 0x00000005 // -void core2_penryn_t9600_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x03122220; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - -// leaf 0x00000006 // -void core2_penryn_t9600_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000006 - Thermal and Power Management Leaf - leaf->eax = 0x00000003; - leaf->ebx = 0x00000002; - leaf->ecx = 0x00000003; - leaf->edx = 0x00000000; -} - +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // diff --git a/bochs/cpu/cpudb/intel/core2_penryn_t9600.h b/bochs/cpu/cpudb/intel/core2_penryn_t9600.h index 49463151f2..e7c72c17cd 100644 --- a/bochs/cpu/cpudb/intel/core2_penryn_t9600.h +++ b/bochs/cpu/cpudb/intel/core2_penryn_t9600.h @@ -51,8 +51,6 @@ class core2_penryn_t9600_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/core_duo_t2400_yonah.cc b/bochs/cpu/cpudb/intel/core_duo_t2400_yonah.cc index 274bb2c233..8d387a701a 100644 --- a/bochs/cpu/cpudb/intel/core_duo_t2400_yonah.cc +++ b/bochs/cpu/cpudb/intel/core_duo_t2400_yonah.cc @@ -117,10 +117,10 @@ void core_duo_t2400_yonah_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x00022220); return; - case 0x00000006: - get_std_cpuid_leaf_6(leaf); + case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf + get_leaf(leaf, 0x00000001, 0x00000002, 0x00000001, 0x00000000); return; case 0x00000007: case 0x00000008: @@ -309,47 +309,8 @@ void core_duo_t2400_yonah_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_func } } -// leaf 0x00000005 // -void core_duo_t2400_yonah_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x00022220; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - -// leaf 0x00000006 // -void core_duo_t2400_yonah_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000006 - Thermal and Power Management Leaf - leaf->eax = 0x00000001; - leaf->ebx = 0x00000002; - leaf->ecx = 0x00000001; - leaf->edx = 0x00000000; -} - +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // diff --git a/bochs/cpu/cpudb/intel/core_duo_t2400_yonah.h b/bochs/cpu/cpudb/intel/core_duo_t2400_yonah.h index 011a0230f7..0bf585c033 100644 --- a/bochs/cpu/cpudb/intel/core_duo_t2400_yonah.h +++ b/bochs/cpu/cpudb/intel/core_duo_t2400_yonah.h @@ -51,8 +51,6 @@ class core_duo_t2400_yonah_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/corei3_cnl.cc b/bochs/cpu/cpudb/intel/corei3_cnl.cc index 6fa9264dad..e7a917be1a 100644 --- a/bochs/cpu/cpudb/intel/corei3_cnl.cc +++ b/bochs/cpu/cpudb/intel/corei3_cnl.cc @@ -168,7 +168,7 @@ void corei3_cnl_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_fun get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: // CPUID leaf 0x00000005 - MONITOR/MWAIT leaf - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x11142020); return; case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf get_leaf(leaf, 0x00002ff7, 0x00000002, 0x00000009, 0x00000000); @@ -435,38 +435,8 @@ void corei3_cnl_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *le } } -// leaf 0x00000005 // -void corei3_cnl_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x11142020; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - -// leaf 0x00000006 - Thermal and Power Management Leaf // +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 // void corei3_cnl_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/intel/corei3_cnl.h b/bochs/cpu/cpudb/intel/corei3_cnl.h index b5fe947c5d..8541a6d79f 100644 --- a/bochs/cpu/cpudb/intel/corei3_cnl.h +++ b/bochs/cpu/cpudb/intel/corei3_cnl.h @@ -50,7 +50,6 @@ class corei3_cnl_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/corei5_arrandale_m520.cc b/bochs/cpu/cpudb/intel/corei5_arrandale_m520.cc index 136ebdaafa..3cc4b9344a 100644 --- a/bochs/cpu/cpudb/intel/corei5_arrandale_m520.cc +++ b/bochs/cpu/cpudb/intel/corei5_arrandale_m520.cc @@ -130,10 +130,10 @@ void corei5_arrandale_m520_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x00001120); return; - case 0x00000006: - get_std_cpuid_leaf_6(leaf); + case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf + get_leaf(leaf, 0x00000007, 0x00000002, 0x00000001, 0x00000000); return; case 0x00000007: case 0x00000008: @@ -377,47 +377,8 @@ void corei5_arrandale_m520_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_fun } } -// leaf 0x00000005 // -void corei5_arrandale_m520_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x00001120; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - -// leaf 0x00000006 // -void corei5_arrandale_m520_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000006 - Thermal and Power Management Leaf - leaf->eax = 0x00000007; - leaf->ebx = 0x00000002; - leaf->ecx = 0x00000001; - leaf->edx = 0x00000000; -} - +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // diff --git a/bochs/cpu/cpudb/intel/corei5_arrandale_m520.h b/bochs/cpu/cpudb/intel/corei5_arrandale_m520.h index da4faee2cd..c5e99c0d8a 100644 --- a/bochs/cpu/cpudb/intel/corei5_arrandale_m520.h +++ b/bochs/cpu/cpudb/intel/corei5_arrandale_m520.h @@ -51,8 +51,6 @@ class corei5_arrandale_m520_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/corei5_lynnfield_750.cc b/bochs/cpu/cpudb/intel/corei5_lynnfield_750.cc index 61de145ac0..8431fbfa61 100644 --- a/bochs/cpu/cpudb/intel/corei5_lynnfield_750.cc +++ b/bochs/cpu/cpudb/intel/corei5_lynnfield_750.cc @@ -129,10 +129,10 @@ void corei5_lynnfield_750_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x00001120); return; - case 0x00000006: - get_std_cpuid_leaf_6(leaf); + case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf + get_leaf(leaf, 0x00000003, 0x00000002, 0x00000001, 0x00000000); return; case 0x00000007: case 0x00000008: @@ -355,47 +355,8 @@ void corei5_lynnfield_750_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_func } } -// leaf 0x00000005 // -void corei5_lynnfield_750_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x00001120; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - -// leaf 0x00000006 // -void corei5_lynnfield_750_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000006 - Thermal and Power Management Leaf - leaf->eax = 0x00000003; - leaf->ebx = 0x00000002; - leaf->ecx = 0x00000001; - leaf->edx = 0x00000000; -} - +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // diff --git a/bochs/cpu/cpudb/intel/corei5_lynnfield_750.h b/bochs/cpu/cpudb/intel/corei5_lynnfield_750.h index 1985475396..bf8ba29cb4 100644 --- a/bochs/cpu/cpudb/intel/corei5_lynnfield_750.h +++ b/bochs/cpu/cpudb/intel/corei5_lynnfield_750.h @@ -51,8 +51,6 @@ class corei5_lynnfield_750_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/corei7_haswell_4770.cc b/bochs/cpu/cpudb/intel/corei7_haswell_4770.cc index 3834d4399e..06a05ee23b 100644 --- a/bochs/cpu/cpudb/intel/corei7_haswell_4770.cc +++ b/bochs/cpu/cpudb/intel/corei7_haswell_4770.cc @@ -150,10 +150,10 @@ void corei7_haswell_4770_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x00042120); return; - case 0x00000006: - get_std_cpuid_leaf_6(leaf); + case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf + get_leaf(leaf, 0x00000077, 0x00000002, 0x00000009, 0x00000000); return; case 0x00000007: get_std_cpuid_leaf_7(subfunction, leaf); @@ -391,46 +391,8 @@ void corei7_haswell_4770_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_funct } } -// leaf 0x00000005 // -void corei7_haswell_4770_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x00042120; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - -// leaf 0x00000006 // -void corei7_haswell_4770_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000006 - Thermal and Power Management Leaf - leaf->eax = 0x00000077; - leaf->ebx = 0x00000002; - leaf->ecx = 0x00000009; - leaf->edx = 0x00000000; -} +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 // void corei7_haswell_4770_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/intel/corei7_haswell_4770.h b/bochs/cpu/cpudb/intel/corei7_haswell_4770.h index a1e4f3e5e2..0e54612144 100644 --- a/bochs/cpu/cpudb/intel/corei7_haswell_4770.h +++ b/bochs/cpu/cpudb/intel/corei7_haswell_4770.h @@ -51,8 +51,6 @@ class corei7_haswell_4770_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/corei7_icelake-u.cc b/bochs/cpu/cpudb/intel/corei7_icelake-u.cc index 1ba5292588..25383b152d 100644 --- a/bochs/cpu/cpudb/intel/corei7_icelake-u.cc +++ b/bochs/cpu/cpudb/intel/corei7_icelake-u.cc @@ -185,7 +185,7 @@ void corei7_icelake_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x11121020); return; case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf get_leaf(leaf, 0x0007aff5, 0x00000002, 0x00000009, 0x00000000); @@ -422,38 +422,8 @@ void corei7_icelake_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t } } -// leaf 0x00000005 // -void corei7_icelake_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x11121020; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - -// leaf 0x00000006 // +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 // void corei7_icelake_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/intel/corei7_icelake-u.h b/bochs/cpu/cpudb/intel/corei7_icelake-u.h index 33630a7ae5..ca430ca363 100644 --- a/bochs/cpu/cpudb/intel/corei7_icelake-u.h +++ b/bochs/cpu/cpudb/intel/corei7_icelake-u.h @@ -50,7 +50,6 @@ class corei7_icelake_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/corei7_ivy_bridge_3770K.cc b/bochs/cpu/cpudb/intel/corei7_ivy_bridge_3770K.cc index b03fbe0dec..13dd178d2e 100644 --- a/bochs/cpu/cpudb/intel/corei7_ivy_bridge_3770K.cc +++ b/bochs/cpu/cpudb/intel/corei7_ivy_bridge_3770K.cc @@ -140,7 +140,7 @@ void corei7_ivy_bridge_3770k_t::get_cpuid_leaf(Bit32u function, Bit32u subfuncti get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x00001120); return; case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf get_leaf(leaf, 0x00000077, 0x00000002, 0x00000009, 0x00000000); @@ -395,38 +395,8 @@ void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_f } } -// leaf 0x00000005 // -void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x00001120; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - -// leaf 0x00000006 - Thermal and Power Management Leaf // +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 // void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/intel/corei7_ivy_bridge_3770K.h b/bochs/cpu/cpudb/intel/corei7_ivy_bridge_3770K.h index b925101e36..792bb69796 100644 --- a/bochs/cpu/cpudb/intel/corei7_ivy_bridge_3770K.h +++ b/bochs/cpu/cpudb/intel/corei7_ivy_bridge_3770K.h @@ -51,7 +51,6 @@ class corei7_ivy_bridge_3770k_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/corei7_sandy_bridge_2600K.cc b/bochs/cpu/cpudb/intel/corei7_sandy_bridge_2600K.cc index 446073b520..d79ab508e0 100644 --- a/bochs/cpu/cpudb/intel/corei7_sandy_bridge_2600K.cc +++ b/bochs/cpu/cpudb/intel/corei7_sandy_bridge_2600K.cc @@ -138,7 +138,7 @@ void corei7_sandy_bridge_2600k_t::get_cpuid_leaf(Bit32u function, Bit32u subfunc get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x00001120); return; case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf get_leaf(leaf, 0x00000077, 0x00000002, 0x0000000B, 0x00000000); @@ -391,37 +391,7 @@ void corei7_sandy_bridge_2600k_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid } } -// leaf 0x00000005 // -void corei7_sandy_bridge_2600k_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x00001120; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - +// leaf 0x00000005 MONITOR/MWAIT Leaf // // leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // diff --git a/bochs/cpu/cpudb/intel/corei7_sandy_bridge_2600K.h b/bochs/cpu/cpudb/intel/corei7_sandy_bridge_2600K.h index 4f2b0b3052..e5e03d5af3 100644 --- a/bochs/cpu/cpudb/intel/corei7_sandy_bridge_2600K.h +++ b/bochs/cpu/cpudb/intel/corei7_sandy_bridge_2600K.h @@ -51,7 +51,6 @@ class corei7_sandy_bridge_2600k_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/corei7_skylake-x.cc b/bochs/cpu/cpudb/intel/corei7_skylake-x.cc index 4c656faa40..a06a71265d 100644 --- a/bochs/cpu/cpudb/intel/corei7_skylake-x.cc +++ b/bochs/cpu/cpudb/intel/corei7_skylake-x.cc @@ -162,10 +162,10 @@ void corei7_skylake_x_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpu get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x00002020); return; - case 0x00000006: - get_std_cpuid_leaf_6(leaf); + case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf + get_leaf(leaf, 0x00000075, 0x00000002, 0x00000009, 0x00000000); return; case 0x00000007: get_std_cpuid_leaf_7(subfunction, leaf); @@ -441,46 +441,8 @@ void corei7_skylake_x_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function } } -// leaf 0x00000005 // -void corei7_skylake_x_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x00002020; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} - -// leaf 0x00000006 - Thermal and Power Management Leaf // -void corei7_skylake_x_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000006 - Thermal and Power Management Leaf - leaf->eax = 0x00000075; - leaf->ebx = 0x00000002; - leaf->ecx = 0x00000009; - leaf->edx = 0x00000000; -} +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 // void corei7_skylake_x_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/intel/corei7_skylake-x.h b/bochs/cpu/cpudb/intel/corei7_skylake-x.h index 4c28553deb..3a42dad071 100644 --- a/bochs/cpu/cpudb/intel/corei7_skylake-x.h +++ b/bochs/cpu/cpudb/intel/corei7_skylake-x.h @@ -51,8 +51,6 @@ class corei7_skylake_x_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/sapphire_rapids.cc b/bochs/cpu/cpudb/intel/sapphire_rapids.cc index 91e8f2af86..9ade7e8917 100644 --- a/bochs/cpu/cpudb/intel/sapphire_rapids.cc +++ b/bochs/cpu/cpudb/intel/sapphire_rapids.cc @@ -207,7 +207,7 @@ void sapphire_rapids_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpui get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: // CPUID leaf 0x00000005 - MONITOR/MWAIT leaf - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x00001020); return; case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf get_leaf(leaf, 0x0045cef7, 0x00000002, 0x00000009, 0x00000000); @@ -463,36 +463,8 @@ void sapphire_rapids_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_ } } -// leaf 0x00000005 - MONITOR/MWAIT Leaf // -void sapphire_rapids_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x00001020; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 // void sapphire_rapids_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/intel/sapphire_rapids.h b/bochs/cpu/cpudb/intel/sapphire_rapids.h index 949b0c0b7e..7f77bc82eb 100644 --- a/bochs/cpu/cpudb/intel/sapphire_rapids.h +++ b/bochs/cpu/cpudb/intel/sapphire_rapids.h @@ -50,8 +50,6 @@ class sapphire_rapids_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpudb/intel/tigerlake.cc b/bochs/cpu/cpudb/intel/tigerlake.cc index a51071095d..039a8bbf7b 100644 --- a/bochs/cpu/cpudb/intel/tigerlake.cc +++ b/bochs/cpu/cpudb/intel/tigerlake.cc @@ -191,7 +191,7 @@ void tigerlake_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_func get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: // CPUID leaf 0x00000005 - MONITOR/MWAIT leaf - get_std_cpuid_leaf_5(leaf); + get_std_cpuid_monitor_mwait_leaf(leaf, 0x11121020); return; case 0x00000006: // CPUID leaf 0x00000006 - Thermal and Power Management Leaf get_leaf(leaf, 0x0017eff7, 0x00000002, 0x00000009, 0x00000000); @@ -427,36 +427,8 @@ void tigerlake_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *lea } } -// leaf 0x00000005 - MONITOR/MWAIT Leaf // -void tigerlake_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const -{ - // CPUID function 0x00000005 - MONITOR/MWAIT Leaf - -#if BX_SUPPORT_MONITOR_MWAIT - // EAX - Smallest monitor-line size in bytes - // EBX - Largest monitor-line size in bytes - // ECX - - // [31:2] - reserved - // [1:1] - exit MWAIT even with EFLAGS.IF = 0 - // [0:0] - MONITOR/MWAIT extensions are supported - // EDX - - // [03-00] - number of C0 sub C-states supported using MWAIT - // [07-04] - number of C1 sub C-states supported using MWAIT - // [11-08] - number of C2 sub C-states supported using MWAIT - // [15-12] - number of C3 sub C-states supported using MWAIT - // [19-16] - number of C4 sub C-states supported using MWAIT - // [31-20] - reserved (MBZ) - leaf->eax = CACHE_LINE_SIZE; - leaf->ebx = CACHE_LINE_SIZE; - leaf->ecx = 3; - leaf->edx = 0x11121020; -#else - leaf->eax = 0; - leaf->ebx = 0; - leaf->ecx = 0; - leaf->edx = 0; -#endif -} +// leaf 0x00000005 MONITOR/MWAIT Leaf // +// leaf 0x00000006 Thermal and Power Management Leaf // // leaf 0x00000007 // void tigerlake_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const diff --git a/bochs/cpu/cpudb/intel/tigerlake.h b/bochs/cpu/cpudb/intel/tigerlake.h index bfa5831900..bb21793560 100644 --- a/bochs/cpu/cpudb/intel/tigerlake.h +++ b/bochs/cpu/cpudb/intel/tigerlake.h @@ -50,8 +50,6 @@ class tigerlake_t : public bx_cpuid_t { void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; - void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; diff --git a/bochs/cpu/cpuid.cc b/bochs/cpu/cpuid.cc index e5851ca260..9a16569834 100644 --- a/bochs/cpu/cpuid.cc +++ b/bochs/cpu/cpuid.cc @@ -74,6 +74,40 @@ void bx_cpuid_t::init() ia_extensions_bitmask[0] = (1 << BX_ISA_386); } +void bx_cpuid_t::get_std_cpuid_monitor_mwait_leaf(cpuid_function_t *leaf, Bit32u edx_power_states) const +{ + // CPUID function 0x00000005 - MONITOR/MWAIT Leaf + +#if BX_SUPPORT_MONITOR_MWAIT + // EAX - Smallest monitor-line size in bytes (cache line size) + // EBX - Largest monitor-line size in bytes (cache line size) + // ECX - + // [31:4] - reserved + // [3:3] - Monitorless MWAIT support + // [2:2] - reserved + // [1:1] - exit MWAIT even with EFLAGS.IF = 0 + // [0:0] - MONITOR/MWAIT extensions are supported + // EDX - + // [03-00] - number of C0 sub C-states supported using MWAIT + // [07-04] - number of C1 sub C-states supported using MWAIT + // [11-08] - number of C2 sub C-states supported using MWAIT + // [15-12] - number of C3 sub C-states supported using MWAIT + // [19-16] - number of C4 sub C-states supported using MWAIT + // [31-20] - reserved + leaf->eax = CACHE_LINE_SIZE; + leaf->ebx = CACHE_LINE_SIZE; + leaf->ecx = 0x3; + if (is_cpu_extension_supported(BX_ISA_MONITORLESS_MWAIT)) + leaf->ecx |= (1<<3); + leaf->edx = edx_power_states; +#else + leaf->eax = 0; + leaf->ebx = 0; + leaf->ecx = 0; + leaf->edx = 0; +#endif +} + #if BX_SUPPORT_APIC BX_CPP_INLINE static Bit32u ilog2(Bit32u x) @@ -392,7 +426,7 @@ Bit32u bx_cpuid_t::get_std_cpuid_leaf_1_ecx(Bit32u extra) const ecx |= BX_CPUID_STD1_ECX_VMX; #endif - // [6:6] SMX: Secure Virtual Machine Technology - not supported + // [6:6] SMX: Safer Mode Extensions for Trusted Execution Technology (TXT) - not supported // [7:7] EST: Enhanced Intel SpeedStep Technology - not supported, could be enabled through extra // [8:8] TM2: Thermal Monitor 2 - not supported, could be enabled through extra @@ -834,7 +868,7 @@ Bit32u bx_cpuid_t::get_std_cpuid_leaf_7_ebx(Bit32u extra) const if (is_cpu_extension_supported(BX_ISA_FCS_FDS_DEPRECATION)) ebx |= BX_CPUID_STD7_SUBLEAF0_EBX_DEPRECATE_FCS_FDS; - // [14:14] Intel Memory Protection Extensions - not supported + // [14:14] Intel Memory Protection Extensions (MPX) - not supported // [15:15] Supports Platform Quality of Service Enforcement (PQE) capability - not supported // [16:16] AVX512F instructions support @@ -1238,12 +1272,27 @@ Bit32u bx_cpuid_t::get_std_cpuid_leaf_7_subleaf_1_edx(Bit32u extra) const edx |= BX_CPUID_STD7_SUBLEAF1_EDX_AVX_VNNI_INT16; #endif - // [13:11] reserved + // [12:11] reserved + // [13:13] User Timer support // [14:14] PREFETCHITI: PREFETCHIT0/T1 instruction // [15:15] USER_MSR: support for URDMSR/UWRMSR instructions // [16:16] reserved - // [17:17] UIRET sets UIF to the RFLAGS[1] image loaded from the stack + + // [17:17] Flexible UIRET: UIRET sets UIF to the RFLAGS[1] image loaded from the stack + if (is_cpu_extension_supported(BX_ISA_FLEXIBLE_UIRET)) + edx |= BX_CPUID_STD7_SUBLEAF1_EDX_UIRET_UIF; + // [18:18] CET_SSS + // [22:19] reserved + + // [23:23] to be used by VMM: MWAIT and CPUID LEAF5 support (introduced with Monitorless MWAIT support) +#if BX_SUPPORT_MONITOR_MWAIT + if (is_cpu_extension_supported(BX_ISA_MONITOR_MWAIT)) + if (is_cpu_extension_supported(BX_ISA_MONITORLESS_MWAIT)) + edx |= BX_CPUID_STD7_SUBLEAF1_EDX_MWAIT_AND_LEAF5; +#endif + + // [31:24] reserved return edx; } diff --git a/bochs/cpu/cpuid.h b/bochs/cpu/cpuid.h index 49b5105eab..8dbd4b72ea 100644 --- a/bochs/cpu/cpuid.h +++ b/bochs/cpu/cpuid.h @@ -118,6 +118,8 @@ class bx_cpuid_t { void get_std_cpuid_amx_tmul_leaf(Bit32u subfunction, cpuid_function_t *leaf) const; #endif + void get_std_cpuid_monitor_mwait_leaf(cpuid_function_t *leaf, Bit32u edx_power_states) const; + Bit32u get_std_cpuid_leaf_1_ecx(Bit32u extra = 0) const; Bit32u get_std_cpuid_leaf_1_edx_common(Bit32u extra = 0) const; Bit32u get_std_cpuid_leaf_1_edx(Bit32u extra = 0) const; @@ -552,7 +554,7 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu); // [18:18] LKGS instruction support // [19:19] WRMSRNS instruction // [20:20] NMI source reporting -// [21:21] AMX-FB16 support +// [21:21] AMX-FP16 support // [22:22] HRESET and CPUID leaf 0x20 support // [23:23] AVX IFMA support // [25:24] reserved @@ -599,11 +601,15 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu); // ----------------------------- // [0:0] IA32_PPIN and IA32_PPIN_CTL MSRs // [1:1] TSE: PBNDKB instruction and existence of the IA32_TSE_CAPABILITY MSR +// [2:2] reserved +// [3:3] CPUIDMAXVAL_LIM_RMV: IA32_MISC_ENABLE[22] cannot be set to 1 to limit the value returned by CPUID.00H:EAX[7:0] // [31:1] reserved // ... #define BX_CPUID_STD7_SUBLEAF1_EBX_PPIN (1 << 0) #define BX_CPUID_STD7_SUBLEAF1_EBX_TSE (1 << 1) +#define BX_CPUID_STD7_SUBLEAF1_EBX_RESERVED2 (1 << 2) +#define BX_CPUID_STD7_SUBLEAF1_EBX_CPUIDMAXVAL_LIM_RMV (1 << 3) // ... // CPUID defines - features CPUID[0x00000007].ECX [subleaf 1] @@ -621,12 +627,17 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu); // [8:8] AMX-COMPLEX instructions // [9:9] reserved // [10:10] AVX-VNNI-INT16 instructions -// [13:11] reserved +// [12:11] reserved +// [13:13] User Timer support // [14:14] PREFETCHITI: PREFETCHIT0/T1 instruction // [15:15] USER_MSR: support for URDMSR/UWRMSR instructions // [16:16] reserved -// [17:17] UIRET sets UIF to the RFLAGS[1] image loaded from the stack +// [17:17] Flexible UIRET: UIRET sets UIF to the RFLAGS[1] image loaded from the stack // [18:18] CET_SSS +// [19:19] AVX10 support and CPUID leaf 0x24 +// [22:20] reserved +// [23:23] MWAIT and CPUID LEAF5 support +// [31:24] reserved #define BX_CPUID_STD7_SUBLEAF1_EDX_RESERVED0 (1 << 0) #define BX_CPUID_STD7_SUBLEAF1_EDX_RESERVED1 (1 << 1) @@ -641,12 +652,17 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu); #define BX_CPUID_STD7_SUBLEAF1_EDX_AVX_VNNI_INT16 (1 << 10) #define BX_CPUID_STD7_SUBLEAF1_EDX_RESERVED11 (1 << 11) #define BX_CPUID_STD7_SUBLEAF1_EDX_RESERVED12 (1 << 12) -#define BX_CPUID_STD7_SUBLEAF1_EDX_RESERVED13 (1 << 13) +#define BX_CPUID_STD7_SUBLEAF1_EDX_USER_TIMER (1 << 13) #define BX_CPUID_STD7_SUBLEAF1_EDX_PREFETCHI (1 << 14) #define BX_CPUID_STD7_SUBLEAF1_EDX_USER_MSR (1 << 15) #define BX_CPUID_STD7_SUBLEAF1_EDX_RESERVED16 (1 << 16) #define BX_CPUID_STD7_SUBLEAF1_EDX_UIRET_UIF (1 << 17) #define BX_CPUID_STD7_SUBLEAF1_EDX_CET_SSS (1 << 18) +#define BX_CPUID_STD7_SUBLEAF1_EDX_AVX10 (1 << 19) +#define BX_CPUID_STD7_SUBLEAF1_EDX_RESERVED20 (1 << 20) +#define BX_CPUID_STD7_SUBLEAF1_EDX_RESERVED21 (1 << 21) +#define BX_CPUID_STD7_SUBLEAF1_EDX_RESERVED22 (1 << 22) +#define BX_CPUID_STD7_SUBLEAF1_EDX_MWAIT_AND_LEAF5 (1 << 23) // ... // CPUID defines - STD2 features CPUID[0x80000001].EDX diff --git a/bochs/cpu/crregs.h b/bochs/cpu/crregs.h index 92ef1dfd06..d02723ef12 100644 --- a/bochs/cpu/crregs.h +++ b/bochs/cpu/crregs.h @@ -88,32 +88,33 @@ struct bx_cr0_t { #if BX_CPU_LEVEL >= 5 -#define BX_CR4_VME_MASK (1 << 0) -#define BX_CR4_PVI_MASK (1 << 1) -#define BX_CR4_TSD_MASK (1 << 2) -#define BX_CR4_DE_MASK (1 << 3) -#define BX_CR4_PSE_MASK (1 << 4) -#define BX_CR4_PAE_MASK (1 << 5) -#define BX_CR4_MCE_MASK (1 << 6) -#define BX_CR4_PGE_MASK (1 << 7) -#define BX_CR4_PCE_MASK (1 << 8) -#define BX_CR4_OSFXSR_MASK (1 << 9) -#define BX_CR4_OSXMMEXCPT_MASK (1 << 10) -#define BX_CR4_UMIP_MASK (1 << 11) -#define BX_CR4_LA57_MASK (1 << 12) -#define BX_CR4_VMXE_MASK (1 << 13) -#define BX_CR4_SMXE_MASK (1 << 14) -#define BX_CR4_FSGSBASE_MASK (1 << 16) -#define BX_CR4_PCIDE_MASK (1 << 17) -#define BX_CR4_OSXSAVE_MASK (1 << 18) -#define BX_CR4_KEYLOCKER_MASK (1 << 19) -#define BX_CR4_SMEP_MASK (1 << 20) -#define BX_CR4_SMAP_MASK (1 << 21) -#define BX_CR4_PKE_MASK (1 << 22) -#define BX_CR4_CET_MASK (1 << 23) -#define BX_CR4_PKS_MASK (1 << 24) -#define BX_CR4_UINTR_MASK (1 << 25) -#define BX_CR4_LASS_MASK (1 << 27) +#define BX_CR4_VME_MASK (1 << 0) +#define BX_CR4_PVI_MASK (1 << 1) +#define BX_CR4_TSD_MASK (1 << 2) +#define BX_CR4_DE_MASK (1 << 3) +#define BX_CR4_PSE_MASK (1 << 4) +#define BX_CR4_PAE_MASK (1 << 5) +#define BX_CR4_MCE_MASK (1 << 6) +#define BX_CR4_PGE_MASK (1 << 7) +#define BX_CR4_PCE_MASK (1 << 8) +#define BX_CR4_OSFXSR_MASK (1 << 9) +#define BX_CR4_OSXMMEXCPT_MASK (1 << 10) +#define BX_CR4_UMIP_MASK (1 << 11) +#define BX_CR4_LA57_MASK (1 << 12) +#define BX_CR4_VMXE_MASK (1 << 13) +#define BX_CR4_SMXE_MASK (1 << 14) +#define BX_CR4_FSGSBASE_MASK (1 << 16) +#define BX_CR4_PCIDE_MASK (1 << 17) +#define BX_CR4_OSXSAVE_MASK (1 << 18) +#define BX_CR4_KEYLOCKER_MASK (1 << 19) +#define BX_CR4_SMEP_MASK (1 << 20) +#define BX_CR4_SMAP_MASK (1 << 21) +#define BX_CR4_PKE_MASK (1 << 22) +#define BX_CR4_CET_MASK (1 << 23) +#define BX_CR4_PKS_MASK (1 << 24) +#define BX_CR4_UINTR_MASK (1 << 25) +#define BX_CR4_LASS_MASK (1 << 27) +#define BX_CR4_LAM_SUPERVISOR_MASK (1 << 28) struct bx_cr4_t { Bit32u val32; // 32bit value of register @@ -148,6 +149,7 @@ struct bx_cr4_t { IMPLEMENT_CRREG_ACCESSORS(PKS, 24); IMPLEMENT_CRREG_ACCESSORS(UINTR, 25); IMPLEMENT_CRREG_ACCESSORS(LASS, 27); + IMPLEMENT_CRREG_ACCESSORS(LAM_SUPERVISOR, 28); BX_CPP_INLINE Bit32u get32() const { return val32; } BX_CPP_INLINE void set32(Bit32u val) { val32 = val; } diff --git a/bochs/cpu/decoder/features.h b/bochs/cpu/decoder/features.h index 0fb45a31ef..48758ea2f5 100644 --- a/bochs/cpu/decoder/features.h +++ b/bochs/cpu/decoder/features.h @@ -49,6 +49,7 @@ x86_feature(BX_ISA_SSE4_2, "sse4_2") /* SSE4_ x86_feature(BX_ISA_POPCNT, "popcnt") /* POPCNT instruction */ x86_feature(BX_ISA_MONITOR_MWAIT, "mwait") /* MONITOR/MWAIT instruction */ x86_feature(BX_ISA_WAITPKG, "waitpkg") /* TPAUSE/UMONITOR/UMWAIT instructions */ +x86_feature(BX_ISA_MONITORLESS_MWAIT, "monitorless_mwait") /* MONITOR-less MWAIT extension */ x86_feature(BX_ISA_MONITORX_MWAITX, "mwaitx") /* MONITORX/MWAITX instruction (AMD) */ x86_feature(BX_ISA_VMX, "vmx") /* VMX instruction */ x86_feature(BX_ISA_SMX, "smx") /* SMX instruction */ @@ -140,6 +141,7 @@ x86_feature(BX_ISA_SERIALIZE, "serialize") /* SERIA x86_feature(BX_ISA_LASS, "lass") /* Linear Address Space Separation support */ x86_feature(BX_ISA_LA57, "la57") /* 57-bit Virtual Address and 5-level paging support */ x86_feature(BX_ISA_UINTR, "uintr") /* User Level Interrupts support */ +x86_feature(BX_ISA_FLEXIBLE_UIRET, "flexible_uiret") /* Flexible UIRET support */ x86_feature(BX_ISA_MOVDIRI, "movdiri") /* MOVDIRI instruction support */ x86_feature(BX_ISA_MOVDIR64B, "movdir64b") /* MOVDIR64B instruction support */ x86_feature(BX_ISA_MSRLIST, "msrlist") /* RDMSRLIST/WRMSRLIST instructions support */ diff --git a/bochs/cpu/decoder/fetchdecode32.cc b/bochs/cpu/decoder/fetchdecode32.cc index 1f36806b22..6070755c10 100644 --- a/bochs/cpu/decoder/fetchdecode32.cc +++ b/bochs/cpu/decoder/fetchdecode32.cc @@ -78,8 +78,7 @@ struct BxOpcodeDecodeDescriptor32 { #ifndef BX_STANDALONE_DECODER #include "cpu/simd_int.h" -#include "cpu/fpu/softfloat.h" -#include "cpu/fpu/softfloat16.h" +#include "cpu/softfloat3e/include/softfloat.h" #include "cpu/simd_pfp.h" #include "cpu/simd_compare.h" #include "cpu/simd_vnni.h" diff --git a/bochs/cpu/decoder/fetchdecode_avx.h b/bochs/cpu/decoder/fetchdecode_avx.h index 0eae061dc7..9993ef0d50 100644 --- a/bochs/cpu/decoder/fetchdecode_avx.h +++ b/bochs/cpu/decoder/fetchdecode_avx.h @@ -1262,67 +1262,67 @@ static const Bit64u BxOpcodeGroup_VEX_0F38DF[] = { }; static const Bit64u BxOpcodeGroup_VEX_0F38E0[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPOXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPOXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPOXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38E1[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPNOXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPNOXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPNOXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38E2[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPBXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPBXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPBXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38E3[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPNBXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPNBXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPNBXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38E4[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPZXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPZXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPZXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38E5[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPNZXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPNZXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPNZXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38E6[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPBEXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPBEXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPBEXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38E7[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPNBEXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPNBEXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPNBEXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38E8[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPSXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPSXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPSXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38E9[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPNSXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPNSXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPNSXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38EA[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPPXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPPXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPPXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38EB[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPNPXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPNPXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPNPXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38EC[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPLXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPLXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPLXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38ED[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPNLXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPNLXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPNLXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38EE[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPLEXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPLEXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPLEXADD_EqGqBq) }; static const Bit64u BxOpcodeGroup_VEX_0F38EF[] = { - form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0, BX_IA_CMPNLEXADD_EdGdBd), + form_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W0 | ATTR_IS64, BX_IA_CMPNLEXADD_EdGdBd), last_opcode(ATTR_SSE_PREFIX_66 | ATTR_VL128 | ATTR_MOD_MEM | ATTR_VEX_W1 | ATTR_IS64, BX_IA_CMPNLEXADD_EqGqBq) }; diff --git a/bochs/cpu/fpu/Makefile.in b/bochs/cpu/fpu/Makefile.in index bdf2de7577..fed30e7e4e 100644 --- a/bochs/cpu/fpu/Makefile.in +++ b/bochs/cpu/fpu/Makefile.in @@ -46,8 +46,7 @@ BX_INCDIRS = -I.. -I../.. -I$(srcdir)/.. -I$(srcdir)/../.. -I../../@INSTRUMENT_D OBJS = ferr.o fpu.o fpu_arith.o fpu_compare.o fpu_const.o fpu_cmov.o \ fpu_load_store.o fpu_misc.o fpu_trans.o \ fprem.o fsincos.o f2xm1.o fyl2x.o fpatan.o \ - softfloat.o softfloatx80.o \ - softfloat-specialize.o softfloat-round-pack.o poly.o + poly.o all: libfpu.a @@ -74,122 +73,168 @@ dist-clean: clean # dependencies generated by # gcc -MM -I.. -I../.. -I../../instrument/stubs *.cc | sed 's/\.cc/.@CPP_SUFFIX@/g' ########################################### -f2xm1.o: f2xm1.@CPP_SUFFIX@ softfloatx80.h softfloat.h ../../config.h \ - softfloat-specialize.h softfloat-macros.h softfloat-round-pack.h +f2xm1.o: f2xm1.@CPP_SUFFIX@ fpu_trans.h ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h ../../config.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h softfloat-helpers.h \ + ../softfloat3e/include/primitives.h \ + ../softfloat3e/include/primitiveTypes.h ferr.o: ferr.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h ../../logio.h \ ../../misc/bswap.h ../../cpu/cpu.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../../cpu/decoder/decoder.h ../../instrument/stubs/instrument.h \ - ../../cpu/i387.h ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h \ - ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ - ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ - ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h \ - ../../cpu/stack.h ../../cpu/access.h softfloat-specialize.h softfloat.h -fpatan.o: fpatan.@CPP_SUFFIX@ softfloatx80.h softfloat.h ../../config.h \ - softfloat-specialize.h softfloat-macros.h softfloat-round-pack.h \ - fpu_constant.h -fprem.o: fprem.@CPP_SUFFIX@ softfloatx80.h softfloat.h ../../config.h \ - softfloat-specialize.h softfloat-round-pack.h softfloat-macros.h + ../../cpu/i387.h ../../cpu/softfloat3e/include/softfloat_types.h \ + ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h \ + ../../cpu/crregs.h ../../cpu/descriptor.h ../../cpu/decoder/instr.h \ + ../../cpu/lazy_flags.h ../../cpu/tlb.h ../../cpu/icache.h \ + ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/vmx_ctrls.h ../../cpu/stack.h \ + ../../cpu/access.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h +fpatan.o: fpatan.@CPP_SUFFIX@ ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h ../../config.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h fpu_trans.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h fpu_constant.h +fprem.o: fprem.@CPP_SUFFIX@ fpu_trans.h ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h ../../config.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h softfloat-helpers.h \ + ../softfloat3e/include/primitives.h \ + ../softfloat3e/include/primitiveTypes.h \ + ../softfloat3e/include/specialize.h ../softfloat3e/include/softfloat.h fpu.o: fpu.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h ../../logio.h \ ../../misc/bswap.h ../../cpu/cpu.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../../cpu/decoder/decoder.h ../../instrument/stubs/instrument.h \ - ../../cpu/i387.h ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h \ - ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ - ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ - ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h \ - ../../cpu/stack.h ../../cpu/access.h ../../iodev/iodev.h ../../plugin.h \ - ../../extplugin.h ../../param_names.h ../../pc_system.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h \ - ../../gui/paramtree.h ../../gui/gui.h softfloatx80.h softfloat.h \ - softfloat-specialize.h + ../../cpu/i387.h ../../cpu/softfloat3e/include/softfloat_types.h \ + ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h \ + ../../cpu/crregs.h ../../cpu/descriptor.h ../../cpu/decoder/instr.h \ + ../../cpu/lazy_flags.h ../../cpu/tlb.h ../../cpu/icache.h \ + ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/vmx_ctrls.h ../../cpu/stack.h \ + ../../cpu/access.h ../../iodev/iodev.h ../../plugin.h ../../extplugin.h \ + ../../param_names.h ../../pc_system.h ../../memory/memory-bochs.h \ + ../../gui/siminterface.h ../../gui/paramtree.h ../../gui/gui.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h fpu_arith.o: fpu_arith.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../../cpu/cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../../cpu/decoder/decoder.h \ ../../instrument/stubs/instrument.h ../../cpu/i387.h \ - ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h \ - ../../cpu/fpu/control_w.h ../../cpu/crregs.h ../../cpu/descriptor.h \ - ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h ../../cpu/tlb.h \ - ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/stack.h \ - ../../cpu/access.h softfloatx80.h softfloat.h softfloat-specialize.h + ../../cpu/softfloat3e/include/softfloat_types.h ../../cpu/fpu/tag_w.h \ + ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ + ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ + ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h \ + ../../cpu/vmx_ctrls.h ../../cpu/stack.h ../../cpu/access.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h fpu_trans.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h fpu_cmov.o: fpu_cmov.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../../cpu/cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../../cpu/decoder/decoder.h \ ../../instrument/stubs/instrument.h ../../cpu/i387.h \ - ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h \ - ../../cpu/fpu/control_w.h ../../cpu/crregs.h ../../cpu/descriptor.h \ - ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h ../../cpu/tlb.h \ - ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/stack.h \ - ../../cpu/access.h + ../../cpu/softfloat3e/include/softfloat_types.h ../../cpu/fpu/tag_w.h \ + ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ + ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ + ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h \ + ../../cpu/vmx_ctrls.h ../../cpu/stack.h ../../cpu/access.h fpu_compare.o: fpu_compare.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../../cpu/cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../../cpu/decoder/decoder.h \ ../../instrument/stubs/instrument.h ../../cpu/i387.h \ - ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h \ - ../../cpu/fpu/control_w.h ../../cpu/crregs.h ../../cpu/descriptor.h \ - ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h ../../cpu/tlb.h \ - ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/stack.h \ - ../../cpu/access.h ../../cpu/decoder/ia_opcodes.h \ - ../../cpu/decoder/ia_opcodes.def softfloatx80.h softfloat.h \ - softfloat-specialize.h + ../../cpu/softfloat3e/include/softfloat_types.h ../../cpu/fpu/tag_w.h \ + ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ + ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ + ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h \ + ../../cpu/vmx_ctrls.h ../../cpu/stack.h ../../cpu/access.h \ + ../../cpu/decoder/ia_opcodes.h ../../cpu/decoder/ia_opcodes.def \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h fpu_const.o: fpu_const.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../../cpu/cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../../cpu/decoder/decoder.h \ ../../instrument/stubs/instrument.h ../../cpu/i387.h \ - ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h \ - ../../cpu/fpu/control_w.h ../../cpu/crregs.h ../../cpu/descriptor.h \ - ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h ../../cpu/tlb.h \ - ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/stack.h \ - ../../cpu/access.h softfloatx80.h softfloat.h softfloat-specialize.h + ../../cpu/softfloat3e/include/softfloat_types.h ../../cpu/fpu/tag_w.h \ + ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ + ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ + ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h \ + ../../cpu/vmx_ctrls.h ../../cpu/stack.h ../../cpu/access.h \ + softfloat-specialize.h ../softfloat3e/include/softfloat_types.h fpu_load_store.o: fpu_load_store.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../logio.h ../../misc/bswap.h ../../cpu/cpu.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../cpu/decoder/decoder.h ../../cpu/decoder/features.h \ ../../cpu/decoder/decoder.h ../../instrument/stubs/instrument.h \ - ../../cpu/i387.h ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h \ - ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ - ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ - ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h \ - ../../cpu/stack.h ../../cpu/access.h ../../cpu/decoder/ia_opcodes.h \ - ../../cpu/decoder/ia_opcodes.def softfloatx80.h softfloat.h \ - softfloat-specialize.h + ../../cpu/i387.h ../../cpu/softfloat3e/include/softfloat_types.h \ + ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h \ + ../../cpu/crregs.h ../../cpu/descriptor.h ../../cpu/decoder/instr.h \ + ../../cpu/lazy_flags.h ../../cpu/tlb.h ../../cpu/icache.h \ + ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/vmx_ctrls.h ../../cpu/stack.h \ + ../../cpu/access.h ../../cpu/decoder/ia_opcodes.h \ + ../../cpu/decoder/ia_opcodes.def softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h fpu_trans.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h fpu_misc.o: fpu_misc.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../../cpu/cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../../cpu/decoder/decoder.h \ ../../instrument/stubs/instrument.h ../../cpu/i387.h \ - ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h \ - ../../cpu/fpu/control_w.h ../../cpu/crregs.h ../../cpu/descriptor.h \ - ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h ../../cpu/tlb.h \ - ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/stack.h \ - ../../cpu/access.h softfloatx80.h softfloat.h softfloat-specialize.h + ../../cpu/softfloat3e/include/softfloat_types.h ../../cpu/fpu/tag_w.h \ + ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ + ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ + ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h \ + ../../cpu/vmx_ctrls.h ../../cpu/stack.h ../../cpu/access.h fpu_trans.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h fpu_trans.o: fpu_trans.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../logio.h ../../misc/bswap.h ../../cpu/cpu.h ../../bx_debug/debug.h \ ../../config.h ../../osdep.h ../../cpu/decoder/decoder.h \ ../../cpu/decoder/features.h ../../cpu/decoder/decoder.h \ ../../instrument/stubs/instrument.h ../../cpu/i387.h \ - ../../cpu/fpu/softfloat.h ../../cpu/fpu/tag_w.h ../../cpu/fpu/status_w.h \ - ../../cpu/fpu/control_w.h ../../cpu/crregs.h ../../cpu/descriptor.h \ - ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h ../../cpu/tlb.h \ - ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h ../../cpu/stack.h \ - ../../cpu/access.h softfloatx80.h softfloat.h softfloat-specialize.h -fsincos.o: fsincos.@CPP_SUFFIX@ softfloatx80.h softfloat.h ../../config.h \ - softfloat-specialize.h softfloat-macros.h softfloat-round-pack.h \ - fpu_constant.h -fyl2x.o: fyl2x.@CPP_SUFFIX@ softfloatx80.h softfloat.h ../../config.h \ - softfloat-specialize.h softfloat-macros.h softfloat-round-pack.h \ - fpu_constant.h -poly.o: poly.@CPP_SUFFIX@ softfloat.h ../../config.h -softfloat-round-pack.o: softfloat-round-pack.@CPP_SUFFIX@ softfloat.h \ - ../../config.h softfloat-round-pack.h softfloat-macros.h \ - softfloat-specialize.h -softfloat-specialize.o: softfloat-specialize.@CPP_SUFFIX@ softfloat.h \ - ../../config.h softfloat-specialize.h softfloat-macros.h -softfloat.o: softfloat.@CPP_SUFFIX@ softfloat.h ../../config.h \ - softfloat-round-pack.h softfloat-macros.h softfloat-specialize.h -softfloatx80.o: softfloatx80.@CPP_SUFFIX@ softfloatx80.h softfloat.h ../../config.h \ - softfloat-specialize.h softfloat-round-pack.h softfloat-macros.h + ../../cpu/softfloat3e/include/softfloat_types.h ../../cpu/fpu/tag_w.h \ + ../../cpu/fpu/status_w.h ../../cpu/fpu/control_w.h ../../cpu/crregs.h \ + ../../cpu/descriptor.h ../../cpu/decoder/instr.h ../../cpu/lazy_flags.h \ + ../../cpu/tlb.h ../../cpu/icache.h ../../cpu/xmm.h ../../cpu/vmx.h \ + ../../cpu/vmx_ctrls.h ../../cpu/stack.h ../../cpu/access.h fpu_trans.h \ + ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h +fsincos.o: fsincos.@CPP_SUFFIX@ fpu_trans.h ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h ../../config.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h softfloat-helpers.h \ + ../softfloat3e/include/primitives.h \ + ../softfloat3e/include/primitiveTypes.h fpu_constant.h +fyl2x.o: fyl2x.@CPP_SUFFIX@ fpu_trans.h ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h ../../config.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h softfloat-specialize.h \ + ../softfloat3e/include/softfloat_types.h softfloat-helpers.h \ + ../softfloat3e/include/primitives.h \ + ../softfloat3e/include/primitiveTypes.h fpu_constant.h +poly.o: poly.@CPP_SUFFIX@ ../softfloat3e/include/softfloat.h \ + ../softfloat3e/include/softfloat_types.h ../../config.h \ + ../softfloat3e/include/softfloat-extra.h \ + ../softfloat3e/include/internals.h diff --git a/bochs/cpu/fpu/f2xm1.cc b/bochs/cpu/fpu/f2xm1.cc index d73608800e..ac83dea03e 100644 --- a/bochs/cpu/fpu/f2xm1.cc +++ b/bochs/cpu/fpu/f2xm1.cc @@ -25,12 +25,12 @@ these four paragraphs for those parts of this code that are retained. #define FLOAT128 -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "fpu_trans.h" +#include "softfloat-helpers.h" static const floatx80 floatx80_negone = packFloatx80(1, 0x3fff, BX_CONST64(0x8000000000000000)); static const floatx80 floatx80_neghalf = packFloatx80(1, 0x3ffe, BX_CONST64(0x8000000000000000)); -static const float128 float128_ln2 = +static const float128_t float128_ln2 = packFloat128(BX_CONST64(0x3ffe62e42fefa39e), BX_CONST64(0xf35793c7673007e6)); #ifdef BETTER_THAN_PENTIUM @@ -47,7 +47,7 @@ static const float128 float128_ln2 = #define EXP_ARR_SIZE 15 -static float128 exp_arr[EXP_ARR_SIZE] = +static float128_t exp_arr[EXP_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0x3ffe000000000000, 0x0000000000000000), /* 2 */ @@ -66,10 +66,10 @@ static float128 exp_arr[EXP_ARR_SIZE] = PACK_FLOAT_128(0x3fd6ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 15 */ }; -extern float128 EvalPoly(float128 x, float128 *arr, int n, float_status_t &status); +extern float128_t EvalPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status); /* required -1 < x < 1 */ -static float128 poly_exp(float128 x, float_status_t &status) +static float128_t poly_exp(float128_t x, softfloat_status_t &status) { /* // 2 3 4 5 6 7 8 9 @@ -92,8 +92,8 @@ static float128 poly_exp(float128 x, float_status_t &status) // e - 1 ~ x * [ p(x) + x * q(x) ] // */ - float128 t = EvalPoly(x, exp_arr, EXP_ARR_SIZE, status); - return float128_mul(t, x, status); + float128_t t = EvalPoly(x, (const float128_t*) exp_arr, EXP_ARR_SIZE, status); + return f128_mul(t, x, &status); } // ================================================= @@ -114,32 +114,34 @@ static float128 poly_exp(float128 x, float_status_t &status) // e = 1 + --- + --- + --- + --- + --- + ... + --- + ... // 1! 2! 3! 4! 5! n! // - -floatx80 f2xm1(floatx80 a, float_status_t &status) +floatx80 f2xm1(floatx80 a, softfloat_status_t &status) { Bit64u zSig0, zSig1, zSig2; + struct exp32_sig64 normExpSig; // handle unsupported extended double-precision floating encodings if (extF80_isUnsupported(a)) { - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); return floatx80_default_nan; } - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); + Bit64u aSig = extF80_fraction(a); + Bit32s aExp = extF80_exp(a); + int aSign = extF80_sign(a); if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaN(a, status); + if (aSig << 1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, 0, 0, &status); return (aSign) ? floatx80_negone : a; } - if (aExp == 0) { - if (aSig == 0) return a; - float_raise(status, float_flag_denormal | float_flag_inexact); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + if (! aExp) { + if (! aSig) return a; + softfloat_raiseFlags(&status, softfloat_flag_denormal | softfloat_flag_inexact); + normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; tiny_argument: mul128By64To192(LN2_SIG_HI, LN2_SIG_LO, aSig, &zSig0, &zSig1, &zSig2); @@ -147,11 +149,10 @@ floatx80 f2xm1(floatx80 a, float_status_t &status) shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --aExp; } - return - roundAndPackFloatx80(80, aSign, aExp, zSig0, zSig1, status); + return softfloat_roundPackToExtF80(aSign, aExp, zSig0, zSig1, 80, &status); } - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (aExp < 0x3FFF) { @@ -162,14 +163,14 @@ floatx80 f2xm1(floatx80 a, float_status_t &status) /* using float128 for approximation */ /* ******************************** */ - float128 x = floatx80_to_float128(a, status); - x = float128_mul(x, float128_ln2, status); + float128_t x = extF80_to_f128(a, &status); + x = f128_mul(x, float128_ln2, &status); x = poly_exp(x, status); - return float128_to_floatx80(x, status); + return f128_to_extF80(x, &status); } else { - if (a.exp == 0xBFFF && ! (aSig<<1)) + if (a.signExp == 0xBFFF && ! (aSig<<1)) return floatx80_neghalf; return a; diff --git a/bochs/cpu/fpu/fpatan.cc b/bochs/cpu/fpu/fpatan.cc index df2ce96b0e..749317548c 100644 --- a/bochs/cpu/fpu/fpatan.cc +++ b/bochs/cpu/fpu/fpatan.cc @@ -25,27 +25,28 @@ these four paragraphs for those parts of this code that are retained. #define FLOAT128 -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "softfloat3e/include/softfloat.h" + +#include "fpu_trans.h" #include "fpu_constant.h" #define FPATAN_ARR_SIZE 11 -static const float128 float128_one = +static const float128_t float128_one = packFloat128(BX_CONST64(0x3fff000000000000), BX_CONST64(0x0000000000000000)); -static const float128 float128_sqrt3 = +static const float128_t float128_sqrt3 = packFloat128(BX_CONST64(0x3fffbb67ae8584ca), BX_CONST64(0xa73b25742d7078b8)); static const floatx80 floatx80_pi = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235)); -static const float128 float128_pi2 = +static const float128_t float128_pi2 = packFloat128(BX_CONST64(0x3fff921fb54442d1), BX_CONST64(0x8469898CC5170416)); -static const float128 float128_pi4 = +static const float128_t float128_pi4 = packFloat128(BX_CONST64(0x3ffe921fb54442d1), BX_CONST64(0x8469898CC5170416)); -static const float128 float128_pi6 = +static const float128_t float128_pi6 = packFloat128(BX_CONST64(0x3ffe0c152382d736), BX_CONST64(0x58465BB32E0F580F)); -static float128 atan_arr[FPATAN_ARR_SIZE] = +static float128_t atan_arr[FPATAN_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0xbffd555555555555, 0x5555555555555555), /* 3 */ @@ -60,10 +61,10 @@ static float128 atan_arr[FPATAN_ARR_SIZE] = PACK_FLOAT_128(0x3ffa861861861861, 0x8618618618618618) /* 21 */ }; -extern float128 OddPoly(float128 x, float128 *arr, int n, float_status_t &status); +extern float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status); /* |x| < 1/4 */ -static float128 poly_atan(float128 x1, float_status_t &status) +static float128_t poly_atan(float128_t x1, softfloat_status_t &status) { /* // 3 5 7 9 11 13 15 17 @@ -86,7 +87,7 @@ static float128 poly_atan(float128 x1, float_status_t &status) // atan(x) ~ x * [ p(x) + x * q(x) ] // */ - return OddPoly(x1, atan_arr, FPATAN_ARR_SIZE, status); + return OddPoly(x1, (const float128_t*) atan_arr, FPATAN_ARR_SIZE, status); } // ================================================= @@ -133,124 +134,123 @@ static float128 poly_atan(float128 x1, float_status_t &status) // 3 5 7 9 2n+1 // -floatx80 fpatan(floatx80 a, floatx80 b, float_status_t &status) +floatx80 fpatan(floatx80 a, floatx80 b, softfloat_status_t &status) { // handle unsupported extended double-precision floating encodings if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); return floatx80_default_nan; } - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - Bit64u bSig = extractFloatx80Frac(b); - Bit32s bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); + Bit64u aSig = extF80_fraction(a); + Bit32s aExp = extF80_exp(a); + int aSign = extF80_sign(a); + Bit64u bSig = extF80_fraction(b); + Bit32s bExp = extF80_exp(b); + int bSign = extF80_sign(b); int zSign = aSign ^ bSign; if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) - return propagateFloatx80NaN(a, b, status); + if (bSig<<1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaN(a, b, status); - - if (aSign) { /* return 3PI/4 */ - return roundAndPackFloatx80(80, bSign, - FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, status); - } - else { /* return PI/4 */ - return roundAndPackFloatx80(80, bSign, - FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); - } + if (aSig<<1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); + + if (aSign) /* return 3PI/4 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80, &status); + else /* return PI/4 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); } - if (aSig && (aExp == 0)) - float_raise(status, float_flag_denormal); + if (aSig && ! aExp) + softfloat_raiseFlags(&status, softfloat_flag_denormal); /* return PI/2 */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); } if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaN(a, b, status); + if (aSig<<1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); - if (bSig && (bExp == 0)) - float_raise(status, float_flag_denormal); + if (bSig && ! bExp) + softfloat_raiseFlags(&status, softfloat_flag_denormal); return_PI_or_ZERO: - if (aSign) { /* return PI */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); - } else { /* return 0 */ - return packFloatx80(bSign, 0, 0); - } + if (aSign) /* return PI */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); + else /* return 0 */ + return packToExtF80(bSign, 0, 0); } - if (bExp == 0) + if (! bExp) { - if (bSig == 0) { - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + if (! bSig) { + if (aSig && ! aExp) softfloat_raiseFlags(&status, softfloat_flag_denormal); goto return_PI_or_ZERO; } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - if (aExp == 0) + if (! aExp) { - if (aSig == 0) /* return PI/2 */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + if (! aSig) /* return PI/2 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; } - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); /* |a| = |b| ==> return PI/4 */ if (aSig == bSig && aExp == bExp) { if (aSign) - return roundAndPackFloatx80(80, bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, status); + return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80, &status); else - return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); } /* ******************************** */ /* using float128 for approximation */ /* ******************************** */ - float128 a128 = normalizeRoundAndPackFloat128(0, aExp-0x10, aSig, 0, status); - float128 b128 = normalizeRoundAndPackFloat128(0, bExp-0x10, bSig, 0, status); - float128 x; + float128_t a128 = softfloat_normRoundPackToF128(0, aExp-0x10, aSig, 0, &status); + float128_t b128 = softfloat_normRoundPackToF128(0, bExp-0x10, bSig, 0, &status); + float128_t x; int swap = 0, add_pi6 = 0, add_pi4 = 0; if (aExp > bExp || (aExp == bExp && aSig > bSig)) { - x = float128_div(b128, a128, status); + x = f128_div(b128, a128, &status); } else { - x = float128_div(a128, b128, status); + x = f128_div(a128, b128, &status); swap = 1; } - Bit32s xExp = extractFloat128Exp(x); + Bit32s xExp = expF128UI64(x.v64); if (xExp <= FLOATX80_EXP_BIAS-40) goto approximation_completed; - if (x.hi >= BX_CONST64(0x3ffe800000000000)) // 3/4 < x < 1 + if (x.v64 >= BX_CONST64(0x3ffe800000000000)) // 3/4 < x < 1 { /* arctan(x) = arctan((x-1)/(x+1)) + pi/4 */ - float128 t1 = float128_sub(x, float128_one, status); - float128 t2 = float128_add(x, float128_one, status); - x = float128_div(t1, t2, status); + float128_t t1 = f128_sub(x, float128_one, &status); + float128_t t2 = f128_add(x, float128_one, &status); + x = f128_div(t1, t2, &status); add_pi4 = 1; } else @@ -261,26 +261,26 @@ floatx80 fpatan(floatx80 a, floatx80 b, float_status_t &status) /* arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6 */ - float128 t1 = float128_mul(x, float128_sqrt3, status); - float128 t2 = float128_add(x, float128_sqrt3, status); - x = float128_sub(t1, float128_one, status); - x = float128_div(x, t2, status); + float128_t t1 = f128_mul(x, float128_sqrt3, &status); + float128_t t2 = f128_add(x, float128_sqrt3, &status); + x = f128_sub(t1, float128_one, &status); + x = f128_div(x, t2, &status); add_pi6 = 1; } } x = poly_atan(x, status); - if (add_pi6) x = float128_add(x, float128_pi6, status); - if (add_pi4) x = float128_add(x, float128_pi4, status); + if (add_pi6) x = f128_add(x, float128_pi6, &status); + if (add_pi4) x = f128_add(x, float128_pi4, &status); approximation_completed: - if (swap) x = float128_sub(float128_pi2, x, status); - floatx80 result = float128_to_floatx80(x, status); + if (swap) x = f128_sub(float128_pi2, x, &status); + floatx80 result = f128_to_extF80(x, &status); if (zSign) floatx80_chs(result); - int rSign = extractFloatx80Sign(result); + int rSign = extF80_sign(result); if (!bSign && rSign) - return floatx80_add(result, floatx80_pi, status); + return extF80_add(result, floatx80_pi, &status); if (bSign && !rSign) - return floatx80_sub(result, floatx80_pi, status); + return extF80_sub(result, floatx80_pi, &status); return result; } diff --git a/bochs/cpu/fpu/fprem.cc b/bochs/cpu/fpu/fprem.cc index ec59bdd325..29c52405b9 100644 --- a/bochs/cpu/fpu/fprem.cc +++ b/bochs/cpu/fpu/fprem.cc @@ -23,93 +23,103 @@ these four paragraphs for those parts of this code that are retained. * Stanislav Shwartsman [sshwarts at sourceforge net] * ==========================================================================*/ -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "fpu_trans.h" #define USE_estimateDiv128To64 -#include "softfloat-macros.h" +#include "softfloat-helpers.h" + +#include "../softfloat3e/include/specialize.h" // for softfloat_propagateNaNExtF80UI /* executes single exponent reduction cycle */ static Bit64u remainder_kernel(Bit64u aSig0, Bit64u bSig, int expDiff, Bit64u *zSig0, Bit64u *zSig1) { - Bit64u term0, term1; + uint128 term, z; Bit64u aSig1 = 0; - shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0); Bit64u q = estimateDiv128To64(aSig1, aSig0, bSig); - mul64To128(bSig, q, &term0, &term1); - sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); - while ((Bit64s)(*zSig1) < 0) { + term = softfloat_mul64To128(bSig, q); + z = softfloat_sub128(aSig1, aSig0, term.v64, term.v0); + while ((int64_t) z.v64 < 0) { --q; - add128(*zSig1, *zSig0, 0, bSig, zSig1, zSig0); + z = softfloat_add128(z.v64, z.v0, 0, bSig); } + *zSig0 = z.v0; + *zSig1 = z.v64; return q; } -static int do_fprem(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, int rounding_mode, float_status_t &status) +static int do_fprem(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, int rounding_mode, struct softfloat_status_t *status) { Bit32s aExp, bExp, zExp, expDiff; - Bit64u aSig0, aSig1, bSig; + Bit64u aSig0, aSig1 = 0, bSig; int aSign; + struct exp32_sig64 normExpSig; + uint128 term; + q = 0; // handle unsupported extended double-precision floating encodings if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(status, softfloat_flag_invalid); r = floatx80_default_nan; return -1; } - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); + bSig = extF80_fraction(b); + bExp = extF80_exp(b); if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { - r = propagateFloatx80NaN(a, b, status); + if ((aSig0<<1) || ((bExp == 0x7FFF) && (bSig<<1))) { + r = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif, status); return -1; } - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(status, softfloat_flag_invalid); r = floatx80_default_nan; return -1; } if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) { - r = propagateFloatx80NaN(a, b, status); + if (bSig << 1) { + r = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif, status); return -1; } - if (aExp == 0 && aSig0) { - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - r = (a.fraction & BX_CONST64(0x8000000000000000)) ? packFloatx80(aSign, aExp, aSig0) : a; + if (! aExp && aSig0) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; + r = (a.signif & BX_CONST64(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a; return 0; } r = a; return 0; } - if (bExp == 0) { - if (bSig == 0) { - float_raise(status, float_flag_invalid); + if (! bExp) { + if (! bSig) { + softfloat_raiseFlags(status, softfloat_flag_invalid); r = floatx80_default_nan; return -1; } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - if (aExp == 0) { - if (aSig0 == 0) { + if (! aExp) { + if (! aSig0) { r = a; return 0; } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; } - expDiff = aExp - bExp; - aSig1 = 0; - Bit32u overflow = 0; + expDiff = aExp - bExp; + int overflow = 0; if (expDiff >= 64) { int n = (expDiff & 0x1f) | 0x20; @@ -122,11 +132,10 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, int rounding if (expDiff < 0) { if (expDiff < -1) { - r = (a.fraction & BX_CONST64(0x8000000000000000)) ? - packFloatx80(aSign, aExp, aSig0) : a; + r = (a.signif & BX_CONST64(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a; return 0; } - shift128Right(aSig0, 0, 1, &aSig0, &aSig1); + shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1); expDiff = 0; } @@ -140,26 +149,28 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, int rounding } } - if (rounding_mode == float_round_nearest_even) - { + if (rounding_mode == softfloat_round_near_even) { Bit64u term0, term1; - shift128Right(bSig, 0, 1, &term0, &term1); - - if (! lt128(aSig0, aSig1, term0, term1)) - { - int lt = lt128(term0, term1, aSig0, aSig1); - int eq = eq128(aSig0, aSig1, term0, term1); - - if ((eq && (q & 1)) || lt) { - aSign = !aSign; - ++q; - } - if (lt) sub128(bSig, 0, aSig0, aSig1, &aSig0, &aSig1); + shortShift128Right(bSig, 0, 1, &term0, &term1); + + if (! softfloat_lt128(aSig0, aSig1, term0, term1)) { + int lt = softfloat_lt128(term0, term1, aSig0, aSig1); + int eq = softfloat_eq128(aSig0, aSig1, term0, term1); + + if ((eq && (q & 1)) || lt) { + aSign = !aSign; + ++q; + } + if (lt) { + term = softfloat_sub128(bSig, 0, aSig0, aSig1); + aSig0 = term.v64; + aSig1 = term.v0; + } } } } - r = normalizeRoundAndPackFloatx80(80, aSign, zExp, aSig0, aSig1, status); + r = softfloat_normRoundPackToExtF80(aSign, zExp, aSig0, aSig1, 80, status); return overflow; } @@ -169,9 +180,9 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, int rounding | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ -int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, float_status_t &status) +int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, struct softfloat_status_t *status) { - return do_fprem(a, b, r, q, float_round_nearest_even, status); + return do_fprem(a, b, r, q, softfloat_round_near_even, status); } /*---------------------------------------------------------------------------- @@ -183,7 +194,7 @@ int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, f | quotient of 'a' divided by 'b' to an integer. *----------------------------------------------------------------------------*/ -int floatx80_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, float_status_t &status) +int floatx80_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, struct softfloat_status_t *status) { - return do_fprem(a, b, r, q, float_round_to_zero, status); + return do_fprem(a, b, r, q, softfloat_round_to_zero, status); } diff --git a/bochs/cpu/fpu/fpu.cc b/bochs/cpu/fpu/fpu.cc index 58f905702c..ef755d9ad0 100644 --- a/bochs/cpu/fpu/fpu.cc +++ b/bochs/cpu/fpu/fpu.cc @@ -21,7 +21,6 @@ // ///////////////////////////////////////////////////////////////////////// - #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu/cpu.h" @@ -29,6 +28,8 @@ #include "iodev/iodev.h" +#include "softfloat3e/include/softfloat.h" + #define CHECK_PENDING_EXCEPTIONS 1 #if BX_SUPPORT_FPU @@ -402,8 +403,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FRSTOR(bxInstruction_c *i) /* read all registers in stack order */ for(int n=0;n<8;n++) { - tmp.fraction = read_virtual_qword(i->seg(), (offset + n*10) & i->asize_mask()); - tmp.exp = read_virtual_word (i->seg(), (offset + n*10 + 8) & i->asize_mask()); + tmp.signif = read_virtual_qword(i->seg(), (offset + n*10) & i->asize_mask()); + tmp.signExp = read_virtual_word (i->seg(), (offset + n*10 + 8) & i->asize_mask()); // update tag only if it is not empty BX_WRITE_FPU_REGISTER_AND_TAG(tmp, @@ -422,8 +423,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FNSAVE(bxInstruction_c *i) for(int n=0;n<8;n++) { floatx80 stn = BX_READ_FPU_REG(n); - write_virtual_qword(i->seg(), (offset + n*10) & i->asize_mask(), stn.fraction); - write_virtual_word (i->seg(), (offset + n*10 + 8) & i->asize_mask(), stn.exp); + write_virtual_qword(i->seg(), (offset + n*10) & i->asize_mask(), stn.signif); + write_virtual_word (i->seg(), (offset + n*10 + 8) & i->asize_mask(), stn.signExp); } BX_CPU_THIS_PTR the_i387.init(); @@ -504,8 +505,6 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPLEGACY(bxInstruction_c *i) #if BX_SUPPORT_FPU -#include "softfloatx80.h" - #include void BX_CPU_C::print_state_FPU(void) @@ -571,18 +570,18 @@ void BX_CPU_C::print_state_FPU(void) const floatx80 &fp = BX_FPU_REG(i); unsigned tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi((i-tos)&7); if (tag != FPU_Tag_Empty) tag = FPU_tagof(fp); - double f = pow(2.0, ((0x7fff & fp.exp) - 0x3fff)); - if (fp.exp & 0x8000) f = -f; + double f = pow(2.0, ((0x7fff & fp.signExp) - 0x3fff)); + if (fp.signExp & 0x8000) f = -f; #ifdef _MSC_VER - f *= (double)(signed __int64)(fp.fraction>>1) * scale_factor * 2; + f *= (double)(signed __int64)(fp.signif>>1) * scale_factor * 2; #else - f *= fp.fraction*scale_factor; + f *= fp.signif*scale_factor; #endif softfloat_class_t f_class = extF80_class(fp); fprintf(stderr, "%sFP%d ST%d(%c): raw 0x%04x:%08x%08x (%.10f) (%s)\n", i==tos?"=>":" ", i, (i-tos)&7, "v0se"[tag], - fp.exp & 0xffff, GET32H(fp.fraction), GET32L(fp.fraction), + fp.signExp & 0xffff, GET32H(fp.signif), GET32L(fp.signif), f, fp_class[f_class]); } } @@ -596,10 +595,10 @@ void BX_CPU_C::print_state_FPU(void) int FPU_tagof(const floatx80 ®) { - Bit32s exp = floatx80_exp(reg); + Bit32s exp = extF80_exp(reg); if (exp == 0) { - if (! floatx80_fraction(reg)) + if (! extF80_fraction(reg)) return FPU_Tag_Zero; /* The number is a de-normal or pseudodenormal. */ @@ -612,7 +611,7 @@ int FPU_tagof(const floatx80 ®) return FPU_Tag_Special; } - if (!(reg.fraction & BX_CONST64(0x8000000000000000))) + if (!(reg.signif & BX_CONST64(0x8000000000000000))) { /* Unsupported data type. */ /* Valid numbers have the ms bit set to 1. */ diff --git a/bochs/cpu/fpu/fpu_arith.cc b/bochs/cpu/fpu/fpu_arith.cc index 40055c902e..7cc1fd9b37 100644 --- a/bochs/cpu/fpu/fpu_arith.cc +++ b/bochs/cpu/fpu/fpu_arith.cc @@ -28,53 +28,54 @@ #if BX_SUPPORT_FPU -float_status_t i387cw_to_softfloat_status_word(Bit16u control_word) +#include "softfloat3e/include/softfloat.h" + +softfloat_status_t i387cw_to_softfloat_status_word(Bit16u control_word) { - float_status_t status; + softfloat_status_t status; int precision = control_word & FPU_CW_PC; switch(precision) { case FPU_PR_32_BITS: - status.float_rounding_precision = 32; + status.extF80_roundingPrecision = 32; break; case FPU_PR_64_BITS: - status.float_rounding_precision = 64; + status.extF80_roundingPrecision = 64; break; case FPU_PR_80_BITS: - status.float_rounding_precision = 80; + status.extF80_roundingPrecision = 80; break; default: /* With the precision control bits set to 01 "(reserved)", a real CPU behaves as if the precision control bits were set to 11 "80 bits" */ - status.float_rounding_precision = 80; + status.extF80_roundingPrecision = 80; } - status.float_exception_flags = 0; // clear exceptions before execution - status.float_nan_handling_mode = float_first_operand_nan; - status.float_rounding_mode = (control_word & FPU_CW_RC) >> 10; - status.flush_underflow_to_zero = 0; - status.float_suppress_exception = 0; - status.float_exception_masks = control_word & FPU_CW_Exceptions_Mask; - status.denormals_are_zeros = 0; + status.softfloat_exceptionFlags = 0; // clear exceptions before execution + status.softfloat_roundingMode = (control_word & FPU_CW_RC) >> 10; + status.softfloat_flush_underflow_to_zero = 0; + status.softfloat_suppressException = 0; + status.softfloat_exceptionMasks = control_word & FPU_CW_Exceptions_Mask; + status.softfloat_denormals_are_zeros = 0; return status; } -#include "softfloatx80.h" +#include "fpu_trans.h" -floatx80 FPU_handle_NaN(floatx80 a, int aIsNaN, float32 b32, int bIsNaN, float_status_t &status) +floatx80 FPU_handle_NaN(floatx80 a, int aIsNaN, float32 b32, int bIsNaN, softfloat_status_t &status) { int aIsSignalingNaN = extF80_isSignalingNaN(a); - int bIsSignalingNaN = float32_is_signaling_nan(b32); + int bIsSignalingNaN = f32_isSignalingNaN(b32); if (aIsSignalingNaN | bIsSignalingNaN) - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); // propagate QNaN to SNaN - a = propagateFloatx80NaN(a, status); + a = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, 0, 0, &status); if (aIsNaN & !bIsNaN) return a; @@ -89,19 +90,19 @@ floatx80 FPU_handle_NaN(floatx80 a, int aIsNaN, float32 b32, int bIsNaN, float_s else if (aIsNaN) { if (bIsSignalingNaN) return a; returnLargerSignificand: - if (a.fraction < b.fraction) return b; - if (b.fraction < a.fraction) return a; - return (a.exp < b.exp) ? a : b; + if (a.signif < b.signif) return b; + if (b.signif < a.signif) return a; + return (a.signExp < b.signExp) ? a : b; } else { return b; } } -bool FPU_handle_NaN(floatx80 a, float32 b, floatx80 &r, float_status_t &status) +bool FPU_handle_NaN(floatx80 a, float32 b, floatx80 &r, softfloat_status_t &status) { if (extF80_isUnsupported(a)) { - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); r = floatx80_default_nan; return true; } @@ -114,16 +115,16 @@ bool FPU_handle_NaN(floatx80 a, float32 b, floatx80 &r, float_status_t &status) return false; } -floatx80 FPU_handle_NaN(floatx80 a, int aIsNaN, float64 b64, int bIsNaN, float_status_t &status) +floatx80 FPU_handle_NaN(floatx80 a, int aIsNaN, float64 b64, int bIsNaN, softfloat_status_t &status) { int aIsSignalingNaN = extF80_isSignalingNaN(a); - int bIsSignalingNaN = float64_is_signaling_nan(b64); + int bIsSignalingNaN = f64_isSignalingNaN(b64); if (aIsSignalingNaN | bIsSignalingNaN) - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); // propagate QNaN to SNaN - a = propagateFloatx80NaN(a, status); + a = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, 0, 0, &status); if (aIsNaN & !bIsNaN) return a; @@ -138,19 +139,19 @@ floatx80 FPU_handle_NaN(floatx80 a, int aIsNaN, float64 b64, int bIsNaN, float_s else if (aIsNaN) { if (bIsSignalingNaN) return a; returnLargerSignificand: - if (a.fraction < b.fraction) return b; - if (b.fraction < a.fraction) return a; - return (a.exp < b.exp) ? a : b; + if (a.signif < b.signif) return b; + if (b.signif < a.signif) return a; + return (a.signExp < b.signExp) ? a : b; } else { return b; } } -bool FPU_handle_NaN(floatx80 a, float64 b, floatx80 &r, float_status_t &status) +bool FPU_handle_NaN(floatx80 a, float64 b, floatx80 &r, softfloat_status_t &status) { if (extF80_isUnsupported(a)) { - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); r = floatx80_default_nan; return true; } @@ -179,12 +180,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FADD_ST0_STj(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = BX_READ_FPU_REG(i->src()); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_add(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -208,12 +209,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FADD_STi_ST0(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(i->dst()); floatx80 b = BX_READ_FPU_REG(0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_add(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_WRITE_FPU_REG(result, i->dst()); if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); @@ -238,14 +239,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FADD_SINGLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(a, load_reg, result, status)) result = extF80_add(a, f32_to_extF80(load_reg, &status), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -267,14 +268,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FADD_DOUBLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(a, load_reg, result, status)) result = extF80_add(a, f64_to_extF80(load_reg, &status), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -299,12 +300,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIADD_WORD_INTEGER(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = i32_to_extF80((Bit32s)(load_reg)); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_add(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -329,12 +330,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIADD_DWORD_INTEGER(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = i32_to_extF80(load_reg); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_add(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -356,12 +357,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FMUL_ST0_STj(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = BX_READ_FPU_REG(i->src()); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_mul(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -385,12 +386,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FMUL_STi_ST0(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(i->dst()); floatx80 b = BX_READ_FPU_REG(0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_mul(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_WRITE_FPU_REG(result, i->dst()); if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); @@ -415,14 +416,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FMUL_SINGLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(a, load_reg, result, status)) result = extF80_mul(a, f32_to_extF80(load_reg, &status), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -444,14 +445,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FMUL_DOUBLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(a, load_reg, result, status)) result = extF80_mul(a, f64_to_extF80(load_reg, &status), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -476,12 +477,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIMUL_WORD_INTEGER(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = i32_to_extF80((Bit32s)(load_reg)); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_mul(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -506,12 +507,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIMUL_DWORD_INTEGER(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = i32_to_extF80(load_reg); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_mul(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -533,12 +534,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUB_ST0_STj(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = BX_READ_FPU_REG(i->src()); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_sub(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -560,12 +561,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUBR_ST0_STj(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(i->src()); floatx80 b = BX_READ_FPU_REG(0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_sub(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -589,12 +590,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUB_STi_ST0(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(i->dst()); floatx80 b = BX_READ_FPU_REG(0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_sub(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_WRITE_FPU_REG(result, i->dst()); if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); @@ -621,12 +622,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUBR_STi_ST0(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = BX_READ_FPU_REG(i->dst()); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_sub(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_WRITE_FPU_REG(result, i->dst()); if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); @@ -651,14 +652,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUB_SINGLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(a, load_reg, result, status)) result = extF80_sub(a, f32_to_extF80(load_reg, &status), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -680,14 +681,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUBR_SINGLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 b = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(b, load_reg, result, status)) result = extF80_sub(f32_to_extF80(load_reg, &status), b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -709,14 +710,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUB_DOUBLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(a, load_reg, result, status)) result = extF80_sub(a, f64_to_extF80(load_reg, &status), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -738,7 +739,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUBR_DOUBLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); @@ -746,7 +747,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUBR_DOUBLE_REAL(bxInstruction_c *i) if (! FPU_handle_NaN(b, load_reg, result, status)) result = extF80_sub(f64_to_extF80(load_reg, &status), b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -771,12 +772,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISUB_WORD_INTEGER(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = i32_to_extF80((Bit32s)(load_reg)); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_sub(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -801,12 +802,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISUBR_WORD_INTEGER(bxInstruction_c *i) floatx80 a = i32_to_extF80((Bit32s)(load_reg)); floatx80 b = BX_READ_FPU_REG(0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_sub(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -828,12 +829,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISUB_DWORD_INTEGER(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_sub(BX_READ_FPU_REG(0), i32_to_extF80(load_reg), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -858,12 +859,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISUBR_DWORD_INTEGER(bxInstruction_c *i) floatx80 a = i32_to_extF80(load_reg); floatx80 b = BX_READ_FPU_REG(0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_sub(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -885,12 +886,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIV_ST0_STj(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = BX_READ_FPU_REG(i->src()); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_div(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -912,12 +913,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIVR_ST0_STj(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(i->src()); floatx80 b = BX_READ_FPU_REG(0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_div(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -941,12 +942,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIV_STi_ST0(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(i->dst()); floatx80 b = BX_READ_FPU_REG(0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_div(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_WRITE_FPU_REG(result, i->dst()); if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); @@ -973,12 +974,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIVR_STi_ST0(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = BX_READ_FPU_REG(i->dst()); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_div(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_WRITE_FPU_REG(result, i->dst()); if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); @@ -1003,14 +1004,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIV_SINGLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(a, load_reg, result, status)) result = extF80_div(a, f32_to_extF80(load_reg, &status), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -1032,14 +1033,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIVR_SINGLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 b = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(b, load_reg, result, status)) result = extF80_div(f32_to_extF80(load_reg, &status), b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -1061,14 +1062,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIV_DOUBLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(a, load_reg, result, status)) result = extF80_div(a, f64_to_extF80(load_reg, &status), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -1090,14 +1091,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIVR_DOUBLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 b = BX_READ_FPU_REG(0), result; if (! FPU_handle_NaN(b, load_reg, result, status)) result = extF80_div(f64_to_extF80(load_reg, &status), b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -1122,12 +1123,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIDIV_WORD_INTEGER(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = i32_to_extF80((Bit32s)(load_reg)); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_div(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -1152,12 +1153,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIDIVR_WORD_INTEGER(bxInstruction_c *i) floatx80 a = i32_to_extF80((Bit32s)(load_reg)); floatx80 b = BX_READ_FPU_REG(0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_div(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -1182,12 +1183,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIDIV_DWORD_INTEGER(bxInstruction_c *i) floatx80 a = BX_READ_FPU_REG(0); floatx80 b = i32_to_extF80(load_reg); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_div(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -1212,12 +1213,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIDIVR_DWORD_INTEGER(bxInstruction_c *i) floatx80 a = i32_to_extF80(load_reg); floatx80 b = BX_READ_FPU_REG(0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_div(a, b, &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -1235,12 +1236,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSQRT(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_sqrt(BX_READ_FPU_REG(0), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -1259,12 +1260,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FRNDINT(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 result = extF80_roundToInt(BX_READ_FPU_REG(0), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); diff --git a/bochs/cpu/fpu/fpu_compare.cc b/bochs/cpu/fpu/fpu_compare.cc index 5c706bc436..1ec912c685 100644 --- a/bochs/cpu/fpu/fpu_compare.cc +++ b/bochs/cpu/fpu/fpu_compare.cc @@ -30,23 +30,25 @@ #include "cpu/decoder/ia_opcodes.h" -extern float_status_t i387cw_to_softfloat_status_word(Bit16u control_word); +#include "softfloat3e/include/softfloat.h" -#include "softfloatx80.h" +#include "softfloat-specialize.h" + +extern softfloat_status_t i387cw_to_softfloat_status_word(Bit16u control_word); static int status_word_flags_fpu_compare(int float_relation) { switch(float_relation) { - case float_relation_unordered: + case softfloat_relation_unordered: return (FPU_SW_C0|FPU_SW_C2|FPU_SW_C3); - case float_relation_greater: + case softfloat_relation_greater: return (0); - case float_relation_less: + case softfloat_relation_less: return (FPU_SW_C0); - case float_relation_equal: + case softfloat_relation_equal: return (FPU_SW_C3); } @@ -56,20 +58,20 @@ static int status_word_flags_fpu_compare(int float_relation) void BX_CPU_C::write_eflags_fpu_compare(int float_relation) { switch(float_relation) { - case float_relation_unordered: + case softfloat_relation_unordered: setEFlagsOSZAPC(EFlagsZFMask | EFlagsPFMask | EFlagsCFMask); break; - case float_relation_greater: + case softfloat_relation_greater: clearEFlagsOSZAPC(); break; - case float_relation_less: + case softfloat_relation_less: clearEFlagsOSZAPC(); assert_CF(); break; - case float_relation_equal: + case softfloat_relation_equal: clearEFlagsOSZAPC(); assert_ZF(); break; @@ -101,13 +103,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOM_STi(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); int rc = extF80_compare(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->src()), &status); setcc(status_word_flags_fpu_compare(rc)); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); } @@ -137,13 +139,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOMI_ST0_STj(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); int rc = extF80_compare(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->src()), &status); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); } @@ -173,13 +175,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FUCOMI_ST0_STj(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); int rc = extF80_compare_quiet(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->src()), &status); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); } @@ -207,13 +209,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FUCOM_STi(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); int rc = extF80_compare_quiet(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->src()), &status); setcc(status_word_flags_fpu_compare(rc)); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); } @@ -247,21 +249,21 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOM_SINGLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0); if (extF80_isNaN(a) || extF80_isUnsupported(a) || f32_isNaN(load_reg)) { - rc = float_relation_unordered; - float_raise(status, float_flag_invalid); + rc = softfloat_relation_unordered; + softfloat_raiseFlags(&status, softfloat_flag_invalid); } else { rc = extF80_compare(a, f32_to_extF80(load_reg, &status), &status); } setcc(status_word_flags_fpu_compare(rc)); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); } @@ -295,21 +297,21 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOM_DOUBLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0); if (extF80_isNaN(a) || extF80_isUnsupported(a) || f64_isNaN(load_reg)) { - rc = float_relation_unordered; - float_raise(status, float_flag_invalid); + rc = softfloat_relation_unordered; + softfloat_raiseFlags(&status, softfloat_flag_invalid); } else { rc = extF80_compare(a, f64_to_extF80(load_reg, &status), &status); } setcc(status_word_flags_fpu_compare(rc)); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); } @@ -343,14 +345,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FICOM_WORD_INTEGER(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); int rc = extF80_compare(BX_READ_FPU_REG(0), i32_to_extF80((Bit32s)(load_reg)), &status); setcc(status_word_flags_fpu_compare(rc)); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); } @@ -384,13 +386,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FICOM_DWORD_INTEGER(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); int rc = extF80_compare(BX_READ_FPU_REG(0), i32_to_extF80(load_reg), &status); setcc(status_word_flags_fpu_compare(rc)); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); } @@ -422,13 +424,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOMPP(bxInstruction_c *i) bool quiet = (i->getIaOpcode() == BX_IA_FUCOMPP); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); int rc = extF80_compare(BX_READ_FPU_REG(0), BX_READ_FPU_REG(1), quiet, &status); setcc(status_word_flags_fpu_compare(rc)); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_CPU_THIS_PTR the_i387.FPU_pop(); BX_CPU_THIS_PTR the_i387.FPU_pop(); } @@ -449,14 +451,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FTST(bxInstruction_c *i) setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3); } else { - extern const floatx80 Const_Z; + static floatx80 Const_Z = packFloatx80(0, 0x0000, 0); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); int rc = extF80_compare(BX_READ_FPU_REG(0), Const_Z, &status); setcc(status_word_flags_fpu_compare(rc)); - FPU_exception(i, status.float_exception_flags); + FPU_exception(i, status.softfloat_exceptionFlags); } BX_NEXT_INSTR(i); @@ -469,7 +471,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FXAM(bxInstruction_c *i) BX_CPU_THIS_PTR FPU_update_last_instruction(i); floatx80 reg = BX_READ_FPU_REG(0); - int sign = floatx80_sign(reg); + int sign = extF80_sign(reg); /* * Examine the contents of the ST(0) register and sets the condition diff --git a/bochs/cpu/fpu/fpu_const.cc b/bochs/cpu/fpu/fpu_const.cc index 7ca8e01262..87a8dd04b1 100644 --- a/bochs/cpu/fpu/fpu_const.cc +++ b/bochs/cpu/fpu/fpu_const.cc @@ -28,9 +28,8 @@ #if BX_SUPPORT_FPU -#include "softfloatx80.h" +#include "softfloat-specialize.h" -const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); const floatx80 Const_Z = packFloatx80(0, 0x0000, 0); const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe)); @@ -48,7 +47,7 @@ const floatx80 Const_INF = packFloatx80(0, 0x7fff, BX_CONST64(0x800000000000000 BX_CPP_INLINE floatx80 FPU_round_const(const floatx80 &a, int adj) { floatx80 result = a; - result.fraction += adj; + result.signif += adj; return result; } diff --git a/bochs/cpu/fpu/fpu_load_store.cc b/bochs/cpu/fpu/fpu_load_store.cc index 1b2a03fac5..1178b57796 100644 --- a/bochs/cpu/fpu/fpu_load_store.cc +++ b/bochs/cpu/fpu/fpu_load_store.cc @@ -32,9 +32,10 @@ #define swap_values16u(a, b) { Bit16u tmp = a; a = b; b = tmp; } -extern float_status_t i387cw_to_softfloat_status_word(Bit16u control_word); +extern softfloat_status_t i387cw_to_softfloat_status_word(Bit16u control_word); -#include "softfloatx80.h" +#include "softfloat-specialize.h" +#include "fpu_trans.h" void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_STi(bxInstruction_c *i) { @@ -84,13 +85,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_SINGLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); // convert to floatx80 format floatx80 result = f32_to_extF80(load_reg, &status); - unsigned unmasked = FPU_exception(i, status.float_exception_flags); + unsigned unmasked = FPU_exception(i, status.softfloat_exceptionFlags); if (! (unmasked & FPU_CW_Invalid)) { BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); @@ -115,13 +116,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_DOUBLE_REAL(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); // convert to floatx80 format floatx80 result = f64_to_extF80(load_reg, &status); - unsigned unmasked = FPU_exception(i, status.float_exception_flags); + unsigned unmasked = FPU_exception(i, status.softfloat_exceptionFlags); if (! (unmasked & FPU_CW_Invalid)) { BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); @@ -137,8 +138,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_EXTENDED_REAL(bxInstruction_c *i) floatx80 result; RMAddr(i) = BX_CPU_RESOLVE_ADDR(i); - result.fraction = read_virtual_qword(i->seg(), RMAddr(i)); - result.exp = read_virtual_word(i->seg(), (RMAddr(i)+8) & i->asize_mask()); + result.signif = read_virtual_qword(i->seg(), RMAddr(i)); + result.signExp = read_virtual_word(i->seg(), (RMAddr(i)+8) & i->asize_mask()); FPU_update_last_instruction(i); @@ -171,7 +172,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FILD_WORD_INTEGER(bxInstruction_c *i) FPU_stack_overflow(i); } else { - extFloat80_t result = i32_to_extF80((Bit32s) load_reg); + floatx80 result = i32_to_extF80((Bit32s) load_reg); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); } @@ -195,7 +196,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FILD_DWORD_INTEGER(bxInstruction_c *i) FPU_stack_overflow(i); } else { - extFloat80_t result = i32_to_extF80(load_reg); + floatx80 result = i32_to_extF80(load_reg); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); } @@ -219,7 +220,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FILD_QWORD_INTEGER(bxInstruction_c *i) FPU_stack_overflow(i); } else { - extFloat80_t result = i64_to_extF80(load_reg); + floatx80 result = i64_to_extF80(load_reg); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); } @@ -323,12 +324,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FST_SINGLE_REAL(bxInstruction_c *i) } else { - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = extF80_to_f32(BX_READ_FPU_REG(0), &status); - if (FPU_exception(i, status.float_exception_flags, 1)) + if (FPU_exception(i, status.softfloat_exceptionFlags, 1)) BX_NEXT_INSTR(i); } @@ -369,12 +370,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FST_DOUBLE_REAL(bxInstruction_c *i) } else { - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = extF80_to_f64(BX_READ_FPU_REG(0), &status); - if (FPU_exception(i, status.float_exception_flags, 1)) + if (FPU_exception(i, status.softfloat_exceptionFlags, 1)) BX_NEXT_INSTR(i); } @@ -415,8 +416,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSTP_EXTENDED_REAL(bxInstruction_c *i) save_reg = BX_READ_FPU_REG(0); } - write_virtual_qword(i->seg(), RMAddr(i), save_reg.fraction); - write_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask(), save_reg.exp); + write_virtual_qword(i->seg(), RMAddr(i), save_reg.signif); + write_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask(), save_reg.signExp); BX_CPU_THIS_PTR the_i387.FPU_pop(); @@ -448,12 +449,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIST_WORD_INTEGER(bxInstruction_c *i) } else { - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = extF80_to_i16(BX_READ_FPU_REG(0), &status); - if (FPU_exception(i, status.float_exception_flags, 1)) + if (FPU_exception(i, status.softfloat_exceptionFlags, 1)) BX_NEXT_INSTR(i); } @@ -494,12 +495,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIST_DWORD_INTEGER(bxInstruction_c *i) } else { - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = extF80_to_i32(BX_READ_FPU_REG(0), &status); - if (FPU_exception(i, status.float_exception_flags, 1)) + if (FPU_exception(i, status.softfloat_exceptionFlags, 1)) BX_NEXT_INSTR(i); } @@ -538,12 +539,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISTP_QWORD_INTEGER(bxInstruction_c *i) } else { - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = extF80_to_i64(BX_READ_FPU_REG(0), &status); - if (FPU_exception(i, status.float_exception_flags, 1)) + if (FPU_exception(i, status.softfloat_exceptionFlags, 1)) BX_NEXT_INSTR(i); } @@ -588,21 +589,21 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FBSTP_PACKED_BCD(bxInstruction_c *i) } else { - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 reg = BX_READ_FPU_REG(0); Bit64s save_val = extF80_to_i64(reg, &status); - int sign = (reg.exp & 0x8000) != 0; + int sign = extF80_sign(reg); if (sign) save_val = -save_val; if (save_val > BX_CONST64(999999999999999999)) { - status.float_exception_flags = float_flag_invalid; // throw away other flags + softfloat_setFlags(&status, softfloat_flag_invalid); // throw away other flags } - if (! (status.float_exception_flags & float_flag_invalid)) + if (! (status.softfloat_exceptionFlags & softfloat_flag_invalid)) { save_reg_hi = (sign) ? 0x8000 : 0; save_reg_lo = 0; @@ -618,7 +619,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FBSTP_PACKED_BCD(bxInstruction_c *i) } /* check for fpu arithmetic exceptions */ - if (FPU_exception(i, status.float_exception_flags, 1)) + if (FPU_exception(i, status.softfloat_exceptionFlags, 1)) BX_NEXT_INSTR(i); } @@ -660,12 +661,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISTTP16(bxInstruction_c *i) } else { - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = extF80_to_i16_round_to_zero(BX_READ_FPU_REG(0), &status); - if (FPU_exception(i, status.float_exception_flags, 1)) + if (FPU_exception(i, status.softfloat_exceptionFlags, 1)) BX_NEXT_INSTR(i); } @@ -705,12 +706,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISTTP32(bxInstruction_c *i) } else { - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = extF80_to_i32_round_to_zero(BX_READ_FPU_REG(0), &status); - if (FPU_exception(i, status.float_exception_flags, 1)) + if (FPU_exception(i, status.softfloat_exceptionFlags, 1)) BX_NEXT_INSTR(i); } @@ -750,12 +751,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISTTP64(bxInstruction_c *i) } else { - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = extF80_to_i64_round_to_zero(BX_READ_FPU_REG(0), &status); - if (FPU_exception(i, status.float_exception_flags, 1)) + if (FPU_exception(i, status.softfloat_exceptionFlags, 1)) BX_NEXT_INSTR(i); } diff --git a/bochs/cpu/fpu/fpu_misc.cc b/bochs/cpu/fpu/fpu_misc.cc index 6efd51cff5..bbef477f06 100644 --- a/bochs/cpu/fpu/fpu_misc.cc +++ b/bochs/cpu/fpu/fpu_misc.cc @@ -28,7 +28,7 @@ #if BX_SUPPORT_FPU -#include "softfloatx80.h" +#include "fpu_trans.h" /* D9 C8 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FXCH_STi(bxInstruction_c *i) diff --git a/bochs/cpu/fpu/fpu_trans.cc b/bochs/cpu/fpu/fpu_trans.cc index c1e5a46c36..95a77c1301 100644 --- a/bochs/cpu/fpu/fpu_trans.cc +++ b/bochs/cpu/fpu/fpu_trans.cc @@ -28,10 +28,10 @@ #if BX_SUPPORT_FPU -#include "softfloatx80.h" +#include "fpu_trans.h" #include "softfloat-specialize.h" -extern float_status_t i387cw_to_softfloat_status_word(Bit16u control_word); +extern softfloat_status_t i387cw_to_softfloat_status_word(Bit16u control_word); /* D9 F0 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::F2XM1(bxInstruction_c *i) @@ -46,12 +46,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::F2XM1(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word() | FPU_PR_80_BITS); floatx80 result = f2xm1(BX_READ_FPU_REG(0), status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -71,12 +71,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FYL2X(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word() | FPU_PR_80_BITS); floatx80 result = fyl2x(BX_READ_FPU_REG(0), BX_READ_FPU_REG(1), status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_CPU_THIS_PTR the_i387.FPU_pop(); BX_WRITE_FPU_REG(result, 0); } @@ -111,9 +111,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPTAN(bxInstruction_c *i) BX_NEXT_INSTR(i); } - extern const floatx80 Const_1; + static const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word() | FPU_PR_80_BITS); floatx80 y = BX_READ_FPU_REG(0); @@ -123,9 +123,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPTAN(bxInstruction_c *i) BX_NEXT_INSTR(i); } - if (floatx80_is_nan(y)) + if (extF80_isNaN(y)) { - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_WRITE_FPU_REG(y, 0); BX_CPU_THIS_PTR the_i387.FPU_push(); @@ -135,7 +135,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPTAN(bxInstruction_c *i) BX_NEXT_INSTR(i); } - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_WRITE_FPU_REG(y, 0); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(Const_1, 0); @@ -158,12 +158,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPATAN(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word() | FPU_PR_80_BITS); floatx80 result = fpatan(BX_READ_FPU_REG(0), BX_READ_FPU_REG(1), status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_CPU_THIS_PTR the_i387.FPU_pop(); BX_WRITE_FPU_REG(result, 0); } @@ -197,13 +197,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FXTRACT(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 a = BX_READ_FPU_REG(0); - floatx80 b = floatx80_extract(a, status); + floatx80 b = extF80_extract(&a, &status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_WRITE_FPU_REG(b, 0); // exponent BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(a, 0); // fraction @@ -227,7 +227,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPREM1(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); Bit64u quotient; @@ -236,9 +236,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPREM1(bxInstruction_c *i) floatx80 b = BX_READ_FPU_REG(1); floatx80 result; - int flags = floatx80_ieee754_remainder(a, b, result, quotient, status); + int flags = floatx80_ieee754_remainder(a, b, result, quotient, &status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { if (flags >= 0) { int cc = 0; if (flags) cc = FPU_SW_C2; @@ -270,7 +270,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPREM(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); Bit64u quotient; @@ -279,9 +279,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPREM(bxInstruction_c *i) floatx80 b = BX_READ_FPU_REG(1); floatx80 result; - int flags = floatx80_remainder(a, b, result, quotient, status); + int flags = floatx80_remainder(a, b, result, quotient, &status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { if (flags >= 0) { int cc = 0; if (flags) cc = FPU_SW_C2; @@ -312,12 +312,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FYL2XP1(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word() | FPU_PR_80_BITS); floatx80 result = fyl2xp1(BX_READ_FPU_REG(0), BX_READ_FPU_REG(1), status); - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_CPU_THIS_PTR the_i387.FPU_pop(); BX_WRITE_FPU_REG(result, 0); } @@ -352,7 +352,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSINCOS(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word() | FPU_PR_80_BITS); floatx80 y = BX_READ_FPU_REG(0); @@ -363,7 +363,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSINCOS(bxInstruction_c *i) BX_NEXT_INSTR(i); } - if (! FPU_exception(i, status.float_exception_flags)) { + if (! FPU_exception(i, status.softfloat_exceptionFlags)) { BX_WRITE_FPU_REG(sin_y, 0); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(cos_y, 0); @@ -386,12 +386,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSCALE(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word()); - floatx80 result = floatx80_scale(BX_READ_FPU_REG(0), BX_READ_FPU_REG(1), status); + floatx80 result = extF80_scale(BX_READ_FPU_REG(0), BX_READ_FPU_REG(1), &status); - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); @@ -411,7 +411,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSIN(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word() | FPU_PR_80_BITS); floatx80 y = BX_READ_FPU_REG(0); @@ -421,7 +421,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSIN(bxInstruction_c *i) BX_NEXT_INSTR(i); } - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(y, 0); BX_NEXT_INSTR(i); @@ -441,7 +441,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOS(bxInstruction_c *i) BX_NEXT_INSTR(i); } - float_status_t status = + softfloat_status_t status = i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word() | FPU_PR_80_BITS); floatx80 y = BX_READ_FPU_REG(0); @@ -451,7 +451,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOS(bxInstruction_c *i) BX_NEXT_INSTR(i); } - if (! FPU_exception(i, status.float_exception_flags)) + if (! FPU_exception(i, status.softfloat_exceptionFlags)) BX_WRITE_FPU_REG(y, 0); BX_NEXT_INSTR(i); diff --git a/bochs/cpu/fpu/fpu_trans.h b/bochs/cpu/fpu/fpu_trans.h new file mode 100644 index 0000000000..7515d5e4f7 --- /dev/null +++ b/bochs/cpu/fpu/fpu_trans.h @@ -0,0 +1,85 @@ +///////////////////////////////////////////////////////////////////////// +// $Id$ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2003-2018 Stanislav Shwartsman +// Written by Stanislav Shwartsman [sshwarts at sourceforge net] +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +///////////////////////////////////////////////////////////////////////// + +#ifndef BX_FPU_TRANSCENDENTAL_H +#define BX_FPU_TRANSCENDENTAL_H + +#include "softfloat3e/include/softfloat.h" + +#include "softfloat-specialize.h" + +extern floatx80 softfloat_propagateNaNExtF80UI(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision operations. +*----------------------------------------------------------------------------*/ + +int floatx80_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, struct softfloat_status_t *status); +int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, struct softfloat_status_t *status); + +floatx80 f2xm1(floatx80 a, softfloat_status_t &status); +floatx80 fyl2x(floatx80 a, floatx80 b, softfloat_status_t &status); +floatx80 fyl2xp1(floatx80 a, floatx80 b, softfloat_status_t &status); +floatx80 fpatan(floatx80 a, floatx80 b, softfloat_status_t &status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision trigonometric functions. +*----------------------------------------------------------------------------*/ + +int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, softfloat_status_t &status); +int fsin(floatx80 &a, softfloat_status_t &status); +int fcos(floatx80 &a, softfloat_status_t &status); +int ftan(floatx80 &a, softfloat_status_t &status); + +/*----------------------------------------------------------------------------- +| Calculates the absolute value of the extended double-precision floating-point +| value `a'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE floatx80& floatx80_abs(floatx80 ®) +{ + reg.signExp &= 0x7FFF; + return reg; +} + +/*----------------------------------------------------------------------------- +| Changes the sign of the extended double-precision floating-point value 'a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE floatx80& floatx80_chs(floatx80 ®) +{ + reg.signExp ^= 0x8000; + return reg; +} + +/*----------------------------------------------------------------------------- +| Commonly used extended double-precision floating-point constants. +*----------------------------------------------------------------------------*/ + +extern const floatx80 Const_Z; +extern const floatx80 Const_1; + +#endif diff --git a/bochs/cpu/fpu/fsincos.cc b/bochs/cpu/fpu/fsincos.cc index 8dfc7c9319..ba0984a292 100644 --- a/bochs/cpu/fpu/fsincos.cc +++ b/bochs/cpu/fpu/fsincos.cc @@ -26,8 +26,8 @@ these four paragraphs for those parts of this code that are retained. #define FLOAT128 #define USE_estimateDiv128To64 -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "fpu_trans.h" +#include "softfloat-helpers.h" #include "fpu_constant.h" static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); @@ -56,7 +56,7 @@ static int reduce_trig_arg(int expDiff, int &zSign, Bit64u &aSig0, Bit64u &aSig1 Bit64u term0, term1, q = 0; if (expDiff < 0) { - shift128Right(aSig0, 0, 1, &aSig0, &aSig1); + shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1); expDiff = 0; } if (expDiff > 0) { @@ -69,11 +69,11 @@ static int reduce_trig_arg(int expDiff, int &zSign, Bit64u &aSig0, Bit64u &aSig1 } } - shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); - if (! lt128(aSig0, aSig1, term0, term1)) + shortShift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); + if (! softfloat_lt128(aSig0, aSig1, term0, term1)) { - int lt = lt128(term0, term1, aSig0, aSig1); - int eq = eq128(aSig0, aSig1, term0, term1); + int lt = softfloat_lt128(term0, term1, aSig0, aSig1); + int eq = softfloat_eq128(aSig0, aSig1, term0, term1); if ((eq && (q & 1)) || lt) { zSign = !zSign; @@ -88,7 +88,7 @@ static int reduce_trig_arg(int expDiff, int &zSign, Bit64u &aSig0, Bit64u &aSig1 #define SIN_ARR_SIZE 11 #define COS_ARR_SIZE 11 -static float128 sin_arr[SIN_ARR_SIZE] = +static float128_t sin_arr[SIN_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /* 3 */ @@ -103,7 +103,7 @@ static float128 sin_arr[SIN_ARR_SIZE] = PACK_FLOAT_128(0x3fbd71b8ef6dcf57, 0x18bef146fcee6e45) /* 21 */ }; -static float128 cos_arr[COS_ARR_SIZE] = +static float128_t cos_arr[COS_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 0 */ PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /* 2 */ @@ -118,10 +118,10 @@ static float128 cos_arr[COS_ARR_SIZE] = PACK_FLOAT_128(0x3fc1e542ba402022, 0x507a9cad2bf8f0bb) /* 20 */ }; -extern float128 OddPoly (float128 x, float128 *arr, int n, float_status_t &status); +extern float128_t OddPoly (float128_t x, const float128_t *arr, int n, softfloat_status_t &status); /* 0 <= x <= pi/4 */ -BX_CPP_INLINE float128 poly_sin(float128 x, float_status_t &status) +BX_CPP_INLINE float128_t poly_sin(float128_t x, softfloat_status_t &status) { // 3 5 7 9 11 13 15 // x x x x x x x @@ -143,13 +143,13 @@ BX_CPP_INLINE float128 poly_sin(float128 x, float_status_t &status) // sin(x) ~ x * [ p(x) + x * q(x) ] // - return OddPoly(x, sin_arr, SIN_ARR_SIZE, status); + return OddPoly(x, (const float128_t*) sin_arr, SIN_ARR_SIZE, status); } -extern float128 EvenPoly(float128 x, float128 *arr, int n, float_status_t &status); +extern float128_t EvenPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status); /* 0 <= x <= pi/4 */ -BX_CPP_INLINE float128 poly_cos(float128 x, float_status_t &status) +BX_CPP_INLINE float128_t poly_cos(float128_t x, softfloat_status_t &status) { // 2 4 6 8 10 12 14 // x x x x x x x @@ -166,7 +166,7 @@ BX_CPP_INLINE float128 poly_cos(float128 x, float_status_t &status) // cos(x) ~ [ p(x) + x * q(x) ] // - return EvenPoly(x, cos_arr, COS_ARR_SIZE, status); + return EvenPoly(x, (const float128_t*) cos_arr, COS_ARR_SIZE, status); } BX_CPP_INLINE void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) @@ -181,7 +181,7 @@ BX_CPP_INLINE void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx if (cos_a) *cos_a = floatx80_one; } -static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, float_status_t &status) +static floatx80 sincos_approximation(int neg, float128_t r, Bit64u quotient, softfloat_status_t &status) { if (quotient & 0x1) { r = poly_cos(r, status); @@ -190,7 +190,7 @@ static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, float r = poly_sin(r, status); } - floatx80 result = float128_to_floatx80(r, status); + floatx80 result = f128_to_extF80(r, &status); if (quotient & 0x2) neg = ! neg; @@ -220,7 +220,7 @@ static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, float // sin(x+2pi) = sin(x) // -int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, float_status_t &status) +int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, softfloat_status_t &status) { Bit64u aSig0, aSig1 = 0; Bit32s aExp, zExp, expDiff; @@ -232,42 +232,44 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, float_status_t &status goto invalid; } - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); /* invalid argument */ if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1)) { - sincos_invalid(sin_a, cos_a, propagateFloatx80NaN(a, status)); + if (aSig0 << 1) { + sincos_invalid(sin_a, cos_a, softfloat_propagateNaNExtF80UI(a.signExp, aSig0, 0, 0, &status)); return 0; } invalid: - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); sincos_invalid(sin_a, cos_a, floatx80_default_nan); return 0; } - if (aExp == 0) { - if (aSig0 == 0) { + if (! aExp) { + if (! aSig0) { sincos_tiny_argument(sin_a, cos_a, a); return 0; } - float_raise(status, float_flag_denormal); + softfloat_raiseFlags(&status, softfloat_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & BX_CONST64(0x8000000000000000))) { - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (sin_a) - float_raise(status, float_flag_underflow); + softfloat_raiseFlags(&status, softfloat_flag_underflow); sincos_tiny_argument(sin_a, cos_a, a); return 0; } - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; } zSign = aSign; @@ -278,7 +280,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, float_status_t &status if (expDiff >= 63) return -1; - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { @@ -297,7 +299,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, float_status_t &status /* **************************** */ /* using float128 for approximation */ - float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status); + float128_t r = softfloat_normRoundPackToF128(0, zExp-0x10, aSig0, aSig1, &status); if (aSign) q = -q; if (sin_a) *sin_a = sincos_approximation(zSign, r, q, status); @@ -306,12 +308,12 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, float_status_t &status return 0; } -int fsin(floatx80 &a, float_status_t &status) +int fsin(floatx80 &a, softfloat_status_t &status) { return fsincos(a, &a, 0, status); } -int fcos(floatx80 &a, float_status_t &status) +int fcos(floatx80 &a, softfloat_status_t &status) { return fsincos(a, 0, &a, status); } @@ -343,7 +345,7 @@ int fcos(floatx80 &a, float_status_t &status) // cos(x) // -int ftan(floatx80 &a, float_status_t &status) +int ftan(floatx80 &a, softfloat_status_t &status) { Bit64u aSig0, aSig1 = 0; Bit32s aExp, zExp, expDiff; @@ -355,34 +357,37 @@ int ftan(floatx80 &a, float_status_t &status) goto invalid; } - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); /* invalid argument */ if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1)) + if (aSig0 << 1) { - a = propagateFloatx80NaN(a, status); + a = softfloat_propagateNaNExtF80UI(a.signExp, aSig0, 0, 0, &status); return 0; } invalid: - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); a = floatx80_default_nan; return 0; } - if (aExp == 0) { - if (aSig0 == 0) return 0; - float_raise(status, float_flag_denormal); + if (! aExp) { + if (! aSig0) return 0; + softfloat_raiseFlags(&status, softfloat_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & BX_CONST64(0x8000000000000000))) { - float_raise(status, float_flag_inexact | float_flag_underflow); + softfloat_raiseFlags(&status, softfloat_flag_inexact | softfloat_flag_underflow); return 0; } - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; } zSign = aSign; @@ -393,7 +398,7 @@ int ftan(floatx80 &a, float_status_t &status) if (expDiff >= 63) return -1; - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { @@ -411,19 +416,19 @@ int ftan(floatx80 &a, float_status_t &status) /* **************************** */ /* using float128 for approximation */ - float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status); + float128_t r = softfloat_normRoundPackToF128(0, zExp-0x10, aSig0, aSig1, &status); - float128 sin_r = poly_sin(r, status); - float128 cos_r = poly_cos(r, status); + float128_t sin_r = poly_sin(r, status); + float128_t cos_r = poly_cos(r, status); if (q & 0x1) { - r = float128_div(cos_r, sin_r, status); + r = f128_div(cos_r, sin_r, &status); zSign = ! zSign; } else { - r = float128_div(sin_r, cos_r, status); + r = f128_div(sin_r, cos_r, &status); } - a = float128_to_floatx80(r, status); + a = f128_to_extF80(r, &status); if (zSign) floatx80_chs(a); diff --git a/bochs/cpu/fpu/fyl2x.cc b/bochs/cpu/fpu/fyl2x.cc index d50dfcdea2..f80f2fcded 100644 --- a/bochs/cpu/fpu/fyl2x.cc +++ b/bochs/cpu/fpu/fyl2x.cc @@ -25,28 +25,27 @@ these four paragraphs for those parts of this code that are retained. #define FLOAT128 -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "fpu_trans.h" +#include "softfloat-helpers.h" #include "fpu_constant.h" -static const floatx80 floatx80_one = - packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); +static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); -static const float128 float128_one = +static const float128_t float128_one = packFloat128(BX_CONST64(0x3fff000000000000), BX_CONST64(0x0000000000000000)); -static const float128 float128_two = +static const float128_t float128_two = packFloat128(BX_CONST64(0x4000000000000000), BX_CONST64(0x0000000000000000)); -static const float128 float128_ln2inv2 = +static const float128_t float128_ln2inv2 = packFloat128(BX_CONST64(0x400071547652b82f), BX_CONST64(0xe1777d0ffda0d23a)); #define SQRT2_HALF_SIG BX_CONST64(0xb504f333f9de6484) -extern float128 OddPoly(float128 x, float128 *arr, int n, float_status_t &status); +extern float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status); #define L2_ARR_SIZE 9 -static float128 ln_arr[L2_ARR_SIZE] = +static float128_t ln_arr[L2_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /* 3 */ @@ -59,7 +58,7 @@ static float128 ln_arr[L2_ARR_SIZE] = PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2) /* 17 */ }; -static float128 poly_ln(float128 x1, float_status_t &status) +static float128_t poly_ln(float128_t x1, softfloat_status_t &status) { /* // @@ -84,28 +83,28 @@ static float128 poly_ln(float128 x1, float_status_t &status) // 1-u // */ - return OddPoly(x1, ln_arr, L2_ARR_SIZE, status); + return OddPoly(x1, (const float128_t*) ln_arr, L2_ARR_SIZE, status); } /* required sqrt(2)/2 < x < sqrt(2) */ -static float128 poly_l2(float128 x, float_status_t &status) +static float128_t poly_l2(float128_t x, softfloat_status_t &status) { /* using float128 for approximation */ - float128 x_p1 = float128_add(x, float128_one, status); - float128 x_m1 = float128_sub(x, float128_one, status); - x = float128_div(x_m1, x_p1, status); + float128_t x_p1 = f128_add(x, float128_one, &status); + float128_t x_m1 = f128_sub(x, float128_one, &status); + x = f128_div(x_m1, x_p1, &status); x = poly_ln(x, status); - x = float128_mul(x, float128_ln2inv2, status); + x = f128_mul(x, float128_ln2inv2, &status); return x; } -static float128 poly_l2p1(float128 x, float_status_t &status) +static float128_t poly_l2p1(float128_t x, softfloat_status_t &status) { /* using float128 for approximation */ - float128 x_p2 = float128_add(x, float128_two, status); - x = float128_div(x, x_p2, status); + float128_t x_plus2 = f128_add(x, float128_two, &status); + x = f128_div(x, x_plus2, &status); x = poly_ln(x, status); - x = float128_mul(x, float128_ln2inv2, status); + x = f128_mul(x, float128_ln2inv2, &status); return x; } @@ -134,74 +133,76 @@ static float128 poly_l2p1(float128 x, float_status_t &status) // 1-u 3 5 7 2n+1 // -floatx80 fyl2x(floatx80 a, floatx80 b, float_status_t &status) +floatx80 fyl2x(floatx80 a, floatx80 b, softfloat_status_t &status) { // handle unsupported extended double-precision floating encodings if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { invalid: - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); return floatx80_default_nan; } - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - Bit64u bSig = extractFloatx80Frac(b); - Bit32s bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); + Bit64u aSig = extF80_fraction(a); + Bit32s aExp = extF80_exp(a); + int aSign = extF80_sign(a); + Bit64u bSig = extF80_fraction(b); + Bit32s bExp = extF80_exp(b); + int bSign = extF80_sign(b); int zSign = bSign ^ 1; if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b, status); + if ((aSig<<1) || ((bExp == 0x7FFF) && (bSig<<1))) { + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); } if (aSign) goto invalid; else { - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(status, float_flag_denormal); + if (! bExp) { + if (! bSig) goto invalid; + softfloat_raiseFlags(&status, softfloat_flag_denormal); } return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } } - if (bExp == 0x7FFF) - { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); + if (bExp == 0x7FFF) { + if (bSig << 1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); if (aSign && (Bit64u)(aExp | aSig)) goto invalid; - if (aSig && (aExp == 0)) - float_raise(status, float_flag_denormal); + if (aSig && ! aExp) + softfloat_raiseFlags(&status, softfloat_flag_denormal); if (aExp < 0x3FFF) { return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } - if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) goto invalid; + if (aExp == 0x3FFF && ! (aSig<<1)) goto invalid; return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } - if (aExp == 0) { - if (aSig == 0) { + if (! aExp) { + if (! aSig) { if ((bExp | bSig) == 0) goto invalid; - float_raise(status, float_flag_divbyzero); + softfloat_raiseFlags(&status, softfloat_flag_divbyzero); return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } if (aSign) goto invalid; - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; } if (aSign) goto invalid; - if (bExp == 0) { - if (bSig == 0) { + if (! bExp) { + if (! bSig) { if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0); return packFloatx80(bSign, 0, 0); } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) + if (aExp == 0x3FFF && ! (aSig<<1)) return packFloatx80(bSign, 0, 0); - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); int ExpDiff = aExp - 0x3FFF; aExp = 0; @@ -214,12 +215,15 @@ floatx80 fyl2x(floatx80 a, floatx80 b, float_status_t &status) /* using float128 for approximation */ /* ******************************** */ + float128_t b128 = softfloat_normRoundPackToF128(bSign, bExp-0x10, bSig, 0, &status); + Bit64u zSig0, zSig1; - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - float128 x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1); + shortShift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128_t x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1); x = poly_l2(x, status); - x = float128_add(x, int64_to_float128((Bit64s) ExpDiff), status); - return floatx80_mul(b, x, status); + x = f128_add(x, i32_to_f128(ExpDiff), &status); + x = f128_mul(x, b128, &status); + return f128_to_extF80(x, &status); } // ================================================= @@ -247,7 +251,7 @@ floatx80 fyl2x(floatx80 a, floatx80 b, float_status_t &status) // 1-u 3 5 7 2n+1 // -floatx80 fyl2xp1(floatx80 a, floatx80 b, float_status_t &status) +floatx80 fyl2xp1(floatx80 a, floatx80 b, softfloat_status_t &status) { Bit32s aExp, bExp; Bit64u aSig, bSig, zSig0, zSig1, zSig2; @@ -256,67 +260,70 @@ floatx80 fyl2xp1(floatx80 a, floatx80 b, float_status_t &status) // handle unsupported extended double-precision floating encodings if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { invalid: - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); return floatx80_default_nan; } - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); + + aSig = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); + bSig = extF80_fraction(b); + bExp = extF80_exp(b); + bSign = extF80_sign(b); int zSign = aSign ^ bSign; if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b, status); + if ((aSig<<1) != 0 || ((bExp == 0x7FFF) && (bSig<<1) != 0)) { + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); } if (aSign) goto invalid; else { - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(status, float_flag_denormal); + if (! bExp) { + if (! bSig) goto invalid; + softfloat_raiseFlags(&status, softfloat_flag_denormal); } return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } } if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) - return propagateFloatx80NaN(a, b, status); + if (bSig << 1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); - if (aExp == 0) { - if (aSig == 0) goto invalid; - float_raise(status, float_flag_denormal); + if (! aExp) { + if (! aSig) goto invalid; + softfloat_raiseFlags(&status, softfloat_flag_denormal); } return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + if (! aExp) { + if (! aSig) { + if (bSig && ! bExp) softfloat_raiseFlags(&status, softfloat_flag_denormal); return packFloatx80(zSign, 0, 0); } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; } - if (bExp == 0) { - if (bSig == 0) return packFloatx80(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + if (! bExp) { + if (! bSig) return packFloatx80(zSign, 0, 0); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (aSign && aExp >= 0x3FFF) return a; if (aExp >= 0x3FFC) // big argument { - return fyl2x(floatx80_add(a, floatx80_one, status), b, status); + return fyl2x(extF80_add(a, floatx80_one, &status), b, status); } // handle tiny argument @@ -325,29 +332,31 @@ floatx80 fyl2xp1(floatx80 a, floatx80 b, float_status_t &status) // first order approximation, return (a*b)/ln(2) Bit32s zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; - mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); + mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); if (0 < (Bit64s) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --zExp; } zExp = zExp + bExp - 0x3FFE; - mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); + mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); if (0 < (Bit64s) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --zExp; } - return - roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1, status); + return softfloat_roundPackToExtF80(aSign ^ bSign, zExp, zSig0, zSig1, 80, &status); } /* ******************************** */ /* using float128 for approximation */ /* ******************************** */ - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - float128 x = packFloat128(aSign, aExp, zSig0, zSig1); + float128_t b128 = softfloat_normRoundPackToF128(bSign, bExp-0x10, bSig, 0, &status); + + shortShift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128_t x = packFloat128(aSign, aExp, zSig0, zSig1); x = poly_l2p1(x, status); - return floatx80_mul(b, x, status); + x = f128_mul(x, b128, &status); + return f128_to_extF80(x, &status); } diff --git a/bochs/cpu/fpu/poly.cc b/bochs/cpu/fpu/poly.cc index 555af93619..71f0525522 100644 --- a/bochs/cpu/fpu/poly.cc +++ b/bochs/cpu/fpu/poly.cc @@ -23,10 +23,9 @@ these four paragraphs for those parts of this code that are retained. * Stanislav Shwartsman [sshwarts at sourceforge net] * ==========================================================================*/ -#define FLOAT128 - #include -#include "softfloat.h" + +#include "softfloat3e/include/softfloat.h" // 2 3 4 n // f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) @@ -39,13 +38,15 @@ these four paragraphs for those parts of this code that are retained. // f(x) ~ [ p(x) + x * q(x) ] // -float128 EvalPoly(float128 x, float128 *arr, int n, float_status_t &status) +float128_t EvalPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status) { - float128 r = arr[--n]; + float128_t r = arr[--n]; do { - r = float128_mul(r, x, status); - r = float128_add(r, arr[--n], status); + r = f128_mulAdd(r, x, arr[--n], 0, &status); +// r = f128_mul(r, x, &status); +// r = f128_add(r, arr[--n], &status); + } while (n > 0); return r; @@ -63,9 +64,9 @@ float128 EvalPoly(float128 x, float128 *arr, int n, float_status_t &status) // f(x) ~ [ p(x) + x * q(x) ] // -float128 EvenPoly(float128 x, float128 *arr, int n, float_status_t &status) +float128_t EvenPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status) { - return EvalPoly(float128_mul(x, x, status), arr, n, status); + return EvalPoly(f128_mul(x, x, &status), arr, n, status); } // 3 5 7 9 2n+1 @@ -83,7 +84,7 @@ float128 EvenPoly(float128 x, float128 *arr, int n, float_status_t &status) // f(x) ~ x * [ p(x) + x * q(x) ] // -float128 OddPoly(float128 x, float128 *arr, int n, float_status_t &status) +float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status) { - return float128_mul(x, EvenPoly(x, arr, n, status), status); + return f128_mul(x, EvenPoly(x, arr, n, status), &status); } diff --git a/bochs/cpu/fpu/softfloat-helpers.h b/bochs/cpu/fpu/softfloat-helpers.h new file mode 100644 index 0000000000..b69d9f9d7d --- /dev/null +++ b/bochs/cpu/fpu/softfloat-helpers.h @@ -0,0 +1,158 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#ifndef _SOFTFLOAT_HELPERS_H_ +#define _SOFTFLOAT_HELPERS_H_ + +#include + +#include "../softfloat3e/include/primitives.h" +#include "../softfloat3e/include/primitiveTypes.h" + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by +| `b' to obtain a 192-bit product. The product is broken into three 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and +| `z2Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void mul128By64To192(Bit64u a64, Bit64u a0, Bit64u b, Bit64u *z0Ptr, Bit64u *z1Ptr, Bit64u *z2Ptr) +{ + Bit64u zPtr[4]; + + softfloat_mul128To256M(a64, a0, 0, b, (uint64_t*) zPtr); + + assert(zPtr[indexWord(4, 3)] == 0); + + *z0Ptr = zPtr[indexWord(4, 2)]; + *z1Ptr = zPtr[indexWord(4, 1)]; + *z2Ptr = zPtr[indexWord(4, 0)]; +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' must be less than 64. The result is broken into two 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void shortShift128Left(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) +{ + *z1Ptr = a1<>((-count) & 63)); +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' must be less than 64. The result is broken into two 64-bit pieces +| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void shortShift128Right(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) +{ + Bit64u z0 = a0, z1 = a1; + int negCount = (-count) & 63; + + if (count != 0) { + z1 = (a0<>count); + z0 = a0>>count; + } + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Returns an approximation to the 64-bit integer quotient obtained by dividing +| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The +| divisor `b' must be at least 2^63. If q is the exact quotient truncated +| toward zero, the approximation returned lies between q and q + 2 inclusive. +| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit +| unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +#ifdef USE_estimateDiv128To64 +static Bit64u estimateDiv128To64(Bit64u a0, Bit64u a1, Bit64u b) +{ + uint128 term, rem; + Bit64u b0, b1; + Bit64u z; + if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF); + b0 = b>>32; + z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32; + term = softfloat_mul64To128(b, z); + rem = softfloat_sub128(a0, a1, term.v64, term.v0); + while (((int64_t) rem.v64) < 0) { + z -= UINT64_C(0x100000000); + b1 = b<<32; + rem = softfloat_add128(rem.v64, rem.v0, b0, b1); + } + rem.v64 = (rem.v64<<32) | (rem.v0>>32); + z |= (b0<<32 <= rem.v64) ? 0xFFFFFFFF : rem.v64 / b0; + return z; +} +#endif + +/*---------------------------------------------------------------------------- +| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the +| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is +| modulo 2^192, so any carry out is lost. The result is broken into three +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', +| `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void add192(Bit64u a0, Bit64u a1, Bit64u a2, Bit64u b0, Bit64u b1, Bit64u b2, Bit64u *z0Ptr, Bit64u *z1Ptr, Bit64u *z2Ptr) +{ + Bit64u z0, z1, z2; + unsigned carry0, carry1; + + z2 = a2 + b2; + carry1 = (z2 < a2); + z1 = a1 + b1; + carry0 = (z1 < a1); + z0 = a0 + b0; + z1 += carry1; + z0 += (z1 < carry1); + z0 += carry0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the +| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo +| 2^128, so any borrow out (carry out) is lost. The result is broken into two +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and +| `z1Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void sub128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr) +{ + *z1Ptr = a1 - b1; + *z0Ptr = a0 - b0 - (a1 < b1); +} + +#endif diff --git a/bochs/cpu/fpu/softfloat-macros.h b/bochs/cpu/fpu/softfloat-macros.h deleted file mode 100644 index cb867bf5d1..0000000000 --- a/bochs/cpu/fpu/softfloat-macros.h +++ /dev/null @@ -1,686 +0,0 @@ -/*============================================================================ -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOAT_MACROS_H_ -#define _SOFTFLOAT_MACROS_H_ - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 16, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16u shift16RightJamming(Bit16u a, int count) -{ - Bit16u z; - - if (count == 0) { - z = a; - } - else if (count < 16) { - z = (a>>count) | ((a<<((-count) & 15)) != 0); - } - else { - z = (a != 0); - } - - return z; -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 32, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32u shift32RightJamming(Bit32u a, int count) -{ - Bit32u z; - - if (count == 0) { - z = a; - } - else if (count < 32) { - z = (a>>count) | ((a<<((-count) & 31)) != 0); - } - else { - z = (a != 0); - } - - return z; -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 64, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u shift64RightJamming(Bit64u a, int count) -{ - Bit64u z; - - if (count == 0) { - z = a; - } - else if (count < 64) { - z = (a>>count) | ((a << ((-count) & 63)) != 0); - } - else { - z = (a != 0); - } - - return z; -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 -| _plus_ the number of bits given in `count'. The shifted result is at most -| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The -| bits shifted off form a second 64-bit result as follows: The _last_ bit -| shifted off is the most-significant bit of the extra result, and the other -| 63 bits of the extra result are all zero if and only if _all_but_the_last_ -| bits shifted off were all zero. This extra result is stored in the location -| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0' and `a1' are considered to form -| a fixed-point value with binary point between `a0' and `a1'. This fixed- -| point value is shifted right by the number of bits given in `count', and -| the integer part of the result is returned at the location pointed to by -| `z0Ptr'. The fractional part of the result may be slightly corrupted as -| described above, and is returned at the location pointed to by `z1Ptr'.) -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift64ExtraRightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z0, z1; - int negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } - else if (count < 64) { - z1 = (a0<>count; - } - else { - if (count == 64) { - z1 = a0 | (a1 != 0); - } - else { - z1 = ((a0 | a1) != 0); - } - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit -| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so -| any carry out is lost. The result is broken into two 64-bit pieces which -| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void add128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z1 = a1 + b1; - *z1Ptr = z1; - *z0Ptr = a0 + b0 + (z1 < a1); -} - -/*---------------------------------------------------------------------------- -| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the -| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo -| 2^128, so any borrow out (carry out) is lost. The result is broken into two -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and -| `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void - sub128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - *z1Ptr = a1 - b1; - *z0Ptr = a0 - b0 - (a1 < b1); -} - -/*---------------------------------------------------------------------------- -| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken -| into two 64-bit pieces which are stored at the locations pointed to by -| `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void mul64To128(Bit64u a, Bit64u b, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit32u aHigh, aLow, bHigh, bLow; - Bit64u z0, zMiddleA, zMiddleB, z1; - - aLow = (Bit32u) a; - aHigh = (Bit32u)(a>>32); - bLow = (Bit32u) b; - bHigh = (Bit32u)(b>>32); - z1 = ((Bit64u) aLow) * bLow; - zMiddleA = ((Bit64u) aLow) * bHigh; - zMiddleB = ((Bit64u) aHigh) * bLow; - z0 = ((Bit64u) aHigh) * bHigh; - zMiddleA += zMiddleB; - z0 += (((Bit64u) (zMiddleA < zMiddleB))<<32) + (zMiddleA>>32); - zMiddleA <<= 32; - z1 += zMiddleA; - z0 += (z1 < zMiddleA); - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the 64-bit integer quotient obtained by dividing -| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The -| divisor `b' must be at least 2^63. If q is the exact quotient truncated -| toward zero, the approximation returned lies between q and q + 2 inclusive. -| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit -| unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -#ifdef USE_estimateDiv128To64 -static Bit64u estimateDiv128To64(Bit64u a0, Bit64u a1, Bit64u b) -{ - Bit64u b0, b1; - Bit64u rem0, rem1, term0, term1; - Bit64u z; - - if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF); - b0 = b>>32; - z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32; - mul64To128(b, z, &term0, &term1); - sub128(a0, a1, term0, term1, &rem0, &rem1); - while (((Bit64s) rem0) < 0) { - z -= BX_CONST64(0x100000000); - b1 = b<<32; - add128(rem0, rem1, b0, b1, &rem0, &rem1); - } - rem0 = (rem0<<32) | (rem1>>32); - z |= (b0<<32 <= rem0) ? 0xFFFFFFFF : rem0 / b0; - return z; -} -#endif - -/*---------------------------------------------------------------------------- -| Returns an approximation to the square root of the 32-bit significand given -| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of -| `aExp' (the least significant bit) is 1, the integer returned approximates -| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' -| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either -| case, the approximation returned lies strictly within +/-2 of the exact -| value. -*----------------------------------------------------------------------------*/ - -#ifdef USE_estimateSqrt32 -static Bit32u estimateSqrt32(Bit16s aExp, Bit32u a) -{ - static const Bit16u sqrtOddAdjustments[] = { - 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 - }; - static const Bit16u sqrtEvenAdjustments[] = { - 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 - }; - Bit32u z; - - int index = (a>>27) & 15; - if (aExp & 1) { - z = 0x4000 + (a>>17) - sqrtOddAdjustments[index]; - z = ((a / z)<<14) + (z<<15); - a >>= 1; - } - else { - z = 0x8000 + (a>>17) - sqrtEvenAdjustments[index]; - z = a / z + z; - z = (0x20000 <= z) ? 0xFFFF8000 : (z<<15); - if (z <= a) return (Bit32u) (((Bit32s) a)>>1); - } - return ((Bit32u) ((((Bit64u) a)<<31) / z)) + (z>>1); -} -#endif - -static const int countLeadingZeros8[] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#ifdef FLOAT16 - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 16 is returned. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int countLeadingZeros16(Bit16u a) -{ - int shiftCount = 0; - if (a < 0x100) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZeros8[a>>8]; - return shiftCount; -} - -#endif - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 32 is returned. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int countLeadingZeros32(Bit32u a) -{ - int shiftCount = 0; - if (a < 0x10000) { - shiftCount += 16; - a <<= 16; - } - if (a < 0x1000000) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZeros8[a>>24]; - return shiftCount; -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int countLeadingZeros64(Bit64u a) -{ - int shiftCount = 0; - if (a < BX_CONST64(0x100000000)) { - shiftCount += 32; - } - else { - a >>= 32; - } - shiftCount += countLeadingZeros32((Bit32u)(a)); - return shiftCount; -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' can be arbitrarily large; in particular, if `count' is greater -| than 128, the result will be 0. The result is broken into two 64-bit pieces -| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift128Right(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z0, z1; - int negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } - else if (count < 64) { - z1 = (a0<>count); - z0 = a0>>count; - } - else { - z1 = (count < 128) ? (a0>>(count & 63)) : 0; - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. If any nonzero bits are shifted off, they -| are ``jammed'' into the least significant bit of the result by setting the -| least significant bit to 1. The value of `count' can be arbitrarily large; -| in particular, if `count' is greater than 128, the result will be either -| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or -| nonzero. The result is broken into two 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift128RightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z0, z1; - int negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } - else if (count < 64) { - z1 = (a0<>count) | ((a1<>count; - } - else { - if (count == 64) { - z1 = a0 | (a1 != 0); - } - else if (count < 128) { - z1 = (a0>>(count & 63)) | (((a0<>((-count) & 63)); -} - -/*---------------------------------------------------------------------------- -| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the -| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is -| modulo 2^192, so any carry out is lost. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void add192( - Bit64u a0, - Bit64u a1, - Bit64u a2, - Bit64u b0, - Bit64u b1, - Bit64u b2, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2; - unsigned carry0, carry1; - - z2 = a2 + b2; - carry1 = (z2 < a2); - z1 = a1 + b1; - carry0 = (z1 < a1); - z0 = a0 + b0; - z1 += carry1; - z0 += (z1 < carry1); - z0 += carry0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' -| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. -| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The -| result is broken into three 64-bit pieces which are stored at the locations -| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void sub192( - Bit64u a0, - Bit64u a1, - Bit64u a2, - Bit64u b0, - Bit64u b1, - Bit64u b2, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2; - unsigned borrow0, borrow1; - - z2 = a2 - b2; - borrow1 = (a2 < b2); - z1 = a1 - b1; - borrow0 = (a1 < b1); - z0 = a0 - b0; - z0 -= (z1 < borrow1); - z1 -= borrow1; - z0 -= borrow0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' -| is equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int eq128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) -{ - return (a0 == b0) && (a1 == b1); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int le128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) -{ - return (a0 < b0) || ((a0 == b0) && (a1 <= b1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, -| returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int lt128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) -{ - return (a0 < b0) || ((a0 == b0) && (a1 < b1)); -} - -#endif /* FLOATX80 */ - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by -| `b' to obtain a 192-bit product. The product is broken into three 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and -| `z2Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void mul128By64To192( - Bit64u a0, - Bit64u a1, - Bit64u b, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2, more1; - - mul64To128(a1, b, &z1, &z2); - mul64To128(a0, b, &z0, &more1); - add128(z0, more1, 0, z1, &z0, &z1); - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the -| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit -| product. The product is broken into four 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void mul128To256( - Bit64u a0, - Bit64u a1, - Bit64u b0, - Bit64u b1, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr, - Bit64u *z3Ptr -) -{ - Bit64u z0, z1, z2, z3; - Bit64u more1, more2; - - mul64To128(a1, b1, &z2, &z3); - mul64To128(a1, b0, &z1, &more2); - add128(z1, more2, 0, z2, &z1, &z2); - mul64To128(a0, b0, &z0, &more1); - add128(z0, more1, 0, z1, &z0, &z1); - mul64To128(a0, b1, &more1, &more2); - add128(more1, more2, 0, z2, &more1, &z2); - add128(z0, z1, 0, more1, &z0, &z1); - *z3Ptr = z3; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - - -/*---------------------------------------------------------------------------- -| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right -| by 64 _plus_ the number of bits given in `count'. The shifted result is -| at most 128 nonzero bits; these are broken into two 64-bit pieces which are -| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted -| off form a third 64-bit result as follows: The _last_ bit shifted off is -| the most-significant bit of the extra result, and the other 63 bits of the -| extra result are all zero if and only if _all_but_the_last_ bits shifted off -| were all zero. This extra result is stored in the location pointed to by -| `z2Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0', `a1', and `a2' are considered -| to form a fixed-point value with binary point between `a1' and `a2'. This -| fixed-point value is shifted right by the number of bits given in `count', -| and the integer part of the result is returned at the locations pointed to -| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly -| corrupted as described above, and is returned at the location pointed to by -| `z2Ptr'.) -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift128ExtraRightJamming( - Bit64u a0, - Bit64u a1, - Bit64u a2, - int count, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2; - int negCount = (-count) & 63; - - if (count == 0) { - z2 = a2; - z1 = a1; - z0 = a0; - } - else { - if (count < 64) { - z2 = a1<>count); - z0 = a0>>count; - } - else { - if (count == 64) { - z2 = a1; - z1 = a0; - } - else { - a2 |= a1; - if (count < 128) { - z2 = a0<>(count & 63); - } - else { - z2 = (count == 128) ? a0 : (a0 != 0); - z1 = 0; - } - } - z0 = 0; - } - z2 |= (a2 != 0); - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -#endif /* FLOAT128 */ - -#endif diff --git a/bochs/cpu/fpu/softfloat-round-pack.cc b/bochs/cpu/fpu/softfloat-round-pack.cc deleted file mode 100644 index 5f92127874..0000000000 --- a/bochs/cpu/fpu/softfloat-round-pack.cc +++ /dev/null @@ -1,427 +0,0 @@ -/*============================================================================ -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -#define FLOAT128 - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-round-pack.h" - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target -| if desired). -*----------------------------------------------------------------------------*/ -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize.h" - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal extended double-precision floating-point value -| represented by the denormalized significand `aSig'. The normalized exponent -| and significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloatx80Subnormal(Bit64u aSig, Bit32s *zExpPtr, Bit64u *zSigPtr) -{ - int shiftCount = countLeadingZeros64(aSig); - *zSigPtr = aSig< zSigExact) set_float_rounding_up(status); - } - return packFloatx80(zSign, zExp, zSig0); - } - } - if (roundBits) float_raise(status, float_flag_inexact); - zSigExact = zSig0; - zSig0 += roundIncrement; - if (zSig0 < roundIncrement) { - // Basically scale by shifting right and keep overflow - ++zExp; - zSig0 = BX_CONST64(0x8000000000000000); - zSigExact >>= 1; // must scale also, or else later tests will fail - } - roundIncrement = roundMask + 1; - if (roundNearestEven && (roundBits<<1 == roundIncrement)) - roundMask |= roundIncrement; - zSig0 &= ~roundMask; - if (zSig0 > zSigExact) set_float_rounding_up(status); - if (zSig0 == 0) zExp = 0; - return packFloatx80(zSign, zExp, zSig0); - precision80: - increment = ((Bit64s) zSig1 < 0); - if (! roundNearestEven) { - if (roundingMode == float_round_to_zero) increment = 0; - else { - if (zSign) { - increment = (roundingMode == float_round_down) && zSig1; - } - else { - increment = (roundingMode == float_round_up) && zSig1; - } - } - } - if (0x7FFD <= (Bit32u) (zExp - 1)) { - if ((0x7FFE < zExp) - || ((zExp == 0x7FFE) - && (zSig0 == BX_CONST64(0xFFFFFFFFFFFFFFFF)) - && increment)) - { - roundMask = 0; - overflow: - float_raise(status, float_flag_overflow | float_flag_inexact); - if ((roundingMode == float_round_to_zero) - || (zSign && (roundingMode == float_round_up)) - || (! zSign && (roundingMode == float_round_down))) - { - return packFloatx80(zSign, 0x7FFE, ~roundMask); - } - set_float_rounding_up(status); - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (zExp <= 0) { - int isTiny = (zExp < 0) || (! increment) - || (zSig0 < BX_CONST64(0xFFFFFFFFFFFFFFFF)); - shift64ExtraRightJamming(zSig0, zSig1, 1 - zExp, &zSig0, &zSig1); - zExp = 0; - if (isTiny) { - if (zSig1 || (zSig0 && !float_exception_masked(status, float_flag_underflow))) - float_raise(status, float_flag_underflow); - } - if (zSig1) float_raise(status, float_flag_inexact); - if (roundNearestEven) increment = ((Bit64s) zSig1 < 0); - else { - if (zSign) { - increment = (roundingMode == float_round_down) && zSig1; - } else { - increment = (roundingMode == float_round_up) && zSig1; - } - } - if (increment) { - zSigExact = zSig0++; - zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven); - if (zSig0 > zSigExact) set_float_rounding_up(status); - if ((Bit64s) zSig0 < 0) zExp = 1; - } - return packFloatx80(zSign, zExp, zSig0); - } - } - if (zSig1) float_raise(status, float_flag_inexact); - if (increment) { - zSigExact = zSig0++; - if (zSig0 == 0) { - zExp++; - zSig0 = BX_CONST64(0x8000000000000000); - zSigExact >>= 1; // must scale also, or else later tests will fail - } - else { - zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven); - } - if (zSig0 > zSigExact) set_float_rounding_up(status); - } - else { - if (zSig0 == 0) zExp = 0; - } - return packFloatx80(zSign, zExp, zSig0); -} - -floatx80 roundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, float_status_t &status) -{ - float_status_t round_status = status; - floatx80 result = SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status); - - // bias unmasked undeflow - if (status.float_exception_flags & ~status.float_exception_masks & float_flag_underflow) { - float_raise(round_status, float_flag_underflow); - return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp + 0x6000, zSig0, zSig1, status = round_status); - } - - // bias unmasked overflow - if (status.float_exception_flags & ~status.float_exception_masks & float_flag_overflow) { - float_raise(round_status, float_flag_overflow); - return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp - 0x6000, zSig0, zSig1, status = round_status); - } - - return result; -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent -| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1', -| and returns the proper extended double-precision floating-point value -| corresponding to the abstract input. This routine is just like -| `roundAndPackFloatx80' except that the input significand does not have to be -| normalized. -*----------------------------------------------------------------------------*/ - -floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, float_status_t &status) -{ - if (zSig0 == 0) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - int shiftCount = countLeadingZeros64(zSig0); - shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); - zExp -= shiftCount; - return - roundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status); -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -void normalizeFloat128Subnormal( - Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr) -{ - int shiftCount; - - if (aSig0 == 0) { - shiftCount = countLeadingZeros64(aSig1) - 15; - if (shiftCount < 0) { - *zSig0Ptr = aSig1 >>(-shiftCount); - *zSig1Ptr = aSig1 << (shiftCount & 63); - } - else { - *zSig0Ptr = aSig1 << shiftCount; - *zSig1Ptr = 0; - } - *zExpPtr = - shiftCount - 63; - } - else { - shiftCount = countLeadingZeros64(aSig0) - 15; - shortShift128Left(aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr); - *zExpPtr = 1 - shiftCount; - } -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0', `zSig1', -| and `zSig2', and returns the proper quadruple-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| simply rounded and packed into the quadruple-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal quadruple- -| precision floating-point number. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. In the -| usual case that the input significand is normalized, `zExp' must be 1 less -| than the ``true'' floating-point exponent. The handling of underflow and -| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 roundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, float_status_t &status) -{ - int increment = ((Bit64s) zSig2 < 0); - if (0x7FFD <= (Bit32u) zExp) { - if ((0x7FFD < zExp) - || ((zExp == 0x7FFD) - && eq128(BX_CONST64(0x0001FFFFFFFFFFFF), - BX_CONST64(0xFFFFFFFFFFFFFFFF), zSig0, zSig1) - && increment)) - { - float_raise(status, float_flag_overflow | float_flag_inexact); - return packFloat128(zSign, 0x7FFF, 0, 0); - } - if (zExp < 0) { - int isTiny = (zExp < -1) - || ! increment - || lt128(zSig0, zSig1, - BX_CONST64(0x0001FFFFFFFFFFFF), - BX_CONST64(0xFFFFFFFFFFFFFFFF)); - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, -zExp, &zSig0, &zSig1, &zSig2); - zExp = 0; - if (isTiny && zSig2) float_raise(status, float_flag_underflow); - increment = ((Bit64s) zSig2 < 0); - } - } - if (zSig2) float_raise(status, float_flag_inexact); - if (increment) { - add128(zSig0, zSig1, 0, 1, &zSig0, &zSig1); - zSig1 &= ~((zSig2 + zSig2 == 0) & 1); - } - else { - if ((zSig0 | zSig1) == 0) zExp = 0; - } - return packFloat128(zSign, zExp, zSig0, zSig1); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand formed by the concatenation of `zSig0' and `zSig1', and -| returns the proper quadruple-precision floating-point value corresponding -| to the abstract input. This routine is just like `roundAndPackFloat128' -| except that the input significand has fewer bits and does not have to be -| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- -| point exponent. -*----------------------------------------------------------------------------*/ - -float128 normalizeRoundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, float_status_t &status) -{ - Bit64u zSig2; - - if (zSig0 == 0) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - int shiftCount = countLeadingZeros64(zSig0) - 15; - if (0 <= shiftCount) { - zSig2 = 0; - shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); - } - else { - shift128ExtraRightJamming( - zSig0, zSig1, 0, -shiftCount, &zSig0, &zSig1, &zSig2); - } - zExp -= shiftCount; - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); -} - -#endif diff --git a/bochs/cpu/fpu/softfloat-round-pack.h b/bochs/cpu/fpu/softfloat-round-pack.h deleted file mode 100644 index f900504a32..0000000000 --- a/bochs/cpu/fpu/softfloat-round-pack.h +++ /dev/null @@ -1,146 +0,0 @@ -/*============================================================================ -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOAT_ROUND_PACK_H_ -#define _SOFTFLOAT_ROUND_PACK_H_ - -#include "softfloat.h" - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal extended double-precision floating-point value -| represented by the denormalized significand `aSig'. The normalized exponent -| and significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloatx80Subnormal(Bit64u aSig, Bit32s *zExpPtr, Bit64u *zSigPtr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0' and `zSig1', -| and returns the proper extended double-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| rounded and packed into the extended double-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal extended -| double-precision floating-point number. -| If `roundingPrecision' is 32 or 64, the result is rounded to the same -| number of bits as single or double precision, respectively. Otherwise, the -| result is rounded to the full precision of the extended double-precision -| format. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. The -| handling of underflow and overflow follows the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 roundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, float_status_t &status); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent -| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1', -| and returns the proper extended double-precision floating-point value -| corresponding to the abstract input. This routine is just like -| `roundAndPackFloatx80' except that the input significand does not have to be -| normalized. -*----------------------------------------------------------------------------*/ - -floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, float_status_t &status); - -#endif // FLOATX80 - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -void normalizeFloat128Subnormal( - Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0', `zSig1', -| and `zSig2', and returns the proper quadruple-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| simply rounded and packed into the quadruple-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal quadruple- -| precision floating-point number. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. In the -| usual case that the input significand is normalized, `zExp' must be 1 less -| than the ``true'' floating-point exponent. The handling of underflow and -| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 roundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, float_status_t &status); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand formed by the concatenation of `zSig0' and `zSig1', and -| returns the proper quadruple-precision floating-point value corresponding -| to the abstract input. This routine is just like `roundAndPackFloat128' -| except that the input significand has fewer bits and does not have to be -| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- -| point exponent. -*----------------------------------------------------------------------------*/ - -float128 normalizeRoundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, float_status_t &status); - -#endif // FLOAT128 - -#endif diff --git a/bochs/cpu/fpu/softfloat-specialize.cc b/bochs/cpu/fpu/softfloat-specialize.cc deleted file mode 100644 index 806e9803bc..0000000000 --- a/bochs/cpu/fpu/softfloat-specialize.cc +++ /dev/null @@ -1,121 +0,0 @@ -/*============================================================================ -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -#define FLOAT128 - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-specialize.h" - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status_t &status) -{ - int aIsNaN = floatx80_is_nan(a); - int aIsSignalingNaN = floatx80_is_signaling_nan(a); - int bIsNaN = floatx80_is_nan(b); - int bIsSignalingNaN = floatx80_is_signaling_nan(b); - a.fraction |= BX_CONST64(0xC000000000000000); - b.fraction |= BX_CONST64(0xC000000000000000); - if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); - if (aIsSignalingNaN) { - if (bIsSignalingNaN) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if (aIsNaN) { - if (bIsSignalingNaN | ! bIsNaN) return a; - returnLargerSignificand: - if (a.fraction < b.fraction) return b; - if (b.fraction < a.fraction) return a; - return (a.exp < b.exp) ? a : b; - } - else { - return b; - } -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ -const floatx80 floatx80_default_nan = - packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - -#endif /* FLOATX80 */ - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float128 propagateFloat128NaN(float128 a, float128 b, float_status_t &status) -{ - int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - aIsNaN = float128_is_nan(a); - aIsSignalingNaN = float128_is_signaling_nan(a); - bIsNaN = float128_is_nan(b); - bIsSignalingNaN = float128_is_signaling_nan(b); - a.hi |= BX_CONST64(0x0000800000000000); - b.hi |= BX_CONST64(0x0000800000000000); - if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); - if (aIsSignalingNaN) { - if (bIsSignalingNaN) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if (aIsNaN) { - if (bIsSignalingNaN | !bIsNaN) return a; - returnLargerSignificand: - if (lt128(a.hi<<1, a.lo, b.hi<<1, b.lo)) return b; - if (lt128(b.hi<<1, b.lo, a.hi<<1, a.lo)) return a; - return (a.hi < b.hi) ? a : b; - } - else { - return b; - } -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. -*----------------------------------------------------------------------------*/ -const float128 float128_default_nan = - packFloat128(float128_default_nan_hi, float128_default_nan_lo); - -#endif /* FLOAT128 */ diff --git a/bochs/cpu/fpu/softfloat-specialize.h b/bochs/cpu/fpu/softfloat-specialize.h index e25a69c720..c637e99b40 100644 --- a/bochs/cpu/fpu/softfloat-specialize.h +++ b/bochs/cpu/fpu/softfloat-specialize.h @@ -30,31 +30,20 @@ these four paragraphs for those parts of this code that are retained. #ifndef _SOFTFLOAT_SPECIALIZE_H_ #define _SOFTFLOAT_SPECIALIZE_H_ -#include "softfloat.h" +#include "../softfloat3e/include/softfloat_types.h" /*============================================================================ * Adapted for Bochs (x86 achitecture simulator) by * Stanislav Shwartsman [sshwarts at sourceforge net] * ==========================================================================*/ -#define int16_indefinite ((Bit16s)0x8000) -#define int32_indefinite ((Bit32s)0x80000000) -#define int64_indefinite BX_CONST64(0x8000000000000000) +const Bit16s int16_indefinite = (Bit16s) 0x8000; +const Bit32s int32_indefinite = (Bit32s) 0x80000000; +const Bit64s int64_indefinite = (Bit64s) BX_CONST64(0x8000000000000000); -#define uint16_indefinite (0xffff) -#define uint32_indefinite (0xffffffff) -#define uint64_indefinite BX_CONST64(0xffffffffffffffff) - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ - -typedef struct { - int sign; - Bit64u hi, lo; -} commonNaNT; - -#ifdef FLOAT16 +const Bit16u uint16_indefinite = 0xffff; +const Bit32u uint32_indefinite = 0xffffffff; +const Bit64u uint64_indefinite = BX_CONST64(0xffffffffffffffff); /*---------------------------------------------------------------------------- | Commonly used half-precision floating point constants @@ -69,39 +58,8 @@ const float16 float16_positive_zero = 0x0000; *----------------------------------------------------------------------------*/ const float16 float16_default_nan = 0xFE00; -#define float16_fraction extractFloat16Frac -#define float16_exp extractFloat16Exp -#define float16_sign extractFloat16Sign - #define FLOAT16_EXP_BIAS 0xF -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16u extractFloat16Frac(float16 a) -{ - return a & 0x3FF; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16s extractFloat16Exp(float16 a) -{ - return (a>>10) & 0x1F; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat16Sign(float16 a) -{ - return a>>15; -} - /*---------------------------------------------------------------------------- | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a | single-precision floating-point value, returning the result. After being @@ -118,54 +76,6 @@ BX_CPP_INLINE float16 packFloat16(int zSign, int zExp, Bit16u zSig) return (((Bit16u) zSign)<<15) + (((Bit16u) zExp)<<10) + zSig; } -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float16_is_nan(float16 a) -{ - return (0xF800 < (Bit16u) (a<<1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float16_is_signaling_nan(float16 a) -{ - return (((a>>9) & 0x3F) == 0x3E) && (a & 0x1FF); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the half-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float16ToCommonNaN(float16 a, float_status_t &status) -{ - commonNaNT z; - if (float16_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = a>>15; - z.lo = 0; - z.hi = ((Bit64u) a)<<54; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the half- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float16 commonNaNToFloat16(commonNaNT a) -{ - return (((Bit16u) a.sign)<<15) | 0x7E00 | (Bit16u)(a.hi>>54); -} - -#endif - /*---------------------------------------------------------------------------- | Commonly used single-precision floating point constants *----------------------------------------------------------------------------*/ @@ -183,39 +93,8 @@ const float32 float32_min_float = 0xff7fffff; *----------------------------------------------------------------------------*/ const float32 float32_default_nan = 0xffc00000; -#define float32_fraction extractFloat32Frac -#define float32_exp extractFloat32Exp -#define float32_sign extractFloat32Sign - #define FLOAT32_EXP_BIAS 0x7F -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32u extractFloat32Frac(float32 a) -{ - return a & 0x007FFFFF; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16s extractFloat32Exp(float32 a) -{ - return (a>>23) & 0xFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat32Sign(float32 a) -{ - return a>>31; -} - /*---------------------------------------------------------------------------- | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a | single-precision floating-point value, returning the result. After being @@ -232,52 +111,6 @@ BX_CPP_INLINE float32 packFloat32(int zSign, Bit16s zExp, Bit32u zSig) return (((Bit32u) zSign)<<31) + (((Bit32u) zExp)<<23) + zSig; } -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float32_is_nan(float32 a) -{ - return (0xFF000000 < (Bit32u) (a<<1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float32_is_signaling_nan(float32 a) -{ - return (((a>>22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float32ToCommonNaN(float32 a, float_status_t &status) -{ - commonNaNT z; - if (float32_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = a>>31; - z.lo = 0; - z.hi = ((Bit64u) a)<<41; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float32 commonNaNToFloat32(commonNaNT a) -{ - return (((Bit32u) a.sign)<<31) | 0x7FC00000 | (Bit32u)(a.hi>>41); -} - /*---------------------------------------------------------------------------- | Commonly used single-precision floating point constants *----------------------------------------------------------------------------*/ @@ -295,39 +128,8 @@ const float64 float64_min_float = BX_CONST64(0xffefffffffffffff); *----------------------------------------------------------------------------*/ const float64 float64_default_nan = BX_CONST64(0xFFF8000000000000); -#define float64_fraction extractFloat64Frac -#define float64_exp extractFloat64Exp -#define float64_sign extractFloat64Sign - #define FLOAT64_EXP_BIAS 0x3FF -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloat64Frac(float64 a) -{ - return a & BX_CONST64(0x000FFFFFFFFFFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16s extractFloat64Exp(float64 a) -{ - return (Bit16s)(a>>52) & 0x7FF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat64Sign(float64 a) -{ - return (int)(a>>63); -} - /*---------------------------------------------------------------------------- | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a | double-precision floating-point value, returning the result. After being @@ -344,54 +146,6 @@ BX_CPP_INLINE float64 packFloat64(int zSign, Bit16s zExp, Bit64u zSig) return (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<52) + zSig; } -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float64_is_nan(float64 a) -{ - return (BX_CONST64(0xFFE0000000000000) < (Bit64u) (a<<1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float64_is_signaling_nan(float64 a) -{ - return (((a>>51) & 0xFFF) == 0xFFE) && (a & BX_CONST64(0x0007FFFFFFFFFFFF)); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float64ToCommonNaN(float64 a, float_status_t &status) -{ - commonNaNT z; - if (float64_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = (int)(a>>63); - z.lo = 0; - z.hi = a<<12; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float64 commonNaNToFloat64(commonNaNT a) -{ - return (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FF8000000000000) | (a.hi>>12); -} - -#ifdef FLOATX80 - /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. The | `high' and `low' values hold the most- and least-significant bits, @@ -400,42 +154,8 @@ BX_CPP_INLINE float64 commonNaNToFloat64(commonNaNT a) #define floatx80_default_nan_exp 0xFFFF #define floatx80_default_nan_fraction BX_CONST64(0xC000000000000000) -#define floatx80_fraction extractFloatx80Frac -#define floatx80_exp extractFloatx80Exp -#define floatx80_sign extractFloatx80Sign - #define FLOATX80_EXP_BIAS 0x3FFF -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloatx80Frac(floatx80 a) -{ - return a.fraction; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32s extractFloatx80Exp(floatx80 a) -{ - return a.exp & 0x7FFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloatx80Sign(floatx80 a) -{ - return a.exp>>15; -} - /*---------------------------------------------------------------------------- | Packs the sign `zSign', exponent `zExp', and significand `zSig' into an | extended double-precision floating-point value, returning the result. @@ -444,155 +164,19 @@ BX_CPP_INLINE int extractFloatx80Sign(floatx80 a) BX_CPP_INLINE floatx80 packFloatx80(int zSign, Bit32s zExp, Bit64u zSig) { floatx80 z; - z.fraction = zSig; - z.exp = (zSign << 15) + zExp; + z.signif = zSig; + z.signExp = (zSign << 15) + zExp; return z; } -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int floatx80_is_nan(floatx80 a) -{ - return ((a.exp & 0x7FFF) == 0x7FFF) && (Bit64s) (a.fraction<<1); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int floatx80_is_signaling_nan(floatx80 a) -{ - Bit64u aLow = a.fraction & ~BX_CONST64(0x4000000000000000); - return ((a.exp & 0x7FFF) == 0x7FFF) && - ((Bit64u) (aLow<<1)) && (a.fraction == aLow); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is an -| unsupported; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int floatx80_is_unsupported(floatx80 a) -{ - return ((a.exp & 0x7FFF) && !(a.fraction & BX_CONST64(0x8000000000000000))); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT floatx80ToCommonNaN(floatx80 a, float_status_t &status) -{ - commonNaNT z; - if (floatx80_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = a.exp >> 15; - z.lo = 0; - z.hi = a.fraction << 1; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE floatx80 commonNaNToFloatx80(commonNaNT a) -{ - floatx80 z; - z.fraction = BX_CONST64(0xC000000000000000) | (a.hi>>1); - z.exp = (((Bit16u) a.sign)<<15) | 0x7FFF; - return z; -} - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status_t &status); - -/*---------------------------------------------------------------------------- -| Takes extended double-precision floating-point NaN `a' and returns the -| appropriate NaN result. If `a' is a signaling NaN, the invalid exception -| is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE floatx80 propagateFloatx80NaN(floatx80 a, float_status_t &status) -{ - if (floatx80_is_signaling_nan(a)) - float_raise(status, float_flag_invalid); - - a.fraction |= BX_CONST64(0xC000000000000000); - - return a; -} - /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ -extern const floatx80 floatx80_default_nan; - -#endif /* FLOATX80 */ +static const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); #ifdef FLOAT128 -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#define float128_default_nan_hi BX_CONST64(0xFFFF800000000000) -#define float128_default_nan_lo BX_CONST64(0x0000000000000000) - -#define float128_exp extractFloat128Exp - -/*---------------------------------------------------------------------------- -| Returns the least-significant 64 fraction bits of the quadruple-precision -| floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloat128Frac1(float128 a) -{ - return a.lo; -} - -/*---------------------------------------------------------------------------- -| Returns the most-significant 48 fraction bits of the quadruple-precision -| floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloat128Frac0(float128 a) -{ - return a.hi & BX_CONST64(0x0000FFFFFFFFFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the quadruple-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32s extractFloat128Exp(float128 a) -{ - return ((Bit32s)(a.hi>>48)) & 0x7FFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat128Sign(float128 a) -{ - return (int)(a.hi >> 63); -} - /*---------------------------------------------------------------------------- | Packs the sign `zSign', the exponent `zExp', and the significand formed | by the concatenation of `zSig0' and `zSig1' into a quadruple-precision @@ -606,11 +190,11 @@ BX_CPP_INLINE int extractFloat128Sign(float128 a) | significand. *----------------------------------------------------------------------------*/ -BX_CPP_INLINE float128 packFloat128(int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1) +BX_CPP_INLINE float128_t packFloat128(int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1) { - float128 z; - z.lo = zSig1; - z.hi = (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<48) + zSig0; + float128_t z; + z.v0 = zSig1; + z.v64 = (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<48) + zSig0; return z; } @@ -619,11 +203,11 @@ BX_CPP_INLINE float128 packFloat128(int zSign, Bit32s zExp, Bit64u zSig0, Bit64u | floating-point value, returning the result. *----------------------------------------------------------------------------*/ -BX_CPP_INLINE float128 packFloat128(Bit64u zHi, Bit64u zLo) +BX_CPP_INLINE float128_t packFloat128(Bit64u zHi, Bit64u zLo) { - float128 z; - z.lo = zLo; - z.hi = zHi; + float128_t z; + z.v0 = zLo; + z.v64 = zHi; return z; } @@ -633,69 +217,6 @@ BX_CPP_INLINE float128 packFloat128(Bit64u zHi, Bit64u zLo) #define PACK_FLOAT_128(hi,lo) packFloat128(BX_CONST64(hi),BX_CONST64(lo)) #endif -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float128_is_nan(float128 a) -{ - return (BX_CONST64(0xFFFE000000000000) <= (Bit64u) (a.hi<<1)) - && (a.lo || (a.hi & BX_CONST64(0x0000FFFFFFFFFFFF))); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float128_is_signaling_nan(float128 a) -{ - return (((a.hi>>47) & 0xFFFF) == 0xFFFE) - && (a.lo || (a.hi & BX_CONST64(0x00007FFFFFFFFFFF))); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float128ToCommonNaN(float128 a, float_status_t &status) -{ - commonNaNT z; - if (float128_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = (int)(a.hi>>63); - shortShift128Left(a.hi, a.lo, 16, &z.hi, &z.lo); - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float128 commonNaNToFloat128(commonNaNT a) -{ - float128 z; - shift128Right(a.hi, a.lo, 16, &z.hi, &z.lo); - z.hi |= (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FFF800000000000); - return z; -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float128 propagateFloat128NaN(float128 a, float128 b, float_status_t &status); - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float128 float128_default_nan; - #endif /* FLOAT128 */ #endif diff --git a/bochs/cpu/fpu/softfloat.cc b/bochs/cpu/fpu/softfloat.cc deleted file mode 100644 index 9dfac6ce3a..0000000000 --- a/bochs/cpu/fpu/softfloat.cc +++ /dev/null @@ -1,856 +0,0 @@ -/*============================================================================ -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -#define FLOAT128 - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-round-pack.h" - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target -| if desired). -*----------------------------------------------------------------------------*/ -#define USE_estimateDiv128To64 -#define USE_estimateSqrt32 -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize.h" - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 int32_to_floatx80(Bit32s a) -{ - if (a == 0) return packFloatx80(0, 0, 0); - int zSign = (a < 0); - Bit32u absA = zSign ? -a : a; - int shiftCount = countLeadingZeros32(absA) + 32; - Bit64u zSig = absA; - return packFloatx80(zSign, 0x403E - shiftCount, zSig< /* generated by configure script from config.h.in */ - -#ifndef _SOFTFLOAT_H_ -#define _SOFTFLOAT_H_ - -#define FLOAT16 -#define FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -#ifdef FLOAT16 -typedef Bit16u float16, bfloat16; -#endif -typedef Bit32u float32; -typedef Bit64u float64; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point class. -*----------------------------------------------------------------------------*/ -typedef enum { - float_zero, - float_SNaN, - float_QNaN, - float_negative_inf, - float_positive_inf, - float_denormal, - float_normalized -} float_class_t; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point NaN operands handling mode. -*----------------------------------------------------------------------------*/ -enum float_nan_handling_mode_t { - float_larger_significand_nan = 0, // this mode used by x87 FPU - float_first_operand_nan = 1 // this mode used by SSE -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -enum float_round_t { - float_round_nearest_even = 0, - float_round_down = 1, - float_round_up = 2, - float_round_to_zero = 3 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -enum float_exception_flag_t { - float_flag_invalid = 0x01, - float_flag_denormal = 0x02, - float_flag_divbyzero = 0x04, - float_flag_overflow = 0x08, - float_flag_underflow = 0x10, - float_flag_inexact = 0x20 -}; - -const unsigned float_all_exceptions_mask = 0x3f; - -#ifdef FLOATX80 -#define RAISE_SW_C1 0x0200 -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point ordering relations -*----------------------------------------------------------------------------*/ -enum { - float_relation_less = -1, - float_relation_equal = 0, - float_relation_greater = 1, - float_relation_unordered = 2 -}; - -#include "../softfloat3e/include/softfloat.h" - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point status structure. -*----------------------------------------------------------------------------*/ -#if 0 -struct float_status_t -{ -#ifdef FLOATX80 - int float_rounding_precision; /* floatx80 only */ -#endif - int float_rounding_mode; - int float_exception_flags; - int float_exception_masks; - int float_suppress_exception; - int float_nan_handling_mode; /* flag register */ - int flush_underflow_to_zero; /* flag register */ - int denormals_are_zeros; /* flag register */ -}; -#endif - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void float_raise(float_status_t &status, int flags) -{ - status.float_exception_flags |= flags; -} - -/*---------------------------------------------------------------------------- -| Returns raised IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_exception_flags(const float_status_t &status) -{ - return status.float_exception_flags & ~status.float_suppress_exception; -} - -/*---------------------------------------------------------------------------- -| Routine to check if any or all of the software IEC/IEEE floating-point -| exceptions are masked. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float_exception_masked(const float_status_t &status, int flag) -{ - return status.float_exception_masks & flag; -} - -/*---------------------------------------------------------------------------- -| Returns current floating point rounding mode specified by status word. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_float_rounding_mode(const float_status_t &status) -{ - return status.float_rounding_mode; -} - -/*---------------------------------------------------------------------------- -| Returns current floating point precision (floatx80 only). -*----------------------------------------------------------------------------*/ - -#ifdef FLOATX80 -BX_CPP_INLINE int get_float_rounding_precision(const float_status_t &status) -{ - return status.float_rounding_precision; -} -#endif - -/*---------------------------------------------------------------------------- -| Returns current floating point NaN operands handling mode specified -| by status word. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_float_nan_handling_mode(const float_status_t &status) -{ - return status.float_nan_handling_mode; -} - -/*---------------------------------------------------------------------------- -| Raise floating point precision lost up flag (floatx80 only). -*----------------------------------------------------------------------------*/ - -#ifdef FLOATX80 -BX_CPP_INLINE void set_float_rounding_up(float_status_t &status) -{ - status.float_exception_flags |= RAISE_SW_C1; -} -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ - -int float32_is_signaling_nan(float32); -int float32_is_nan(float32); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ - -int float64_is_signaling_nan(float64); -int float64_is_nan(float64); - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -floatx80 int32_to_floatx80(Bit32s); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_add(floatx80, floatx80, float_status_t &status); -floatx80 floatx80_sub(floatx80, floatx80, float_status_t &status); -floatx80 floatx80_mul(floatx80, floatx80, float_status_t &status); - -float_class_t floatx80_class(floatx80); -int floatx80_is_signaling_nan(floatx80); -int floatx80_is_nan(floatx80); - -#endif /* FLOATX80 */ - -#ifdef FLOAT128 -/* -#ifdef BX_BIG_ENDIAN -struct float128 { - Bit64u hi, lo; -}; -#else -struct float128 { - Bit64u lo, hi; -}; -#endif -*/ -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -float128 floatx80_to_float128(floatx80 a, float_status_t &status); -floatx80 float128_to_floatx80(float128 a, float_status_t &status); - -float128 int64_to_float128(Bit64s a); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_mul(floatx80 a, float128 b, float_status_t &status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_add(float128 a, float128 b, float_status_t &status); -float128 float128_sub(float128 a, float128 b, float_status_t &status); -float128 float128_mul(float128 a, float128 b, float_status_t &status); -float128 float128_div(float128 a, float128 b, float_status_t &status); - -#endif /* FLOAT128 */ - -#endif diff --git a/bochs/cpu/fpu/softfloat16.h b/bochs/cpu/fpu/softfloat16.h deleted file mode 100644 index ccbcae5f21..0000000000 --- a/bochs/cpu/fpu/softfloat16.h +++ /dev/null @@ -1,45 +0,0 @@ -/*============================================================================ -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOAT_F16_HELPERS_H_ -#define _SOFTFLOAT_F16_HELPERS_H_ - -extern float32 convert_ne_fp16_to_fp32(float16 op); - -BX_CPP_INLINE float16 f16_scalef(float16 a, float16 b, float_status_t *status) -{ - return f32_to_f16(f32_scalef(convert_ne_fp16_to_fp32(a), convert_ne_fp16_to_fp32(b), status), status); -} - -#endif diff --git a/bochs/cpu/fpu/softfloatx80.cc b/bochs/cpu/fpu/softfloatx80.cc deleted file mode 100644 index 207036d61b..0000000000 --- a/bochs/cpu/fpu/softfloatx80.cc +++ /dev/null @@ -1,154 +0,0 @@ -/*============================================================================ -This source file is an extension to the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) -floating point emulation. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Written for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloatx80.h" -#include "softfloat-round-pack.h" -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Separate the source extended double-precision floating point value `a' -| into its exponent and significand, store the significant back to the -| 'a' and return the exponent. The operation performed is a superset of -| the IEC/IEEE recommended logb(x) function. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_extract(floatx80 &a, float_status_t &status) -{ - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); - a = floatx80_default_nan; - return a; - } - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - { - a = propagateFloatx80NaN(a, status); - return a; - } - return packFloatx80(0, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) - { - if (aSig == 0) { - float_raise(status, float_flag_divbyzero); - a = packFloatx80(aSign, 0, 0); - return packFloatx80(1, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - - a.exp = (aSign << 15) + 0x3FFF; - a.fraction = aSig; - return int32_to_floatx80(aExp - 0x3FFF); -} - -/*---------------------------------------------------------------------------- -| Scales extended double-precision floating-point value in operand `a' by -| value `b'. The function truncates the value in the second operand 'b' to -| an integral value and adds that value to the exponent of the operand 'a'. -| The operation performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status_t &status) -{ - Bit32s aExp, bExp; - Bit64u aSig, bSig; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b, status); - } - if ((bExp == 0x7FFF) && bSign) { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if ((aExp | aSig) == 0) { - if (! bSign) { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - return a; - } - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - if (bSign) return packFloatx80(aSign, 0, 0); - return packFloatx80(aSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - if (aSig == 0) return a; - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - if (bExp < 0x3FFF) - return normalizeRoundAndPackFloatx80(80, aSign, aExp, aSig, 0, status); - } - if (bExp == 0) { - if (bSig == 0) return a; - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - - if (bExp > 0x400E) { - /* generate appropriate overflow/underflow */ - return roundAndPackFloatx80(80, aSign, - bSign ? -0x3FFF : 0x7FFF, aSig, 0, status); - } - - if (bExp < 0x3FFF) return a; - - int shiftCount = 0x403E - bExp; - bSig >>= shiftCount; - Bit32s scale = (Bit32s) bSig; - if (bSign) scale = -scale; /* -32768..32767 */ - return - roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0, status); -} diff --git a/bochs/cpu/fpu/softfloatx80.h b/bochs/cpu/fpu/softfloatx80.h deleted file mode 100644 index 7468c9a017..0000000000 --- a/bochs/cpu/fpu/softfloatx80.h +++ /dev/null @@ -1,85 +0,0 @@ -/*============================================================================ -This source file is an extension to the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) -floating point emulation. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Written for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOATX80_EXTENSIONS_H_ -#define _SOFTFLOATX80_EXTENSIONS_H_ - -#include "softfloat.h" -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_extract(floatx80 &a, float_status_t &status); -floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status_t &status); -int floatx80_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, float_status_t &status); -int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, float_status_t &status); -floatx80 f2xm1(floatx80 a, float_status_t &status); -floatx80 fyl2x(floatx80 a, floatx80 b, float_status_t &status); -floatx80 fyl2xp1(floatx80 a, floatx80 b, float_status_t &status); -floatx80 fpatan(floatx80 a, floatx80 b, float_status_t &status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision trigonometric functions. -*----------------------------------------------------------------------------*/ - -int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, float_status_t &status); -int fsin(floatx80 &a, float_status_t &status); -int fcos(floatx80 &a, float_status_t &status); -int ftan(floatx80 &a, float_status_t &status); - -/*----------------------------------------------------------------------------- -| Calculates the absolute value of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE floatx80& floatx80_abs(floatx80 ®) -{ - reg.exp &= 0x7FFF; - return reg; -} - -/*----------------------------------------------------------------------------- -| Changes the sign of the extended double-precision floating-point value 'a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE floatx80& floatx80_chs(floatx80 ®) -{ - reg.exp ^= 0x8000; - return reg; -} - -/*----------------------------------------------------------------------------- -| Commonly used extended double-precision floating-point constants. -*----------------------------------------------------------------------------*/ - -extern const floatx80 Const_Z; -extern const floatx80 Const_1; - -#endif diff --git a/bochs/cpu/i387.h b/bochs/cpu/i387.h index c345802360..6568faead3 100644 --- a/bochs/cpu/i387.h +++ b/bochs/cpu/i387.h @@ -26,7 +26,6 @@ #if BX_SUPPORT_FPU -#include "fpu/softfloat.h" #include "softfloat3e/include/softfloat_types.h" #define BX_FPU_REG(index) \ @@ -43,8 +42,6 @@ #include "fpu/status_w.h" #include "fpu/control_w.h" -extern int FPU_tagof(const floatx80 ®); - // // Minimal i387 structure // @@ -93,6 +90,9 @@ struct BOCHSAPI_MSVCONLY i387_t unsigned char align3; }; +extern int FPU_tagof(const floatx80 ®); +extern Bit16u unpack_FPU_TW(const i387_t *i387, Bit16u tag_byte); + #define IS_TAG_EMPTY(i) \ ((BX_CPU_THIS_PTR the_i387.FPU_gettagi(i)) == FPU_Tag_Empty) @@ -254,15 +254,15 @@ typedef BxPackedRegister BxPackedMmxRegister; #define MMXUB6(reg) (reg.ubyte(6)) #define MMXUB7(reg) (reg.ubyte(7)) -#define BX_MMX_REG(index) (BX_FPU_REG(index).fraction) +#define BX_MMX_REG(index) (BX_FPU_REG(index).signif) #define BX_READ_MMX_REG(index) \ (*((const BxPackedMmxRegister*)(&(BX_MMX_REG(index))))) #define BX_WRITE_MMX_REG(index, value) \ { \ - (BX_FPU_REG(index)).fraction = MMXUQ(value); \ - (BX_FPU_REG(index)).exp = 0xffff; \ + (BX_FPU_REG(index)).signif = MMXUQ(value); \ + (BX_FPU_REG(index)).signExp = 0xffff; \ } #endif /* BX_SUPPORT_FPU */ diff --git a/bochs/cpu/init.cc b/bochs/cpu/init.cc index 909746f35e..0860feb54e 100644 --- a/bochs/cpu/init.cc +++ b/bochs/cpu/init.cc @@ -508,8 +508,8 @@ void BX_CPU_C::register_state(void) for (n=0; n<8; n++) { sprintf(name, "st%d", n); bx_list_c *STx = new bx_list_c(fpu, name); - BXRS_HEX_PARAM_FIELD(STx, exp, the_i387.st_space[n].exp); - BXRS_HEX_PARAM_FIELD(STx, fraction, the_i387.st_space[n].fraction); + new bx_shadow_num_c(STx, "exp", &the_i387.st_space[n].signExp, BASE_HEX); + new bx_shadow_num_c(STx, "fraction", (Bit64s*) &the_i387.st_space[n].signif, BASE_HEX); } BXRS_DEC_PARAM_FIELD(fpu, tos, the_i387.tos); #endif diff --git a/bochs/cpu/msr.cc b/bochs/cpu/msr.cc index 4935640037..59c4ea5f69 100644 --- a/bochs/cpu/msr.cc +++ b/bochs/cpu/msr.cc @@ -663,6 +663,18 @@ bool isValidMSR_FixedMTRR(Bit64u fixed_mtrr_val) } #endif +bool isValidMSR_IA32_SPEC_CTRL(Bit64u val_64) +{ + // [0] - Enable IBRS: Indirect Branch Restricted Speculation + // [1] - Enable STIBP: Single Thread Indirect Branch Predictors + // [2] - Enable SSCB: Speculative Store Bypass Disable + // [63:3] - reserved + if (val_64 & ~(BX_CONST64(0x7))) + return false; + + return true; +} + #if BX_CPU_LEVEL >= 5 bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64) { @@ -1091,11 +1103,7 @@ bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64) if (BX_CPU_THIS_PTR in_vmx_guest && vm->vmexec_ctrls3.VIRTUALIZE_IA32_SPEC_CTRL()) val_64 = (BX_CPU_THIS_PTR msr.ia32_spec_ctrl & vm->ia32_spec_ctrl_mask) | (val_64 & ~vm->ia32_spec_ctrl_mask); #endif - // [0] - Enable IBRS: Indirect Branch Restricted Speculation - // [1] - Enable STIBP: Single Thread Indirect Branch Predictors - // [2] - Enable SSCB: Speculative Store Bypass Disable - // [63:3] - reserved - if (val_64 & ~(BX_CONST64(0x7))) { + if (! isValidMSR_IA32_SPEC_CTRL(val_64)) { BX_ERROR(("WRMSR: attempt to set reserved bits of IA32_SPEC_CTRL !")); return false; } diff --git a/bochs/cpu/msr.h b/bochs/cpu/msr.h index b4071ca8fd..5bbc95d1c8 100644 --- a/bochs/cpu/msr.h +++ b/bochs/cpu/msr.h @@ -149,6 +149,7 @@ enum MSR_Register { BX_MSR_IA32_UINTR_MISC = 0x988, BX_MSR_IA32_UINTR_PD = 0x989, // interface to UPID_ADDR BX_MSR_IA32_UINTR_TT = 0x98A, // interface to UITT_ADDR + BX_MSR_IA32_UINTR_TIMER = 0x1B00, // for User Timer feature (not implemented yet) #endif BX_MSR_XSS = 0xDA0, diff --git a/bochs/cpu/mwait.cc b/bochs/cpu/mwait.cc index 0f3a8a9bd3..3fd2f19de2 100644 --- a/bochs/cpu/mwait.cc +++ b/bochs/cpu/mwait.cc @@ -128,6 +128,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MONITOR(bxInstruction_c *i) BX_NEXT_INSTR(i); } +enum { + BX_MWAIT_WAKEUP_ON_EVENT_WHEN_INTERRUPT_DISABLE = 0x1, + BX_MWAIT_TIMED_MWAITX = 0x2, + BX_MWAIT_MONITORLESS_MWAIT = 0x4 +}; + void BX_CPP_AttrRegparmN(1) BX_CPU_C::MWAIT(bxInstruction_c *i) { #if BX_SUPPORT_MONITOR_MWAIT @@ -151,19 +157,18 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MWAIT(bxInstruction_c *i) // extension supported: // ECX[0] - interrupt MWAIT even if EFLAGS.IF = 0 - // ECX[1] - timed MWAITX + // ECX[1] - timed MWAITX (MWAITX only) + // ECX[2] - monitorless MWAIT // all other bits are reserved - if (i->getIaOpcode() == BX_IA_MWAITX) { - if (RCX & ~(BX_CONST64(3))) { - BX_ERROR(("%s: incorrect optional extensions in RCX", i->getIaOpcodeNameShort())); - exception(BX_GP_EXCEPTION, 0); - } - } - else { - if (RCX & ~(BX_CONST64(1))) { - BX_ERROR(("%s: incorrect optional extensions in RCX", i->getIaOpcodeNameShort())); - exception(BX_GP_EXCEPTION, 0); - } + Bit64u supported_bits = BX_MWAIT_WAKEUP_ON_EVENT_WHEN_INTERRUPT_DISABLE; + if (i->getIaOpcode() == BX_IA_MWAITX) + supported_bits |= BX_MWAIT_TIMED_MWAITX; + if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MONITORLESS_MWAIT)) + supported_bits |= BX_MWAIT_MONITORLESS_MWAIT; + + if (RCX & ~supported_bits) { + BX_ERROR(("%s: incorrect optional extensions in RCX", i->getIaOpcodeNameShort())); + exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM @@ -175,22 +180,25 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MWAIT(bxInstruction_c *i) } #endif - // If monitor has already triggered, we just return. - bool monitor_armed = true; - if (i->getIaOpcode() == BX_IA_MWAITX) { - if (! BX_CPU_THIS_PTR monitor.armed_by_monitorx()) { - monitor_armed = false; + if (! (ECX & BX_MWAIT_MONITORLESS_MWAIT)) { + // If monitor has already triggered, we just return. + bool monitor_armed = true; + if (i->getIaOpcode() == BX_IA_MWAITX) { + if (! BX_CPU_THIS_PTR monitor.armed_by_monitorx()) + monitor_armed = false; } - } - else { - if (! BX_CPU_THIS_PTR monitor.armed_by_monitor()) { - monitor_armed = false; + else { + if (! BX_CPU_THIS_PTR monitor.armed_by_monitor()) + monitor_armed = false; } - } - if (! monitor_armed) { - BX_DEBUG(("%s: the MONITOR was not armed or already triggered", i->getIaOpcodeNameShort())); - BX_NEXT_TRACE(i); + if (! monitor_armed) { + BX_DEBUG(("%s: the MONITOR was not armed or already triggered", i->getIaOpcodeNameShort())); + BX_NEXT_TRACE(i); + } + } + else { + BX_CPU_THIS_PTR monitor.reset_monitor(); // Monitorless MWAIT } static bool mwait_is_nop = SIM->get_param_bool(BXPN_MWAIT_IS_NOP)->get(); diff --git a/bochs/cpu/sha.cc b/bochs/cpu/sha.cc index 3d63d459e6..d8a971375e 100644 --- a/bochs/cpu/sha.cc +++ b/bochs/cpu/sha.cc @@ -233,33 +233,39 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHA256MSG2_VdqWdqR(bxInstruction_c *i) void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHA1RNDS4_VdqWdqIbR(bxInstruction_c *i) { // SHA1 Constants dependent on immediate i - static const Bit32u sha_Ki[4] = { 0x5A827999, 0x6ED9EBA1, 0X8F1BBCDC, 0xCA62C1D6 }; + static const Bit32u sha_Ki[4] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); unsigned imm = i->Ib() & 0x3; Bit32u K = sha_Ki[imm]; - Bit32u W[4] = { op2.xmm32u(3), op2.xmm32u(2), op2.xmm32u(1), op2.xmm32u(0) }; - Bit32u A[5], B[5], C[5], D[5], E[5]; + Bit32u A, B, C, D, E, W[4]; - A[0] = op1.xmm32u(3); - B[0] = op1.xmm32u(2); - C[0] = op1.xmm32u(1); - D[0] = op1.xmm32u(0); - E[0] = 0; + A = op1.xmm32u(3); + B = op1.xmm32u(2); + C = op1.xmm32u(1); + D = op1.xmm32u(0); + E = 0; + + W[0] = op2.xmm32u(3); + W[1] = op2.xmm32u(2); + W[2] = op2.xmm32u(1); + W[3] = op2.xmm32u(0); for (unsigned n=0; n < 4; n++) { - A[n+1] = sha_f(B[n], C[n], D[n], imm) + rol32(A[n], 5) + W[n] + E[n] + K; - B[n+1] = A[n]; - C[n+1] = rol32(B[n], 30); - D[n+1] = C[n]; - E[n+1] = D[n]; + Bit32u A_next = sha_f(B, C, D, imm) + rol32(A, 5) + W[n] + E + K; + + E = D; + D = C; + C = rol32(B, 30); + B = A; + A = A_next; } - op1.xmm32u(0) = A[4]; - op1.xmm32u(1) = B[4]; - op1.xmm32u(2) = C[4]; - op1.xmm32u(3) = D[4]; + op1.xmm32u(3) = A; + op1.xmm32u(2) = B; + op1.xmm32u(1) = C; + op1.xmm32u(0) = D; BX_WRITE_XMM_REG(i->dst(), op1); diff --git a/bochs/cpu/simd_pfp.h b/bochs/cpu/simd_pfp.h index 12df5d20cf..8f702e757e 100644 --- a/bochs/cpu/simd_pfp.h +++ b/bochs/cpu/simd_pfp.h @@ -26,14 +26,14 @@ // arithmetic add/sub/mul/div -BX_CPP_INLINE void xmm_addps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_addps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_add(op1->xmm32u(n), op2->xmm32u(n), &status); } } -BX_CPP_INLINE void xmm_addps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_addps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -43,14 +43,14 @@ BX_CPP_INLINE void xmm_addps_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_addpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_addpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_add(op1->xmm64u(n), op2->xmm64u(n), &status); } } -BX_CPP_INLINE void xmm_addpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_addpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -60,14 +60,14 @@ BX_CPP_INLINE void xmm_addpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_addph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_addph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_add(op1->xmm16u(n), op2->xmm16u(n), &status); } } -BX_CPP_INLINE void xmm_addph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_addph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -77,14 +77,14 @@ BX_CPP_INLINE void xmm_addph_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_subps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_subps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_sub(op1->xmm32u(n), op2->xmm32u(n), &status); } } -BX_CPP_INLINE void xmm_subps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_subps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -94,14 +94,14 @@ BX_CPP_INLINE void xmm_subps_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_subpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_subpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_sub(op1->xmm64u(n), op2->xmm64u(n), &status); } } -BX_CPP_INLINE void xmm_subpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_subpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -111,14 +111,14 @@ BX_CPP_INLINE void xmm_subpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_subph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_subph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_sub(op1->xmm16u(n), op2->xmm16u(n), &status); } } -BX_CPP_INLINE void xmm_subph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_subph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -128,14 +128,14 @@ BX_CPP_INLINE void xmm_subph_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_mulps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_mulps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_mul(op1->xmm32u(n), op2->xmm32u(n), &status); } } -BX_CPP_INLINE void xmm_mulps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_mulps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -145,14 +145,14 @@ BX_CPP_INLINE void xmm_mulps_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_mulpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_mulpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_mul(op1->xmm64u(n), op2->xmm64u(n), &status); } } -BX_CPP_INLINE void xmm_mulpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_mulpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -162,14 +162,14 @@ BX_CPP_INLINE void xmm_mulpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_mulph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_mulph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_mul(op1->xmm16u(n), op2->xmm16u(n), &status); } } -BX_CPP_INLINE void xmm_mulph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_mulph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -179,14 +179,14 @@ BX_CPP_INLINE void xmm_mulph_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_divps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_divps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_div(op1->xmm32u(n), op2->xmm32u(n), &status); } } -BX_CPP_INLINE void xmm_divps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_divps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -196,14 +196,14 @@ BX_CPP_INLINE void xmm_divps_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_divpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_divpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_div(op1->xmm64u(n), op2->xmm64u(n), &status); } } -BX_CPP_INLINE void xmm_divpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_divpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -213,14 +213,14 @@ BX_CPP_INLINE void xmm_divpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_divph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_divph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_div(op1->xmm16u(n), op2->xmm16u(n), &status); } } -BX_CPP_INLINE void xmm_divph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_divph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -230,7 +230,7 @@ BX_CPP_INLINE void xmm_divph_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_addsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_addsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { op1->xmm32u(0) = f32_sub(op1->xmm32u(0), op2->xmm32u(0), &status); op1->xmm32u(1) = f32_add(op1->xmm32u(1), op2->xmm32u(1), &status); @@ -238,7 +238,7 @@ BX_CPP_INLINE void xmm_addsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegis op1->xmm32u(3) = f32_add(op1->xmm32u(3), op2->xmm32u(3), &status); } -BX_CPP_INLINE void xmm_addsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_addsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { if (mask & 0x1) op1->xmm32u(0) = f32_sub(op1->xmm32u(0), op2->xmm32u(0), &status); @@ -261,13 +261,13 @@ BX_CPP_INLINE void xmm_addsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmm op1->xmm32u(3) = 0; } -BX_CPP_INLINE void xmm_addsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_addsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { op1->xmm64u(0) = f64_sub(op1->xmm64u(0), op2->xmm64u(0), &status); op1->xmm64u(1) = f64_add(op1->xmm64u(1), op2->xmm64u(1), &status); } -BX_CPP_INLINE void xmm_addsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_addsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { if (mask & 0x1) op1->xmm64u(0) = f64_sub(op1->xmm64u(0), op2->xmm64u(0), &status); @@ -282,7 +282,7 @@ BX_CPP_INLINE void xmm_addsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmm // horizontal arithmetic add/sub -BX_CPP_INLINE void xmm_haddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_haddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { op1->xmm32u(0) = f32_add(op1->xmm32u(0), op1->xmm32u(1), &status); op1->xmm32u(1) = f32_add(op1->xmm32u(2), op1->xmm32u(3), &status); @@ -290,7 +290,7 @@ BX_CPP_INLINE void xmm_haddps(BxPackedXmmRegister *op1, const BxPackedXmmRegiste op1->xmm32u(3) = f32_add(op2->xmm32u(2), op2->xmm32u(3), &status); } -BX_CPP_INLINE void xmm_haddps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_haddps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { if (mask & 0x1) op1->xmm32u(0) = f32_add(op1->xmm32u(0), op1->xmm32u(1), &status); @@ -313,13 +313,13 @@ BX_CPP_INLINE void xmm_haddps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRe op1->xmm32u(3) = 0; } -BX_CPP_INLINE void xmm_haddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_haddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { op1->xmm64u(0) = f64_add(op1->xmm64u(0), op1->xmm64u(1), &status); op1->xmm64u(1) = f64_add(op2->xmm64u(0), op2->xmm64u(1), &status); } -BX_CPP_INLINE void xmm_haddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_haddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { if (mask & 0x1) op1->xmm64u(0) = f64_add(op1->xmm64u(0), op1->xmm64u(1), &status); @@ -332,7 +332,7 @@ BX_CPP_INLINE void xmm_haddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRe op1->xmm64u(1) = 0; } -BX_CPP_INLINE void xmm_hsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_hsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { op1->xmm32u(0) = f32_sub(op1->xmm32u(0), op1->xmm32u(1), &status); op1->xmm32u(1) = f32_sub(op1->xmm32u(2), op1->xmm32u(3), &status); @@ -340,7 +340,7 @@ BX_CPP_INLINE void xmm_hsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegiste op1->xmm32u(3) = f32_sub(op2->xmm32u(2), op2->xmm32u(3), &status); } -BX_CPP_INLINE void xmm_hsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_hsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { if (mask & 0x1) op1->xmm32u(0) = f32_sub(op1->xmm32u(0), op1->xmm32u(1), &status); @@ -363,13 +363,13 @@ BX_CPP_INLINE void xmm_hsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRe op1->xmm32u(3) = 0; } -BX_CPP_INLINE void xmm_hsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_hsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { op1->xmm64u(0) = f64_sub(op1->xmm64u(0), op1->xmm64u(1), &status); op1->xmm64u(1) = f64_sub(op2->xmm64u(0), op2->xmm64u(1), &status); } -BX_CPP_INLINE void xmm_hsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_hsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { if (mask & 0x1) op1->xmm64u(0) = f64_sub(op1->xmm64u(0), op1->xmm64u(1), &status); @@ -384,14 +384,14 @@ BX_CPP_INLINE void xmm_hsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRe // min/max -BX_CPP_INLINE void xmm_minps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_minps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_min(op1->xmm32u(n), op2->xmm32u(n), &status); } } -BX_CPP_INLINE void xmm_minps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_minps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -401,14 +401,14 @@ BX_CPP_INLINE void xmm_minps_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_minpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_minpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_min(op1->xmm64u(n), op2->xmm64u(n), &status); } } -BX_CPP_INLINE void xmm_minpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_minpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -418,14 +418,14 @@ BX_CPP_INLINE void xmm_minpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_minph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_minph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_min(op1->xmm16u(n), op2->xmm16u(n), &status); } } -BX_CPP_INLINE void xmm_minph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_minph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -435,14 +435,14 @@ BX_CPP_INLINE void xmm_minph_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_maxps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_maxps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_max(op1->xmm32u(n), op2->xmm32u(n), &status); } } -BX_CPP_INLINE void xmm_maxps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_maxps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -452,14 +452,14 @@ BX_CPP_INLINE void xmm_maxps_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_maxpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_maxpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_max(op1->xmm64u(n), op2->xmm64u(n), &status); } } -BX_CPP_INLINE void xmm_maxpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_maxpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -469,14 +469,14 @@ BX_CPP_INLINE void xmm_maxpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_maxph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_maxph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_max(op1->xmm16u(n), op2->xmm16u(n), &status); } } -BX_CPP_INLINE void xmm_maxph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_maxph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -488,14 +488,14 @@ BX_CPP_INLINE void xmm_maxph_mask(BxPackedXmmRegister *op1, const BxPackedXmmReg // fma -BX_CPP_INLINE void xmm_fmaddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmaddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_mulAdd(op1->xmm32u(n), op2->xmm32u(n), op3->xmm32u(n), 0, &status); } } -BX_CPP_INLINE void xmm_fmaddps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmaddps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -505,14 +505,14 @@ BX_CPP_INLINE void xmm_fmaddps_mask(BxPackedXmmRegister *op1, const BxPackedXmmR } } -BX_CPP_INLINE void xmm_fmaddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmaddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_mulAdd(op1->xmm64u(n), op2->xmm64u(n), op3->xmm64u(n), 0, &status); } } -BX_CPP_INLINE void xmm_fmaddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmaddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -522,14 +522,14 @@ BX_CPP_INLINE void xmm_fmaddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmR } } -BX_CPP_INLINE void xmm_fmaddph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmaddph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_mulAdd(op1->xmm16u(n), op2->xmm16u(n), op3->xmm16u(n), 0, &status); } } -BX_CPP_INLINE void xmm_fmaddph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmaddph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -539,14 +539,14 @@ BX_CPP_INLINE void xmm_fmaddph_mask(BxPackedXmmRegister *op1, const BxPackedXmmR } } -BX_CPP_INLINE void xmm_fmsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_mulAdd(op1->xmm32u(n), op2->xmm32u(n), op3->xmm32u(n), softfloat_muladd_negate_c, &status); } } -BX_CPP_INLINE void xmm_fmsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -556,14 +556,14 @@ BX_CPP_INLINE void xmm_fmsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmR } } -BX_CPP_INLINE void xmm_fmsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_mulAdd(op1->xmm64u(n), op2->xmm64u(n), op3->xmm64u(n), softfloat_muladd_negate_c, &status); } } -BX_CPP_INLINE void xmm_fmsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -573,14 +573,14 @@ BX_CPP_INLINE void xmm_fmsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmR } } -BX_CPP_INLINE void xmm_fmsubph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmsubph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_mulAdd(op1->xmm16u(n), op2->xmm16u(n), op3->xmm16u(n), softfloat_muladd_negate_c, &status); } } -BX_CPP_INLINE void xmm_fmsubph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmsubph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -590,7 +590,7 @@ BX_CPP_INLINE void xmm_fmsubph_mask(BxPackedXmmRegister *op1, const BxPackedXmmR } } -BX_CPP_INLINE void xmm_fmaddsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmaddsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { op1->xmm32u(0) = f32_mulAdd(op1->xmm32u(0), op2->xmm32u(0), op3->xmm32u(0), softfloat_muladd_negate_c, &status); op1->xmm32u(1) = f32_mulAdd(op1->xmm32u(1), op2->xmm32u(1), op3->xmm32u(1), 0, &status); @@ -598,7 +598,7 @@ BX_CPP_INLINE void xmm_fmaddsubps(BxPackedXmmRegister *op1, const BxPackedXmmReg op1->xmm32u(3) = f32_mulAdd(op1->xmm32u(3), op2->xmm32u(3), op3->xmm32u(3), 0, &status); } -BX_CPP_INLINE void xmm_fmaddsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmaddsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n+=2, mask >>= 2) { if (mask & 0x1) @@ -613,13 +613,13 @@ BX_CPP_INLINE void xmm_fmaddsubps_mask(BxPackedXmmRegister *op1, const BxPackedX } } -BX_CPP_INLINE void xmm_fmaddsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmaddsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { op1->xmm64u(0) = f64_mulAdd(op1->xmm64u(0), op2->xmm64u(0), op3->xmm64u(0), softfloat_muladd_negate_c, &status); op1->xmm64u(1) = f64_mulAdd(op1->xmm64u(1), op2->xmm64u(1), op3->xmm64u(1), 0, &status); } -BX_CPP_INLINE void xmm_fmaddsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmaddsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { if (mask & 0x1) op1->xmm64u(0) = f64_mulAdd(op1->xmm64u(0), op2->xmm64u(0), op3->xmm64u(0), softfloat_muladd_negate_c, &status); @@ -632,7 +632,7 @@ BX_CPP_INLINE void xmm_fmaddsubpd_mask(BxPackedXmmRegister *op1, const BxPackedX op1->xmm64u(1) = 0; } -BX_CPP_INLINE void xmm_fmaddsubph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmaddsubph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<8;n+=2) { op1->xmm16u(n) = f16_mulAdd(op1->xmm16u(n), op2->xmm16u(n), op3->xmm16u(n), softfloat_muladd_negate_c, &status); @@ -640,7 +640,7 @@ BX_CPP_INLINE void xmm_fmaddsubph(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_fmaddsubph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmaddsubph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n+=2, mask >>= 2) { if (mask & 0x1) @@ -655,7 +655,7 @@ BX_CPP_INLINE void xmm_fmaddsubph_mask(BxPackedXmmRegister *op1, const BxPackedX } } -BX_CPP_INLINE void xmm_fmsubaddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmsubaddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { op1->xmm32u(0) = f32_mulAdd(op1->xmm32u(0), op2->xmm32u(0), op3->xmm32u(0), 0, &status); op1->xmm32u(1) = f32_mulAdd(op1->xmm32u(1), op2->xmm32u(1), op3->xmm32u(1), softfloat_muladd_negate_c, &status); @@ -663,7 +663,7 @@ BX_CPP_INLINE void xmm_fmsubaddps(BxPackedXmmRegister *op1, const BxPackedXmmReg op1->xmm32u(3) = f32_mulAdd(op1->xmm32u(3), op2->xmm32u(3), op3->xmm32u(3), softfloat_muladd_negate_c, &status); } -BX_CPP_INLINE void xmm_fmsubaddps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmsubaddps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n+=2, mask >>= 2) { if (mask & 0x1) @@ -678,13 +678,13 @@ BX_CPP_INLINE void xmm_fmsubaddps_mask(BxPackedXmmRegister *op1, const BxPackedX } } -BX_CPP_INLINE void xmm_fmsubaddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmsubaddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { op1->xmm64u(0) = f64_mulAdd(op1->xmm64u(0), op2->xmm64u(0), op3->xmm64u(0), 0, &status); op1->xmm64u(1) = f64_mulAdd(op1->xmm64u(1), op2->xmm64u(1), op3->xmm64u(1), softfloat_muladd_negate_c, &status); } -BX_CPP_INLINE void xmm_fmsubaddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmsubaddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { if (mask & 0x1) op1->xmm64u(0) = f64_mulAdd(op1->xmm64u(0), op2->xmm64u(0), op3->xmm64u(0), 0, &status); @@ -697,7 +697,7 @@ BX_CPP_INLINE void xmm_fmsubaddpd_mask(BxPackedXmmRegister *op1, const BxPackedX op1->xmm64u(1) = 0; } -BX_CPP_INLINE void xmm_fmsubaddph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fmsubaddph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<8;n+=2) { op1->xmm16u(n) = f16_mulAdd(op1->xmm16u(n), op2->xmm16u(n), op3->xmm16u(n), 0, &status); @@ -705,7 +705,7 @@ BX_CPP_INLINE void xmm_fmsubaddph(BxPackedXmmRegister *op1, const BxPackedXmmReg } } -BX_CPP_INLINE void xmm_fmsubaddph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fmsubaddph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n+=2, mask >>= 2) { if (mask & 0x1) @@ -720,14 +720,14 @@ BX_CPP_INLINE void xmm_fmsubaddph_mask(BxPackedXmmRegister *op1, const BxPackedX } } -BX_CPP_INLINE void xmm_fnmaddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fnmaddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_mulAdd(op1->xmm32u(n), op2->xmm32u(n), op3->xmm32u(n), softfloat_muladd_negate_product, &status); } } -BX_CPP_INLINE void xmm_fnmaddps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fnmaddps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -737,14 +737,14 @@ BX_CPP_INLINE void xmm_fnmaddps_mask(BxPackedXmmRegister *op1, const BxPackedXmm } } -BX_CPP_INLINE void xmm_fnmaddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fnmaddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_mulAdd(op1->xmm64u(n), op2->xmm64u(n), op3->xmm64u(n), softfloat_muladd_negate_product, &status); } } -BX_CPP_INLINE void xmm_fnmaddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fnmaddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -754,14 +754,14 @@ BX_CPP_INLINE void xmm_fnmaddpd_mask(BxPackedXmmRegister *op1, const BxPackedXmm } } -BX_CPP_INLINE void xmm_fnmaddph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fnmaddph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_mulAdd(op1->xmm16u(n), op2->xmm16u(n), op3->xmm16u(n), softfloat_muladd_negate_product, &status); } } -BX_CPP_INLINE void xmm_fnmaddph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fnmaddph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -771,14 +771,14 @@ BX_CPP_INLINE void xmm_fnmaddph_mask(BxPackedXmmRegister *op1, const BxPackedXmm } } -BX_CPP_INLINE void xmm_fnmsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fnmsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_mulAdd(op1->xmm32u(n), op2->xmm32u(n), op3->xmm32u(n), softfloat_muladd_negate_result, &status); } } -BX_CPP_INLINE void xmm_fnmsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fnmsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -788,14 +788,14 @@ BX_CPP_INLINE void xmm_fnmsubps_mask(BxPackedXmmRegister *op1, const BxPackedXmm } } -BX_CPP_INLINE void xmm_fnmsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fnmsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_mulAdd(op1->xmm64u(n), op2->xmm64u(n), op3->xmm64u(n), softfloat_muladd_negate_result, &status); } } -BX_CPP_INLINE void xmm_fnmsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fnmsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -805,14 +805,14 @@ BX_CPP_INLINE void xmm_fnmsubpd_mask(BxPackedXmmRegister *op1, const BxPackedXmm } } -BX_CPP_INLINE void xmm_fnmsubph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) +BX_CPP_INLINE void xmm_fnmsubph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_mulAdd(op1->xmm16u(n), op2->xmm16u(n), op3->xmm16u(n), softfloat_muladd_negate_result, &status); } } -BX_CPP_INLINE void xmm_fnmsubph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_fnmsubph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -824,14 +824,14 @@ BX_CPP_INLINE void xmm_fnmsubph_mask(BxPackedXmmRegister *op1, const BxPackedXmm // sqrt -BX_CPP_INLINE void xmm_sqrtps(BxPackedXmmRegister *op, float_status_t &status) +BX_CPP_INLINE void xmm_sqrtps(BxPackedXmmRegister *op, softfloat_status_t &status) { for (unsigned n=0; n < 4; n++) { op->xmm32u(n) = f32_sqrt(op->xmm32u(n), &status); } } -BX_CPP_INLINE void xmm_sqrtps_mask(BxPackedXmmRegister *op, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_sqrtps_mask(BxPackedXmmRegister *op, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -841,14 +841,14 @@ BX_CPP_INLINE void xmm_sqrtps_mask(BxPackedXmmRegister *op, float_status_t &stat } } -BX_CPP_INLINE void xmm_sqrtpd(BxPackedXmmRegister *op, float_status_t &status) +BX_CPP_INLINE void xmm_sqrtpd(BxPackedXmmRegister *op, softfloat_status_t &status) { for (unsigned n=0; n < 2; n++) { op->xmm64u(n) = f64_sqrt(op->xmm64u(n), &status); } } -BX_CPP_INLINE void xmm_sqrtpd_mask(BxPackedXmmRegister *op, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_sqrtpd_mask(BxPackedXmmRegister *op, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -858,14 +858,14 @@ BX_CPP_INLINE void xmm_sqrtpd_mask(BxPackedXmmRegister *op, float_status_t &stat } } -BX_CPP_INLINE void xmm_sqrtph(BxPackedXmmRegister *op, float_status_t &status) +BX_CPP_INLINE void xmm_sqrtph(BxPackedXmmRegister *op, softfloat_status_t &status) { for (unsigned n=0; n < 8; n++) { op->xmm16u(n) = f16_sqrt(op->xmm16u(n), &status); } } -BX_CPP_INLINE void xmm_sqrtph_mask(BxPackedXmmRegister *op, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_sqrtph_mask(BxPackedXmmRegister *op, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -877,14 +877,14 @@ BX_CPP_INLINE void xmm_sqrtph_mask(BxPackedXmmRegister *op, float_status_t &stat // getexp -BX_CPP_INLINE void xmm_getexpps(BxPackedXmmRegister *op, float_status_t &status) +BX_CPP_INLINE void xmm_getexpps(BxPackedXmmRegister *op, softfloat_status_t &status) { for (unsigned n=0; n < 4; n++) { op->xmm32u(n) = f32_getExp(op->xmm32u(n), &status); } } -BX_CPP_INLINE void xmm_getexpps_mask(BxPackedXmmRegister *op, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_getexpps_mask(BxPackedXmmRegister *op, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -894,14 +894,14 @@ BX_CPP_INLINE void xmm_getexpps_mask(BxPackedXmmRegister *op, float_status_t &st } } -BX_CPP_INLINE void xmm_getexppd(BxPackedXmmRegister *op, float_status_t &status) +BX_CPP_INLINE void xmm_getexppd(BxPackedXmmRegister *op, softfloat_status_t &status) { for (unsigned n=0; n < 2; n++) { op->xmm64u(n) = f64_getExp(op->xmm64u(n), &status); } } -BX_CPP_INLINE void xmm_getexppd_mask(BxPackedXmmRegister *op, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_getexppd_mask(BxPackedXmmRegister *op, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -911,14 +911,14 @@ BX_CPP_INLINE void xmm_getexppd_mask(BxPackedXmmRegister *op, float_status_t &st } } -BX_CPP_INLINE void xmm_getexpph(BxPackedXmmRegister *op, float_status_t &status) +BX_CPP_INLINE void xmm_getexpph(BxPackedXmmRegister *op, softfloat_status_t &status) { for (unsigned n=0; n < 8; n++) { op->xmm16u(n) = f16_getExp(op->xmm16u(n), &status); } } -BX_CPP_INLINE void xmm_getexpph_mask(BxPackedXmmRegister *op, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_getexpph_mask(BxPackedXmmRegister *op, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) @@ -930,14 +930,14 @@ BX_CPP_INLINE void xmm_getexpph_mask(BxPackedXmmRegister *op, float_status_t &st // scalef -BX_CPP_INLINE void xmm_scalefps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_scalefps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<4;n++) { op1->xmm32u(n) = f32_scalef(op1->xmm32u(n), op2->xmm32u(n), &status); } } -BX_CPP_INLINE void xmm_scalefps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_scalefps_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 4; n++, mask >>= 1) { if (mask & 0x1) @@ -947,14 +947,14 @@ BX_CPP_INLINE void xmm_scalefps_mask(BxPackedXmmRegister *op1, const BxPackedXmm } } -BX_CPP_INLINE void xmm_scalefpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE void xmm_scalefpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<2;n++) { op1->xmm64u(n) = f64_scalef(op1->xmm64u(n), op2->xmm64u(n), &status); } } -BX_CPP_INLINE void xmm_scalefpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_scalefpd_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 2; n++, mask >>= 1) { if (mask & 0x1) @@ -964,16 +964,22 @@ BX_CPP_INLINE void xmm_scalefpd_mask(BxPackedXmmRegister *op1, const BxPackedXmm } } -#include "fpu/softfloat16.h" +// FIXME, f16_scalef should be implemented in softfloat3e +extern float32 convert_ne_fp16_to_fp32(float16 op); -BX_CPP_INLINE void xmm_scalefph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) +BX_CPP_INLINE float16 f16_scalef(float16 a, float16 b, softfloat_status_t *status) +{ + return f32_to_f16(f32_scalef(convert_ne_fp16_to_fp32(a), convert_ne_fp16_to_fp32(b), status), status); +} + +BX_CPP_INLINE void xmm_scalefph(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status) { for (unsigned n=0;n<8;n++) { op1->xmm16u(n) = f16_scalef(op1->xmm16u(n), op2->xmm16u(n), &status); } } -BX_CPP_INLINE void xmm_scalefph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status, Bit32u mask) +BX_CPP_INLINE void xmm_scalefph_mask(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, softfloat_status_t &status, Bit32u mask) { for (unsigned n=0; n < 8; n++, mask >>= 1) { if (mask & 0x1) diff --git a/bochs/cpu/softfloat3e/8086-SSE/s_propagateNaNExtF80UI.c b/bochs/cpu/softfloat3e/8086-SSE/s_propagateNaNExtF80UI.c index 808522f26b..fa83fa24f3 100644 --- a/bochs/cpu/softfloat3e/8086-SSE/s_propagateNaNExtF80UI.c +++ b/bochs/cpu/softfloat3e/8086-SSE/s_propagateNaNExtF80UI.c @@ -48,19 +48,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 +extFloat80_t softfloat_propagateNaNExtF80UI( uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, - struct softfloat_status_t *status -) + struct softfloat_status_t *status) { bool isSigNaNA, isSigNaNB; uint64_t uiNonsigA0, uiNonsigB0; uint16_t uiMagA64, uiMagB64; - struct uint128 uiZ; + extFloat80_t z; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ @@ -93,11 +92,11 @@ struct uint128 if (uiB0 < uiA0) goto returnA; if (uiA64 < uiB64) goto returnA; returnB: - uiZ.v64 = uiB64; - uiZ.v0 = uiNonsigB0; - return uiZ; + z.signExp = uiB64; + z.signif = uiNonsigB0; + return z; returnA: - uiZ.v64 = uiA64; - uiZ.v0 = uiNonsigA0; - return uiZ; + z.signExp = uiA64; + z.signif = uiNonsigA0; + return z; } diff --git a/bochs/cpu/softfloat3e/Makefile.in b/bochs/cpu/softfloat3e/Makefile.in index 527058c169..c6f93ebfa5 100644 --- a/bochs/cpu/softfloat3e/Makefile.in +++ b/bochs/cpu/softfloat3e/Makefile.in @@ -40,7 +40,7 @@ SOFTFLOAT_OPTS = \ -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV32TO16 -DSOFTFLOAT_FAST_DIV64TO32 DELETE = @RMCOMMAND@ -C_INCLUDES = -I. -I../.. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include +C_INCLUDES = -I. -I../.. -I$(SOURCE_DIR)/include COMPILE_C = \ $(CXX) @DASH@c @CFLAGS@ \ -DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) @OFP@$@ @@ -106,19 +106,16 @@ OBJS_OTHERS = \ s_normRoundPackToF16$(OBJ) \ s_addMagsF16$(OBJ) \ s_subMagsF16$(OBJ) \ - s_mulAddF16$(OBJ) \ s_normSubnormalF32Sig$(OBJ) \ s_roundPackToF32$(OBJ) \ s_normRoundPackToF32$(OBJ) \ s_addMagsF32$(OBJ) \ s_subMagsF32$(OBJ) \ - s_mulAddF32$(OBJ) \ s_normSubnormalF64Sig$(OBJ) \ s_roundPackToF64$(OBJ) \ s_normRoundPackToF64$(OBJ) \ s_addMagsF64$(OBJ) \ s_subMagsF64$(OBJ) \ - s_mulAddF64$(OBJ) \ s_packToExtF80$(OBJ) \ s_normSubnormalExtF80Sig$(OBJ) \ s_roundPackToExtF80$(OBJ) \ @@ -130,7 +127,6 @@ OBJS_OTHERS = \ s_normRoundPackToF128$(OBJ) \ s_addMagsF128$(OBJ) \ s_subMagsF128$(OBJ) \ - s_mulAddF128$(OBJ) \ isNaN$(OBJ) \ isSignalingNaN$(OBJ) \ ui32_to_f16$(OBJ) \ @@ -243,6 +239,8 @@ OBJS_OTHERS = \ extF80_roundToInt$(OBJ) \ extF80_class$(OBJ) \ extF80_compare$(OBJ) \ + extF80_extract$(OBJ) \ + extF80_scale$(OBJ) \ extF80_addsub$(OBJ) \ extF80_mul$(OBJ) \ extF80_div$(OBJ) \ @@ -263,8 +261,7 @@ OBJS_OTHERS = \ f128_addsub$(OBJ) \ f128_mul$(OBJ) \ f128_mulAdd$(OBJ) \ - f128_div$(OBJ) \ - f128_sqrt$(OBJ) + f128_div$(OBJ) OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) @@ -273,7 +270,7 @@ $(OBJS_ALL): \ $(SOURCE_DIR)/include/primitives.h $(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ - $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ + $(SOURCE_DIR)/include/specialize.h \ $(SOURCE_DIR)/include/softfloat.h @GNU_MAKE_ONLY@$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c diff --git a/bochs/cpu/softfloat3e/extF80_div.c b/bochs/cpu/softfloat3e/extF80_div.c index b4b761a74c..42a9fa8841 100644 --- a/bochs/cpu/softfloat3e/extF80_div.c +++ b/bochs/cpu/softfloat3e/extF80_div.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" @@ -62,7 +63,6 @@ extFloat80_t extF80_div(extFloat80_t a, extFloat80_t b, struct softfloat_status_ uint32_t q; struct uint128 term; uint64_t sigZExtra; - struct uint128 uiZ; // handle unsupported extended double-precision floating encodings if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) @@ -180,8 +180,7 @@ extFloat80_t extF80_div(extFloat80_t a, extFloat80_t b, struct softfloat_status_ /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: - uiZ = softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); - return packToExtF80(uiZ.v64, uiZ.v0); + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: diff --git a/bochs/cpu/softfloat3e/extF80_extract.c b/bochs/cpu/softfloat3e/extF80_extract.c new file mode 100644 index 0000000000..e944f8e311 --- /dev/null +++ b/bochs/cpu/softfloat3e/extF80_extract.c @@ -0,0 +1,98 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 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. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Separate the source extended double-precision floating point value `a' +| into its exponent and significand, store the significant back to the +| 'a' and return the exponent. The operation performed is a superset of +| the IEC/IEEE recommended logb(x) function. +*----------------------------------------------------------------------------*/ + +extFloat80_t extF80_extract(extFloat80_t *a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + struct exp32_sig64 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(*a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + *a = packToExtF80(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + return *a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a->signExp; + uiA0 = a->signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if (sigA<<1) { + *a = softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status); + return *a; + } + return packToExtF80(0, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + softfloat_raiseFlags(status, softfloat_flag_divbyzero); + *a = packToExtF80(signA, 0, 0); + return packToExtF80(1, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + } + + *a = packToExtF80(signA, 0x3FFF, sigA); + return i32_to_extF80(expA - 0x3FFF); +} diff --git a/bochs/cpu/softfloat3e/extF80_mul.c b/bochs/cpu/softfloat3e/extF80_mul.c index e56396fba1..f6cf07df26 100644 --- a/bochs/cpu/softfloat3e/extF80_mul.c +++ b/bochs/cpu/softfloat3e/extF80_mul.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" @@ -55,7 +56,7 @@ extFloat80_t extF80_mul(extFloat80_t a, extFloat80_t b, struct softfloat_status_ uint64_t magBits; struct exp32_sig64 normExpSig; int32_t expZ; - struct uint128 sig128Z, uiZ; + struct uint128 sig128Z; uint16_t uiZ64; uint64_t uiZ0; @@ -135,8 +136,7 @@ extFloat80_t extF80_mul(extFloat80_t a, extFloat80_t b, struct softfloat_status_ /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: - uiZ = softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); - return packToExtF80(uiZ.v64, uiZ.v0); + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infArg: diff --git a/bochs/cpu/softfloat3e/extF80_rem.c b/bochs/cpu/softfloat3e/extF80_rem.c index 43c24276fb..02f887b7df 100644 --- a/bochs/cpu/softfloat3e/extF80_rem.c +++ b/bochs/cpu/softfloat3e/extF80_rem.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" @@ -57,7 +58,6 @@ extFloat80_t extF80_rem(extFloat80_t a, extFloat80_t b, struct softfloat_status_ uint64_t q64; struct uint128 term, altRem, meanRem; bool signRem; - struct uint128 uiZ; // handle unsupported extended double-precision floating encodings if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) @@ -93,21 +93,27 @@ extFloat80_t extF80_rem(extFloat80_t a, extFloat80_t b, struct softfloat_status_ } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ - if (! expB) expB = 1; + if (! expB) { + expB = 1; + if (sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } if (! (sigB & UINT64_C(0x8000000000000000))) { if (! sigB) goto invalid; - softfloat_raiseFlags(status, softfloat_flag_denormal); normExpSig = softfloat_normSubnormalExtF80Sig(sigB); expB += normExpSig.exp; sigB = normExpSig.sig; } - if (! expA) expA = 1; + if (! expA) { + expA = 1; + if (sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } if (! (sigA & UINT64_C(0x8000000000000000))) { if (! sigA) { expA = 0; goto copyA; } - softfloat_raiseFlags(status, softfloat_flag_denormal); normExpSig = softfloat_normSubnormalExtF80Sig(sigA); expA += normExpSig.exp; sigA = normExpSig.sig; @@ -177,8 +183,7 @@ extFloat80_t extF80_rem(extFloat80_t a, extFloat80_t b, struct softfloat_status_ /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: - uiZ = softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); - return packToExtF80(uiZ.v64, uiZ.v0); + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: diff --git a/bochs/cpu/softfloat3e/extF80_roundToInt.c b/bochs/cpu/softfloat3e/extF80_roundToInt.c index 0728d52113..142bc8810c 100644 --- a/bochs/cpu/softfloat3e/extF80_roundToInt.c +++ b/bochs/cpu/softfloat3e/extF80_roundToInt.c @@ -47,7 +47,6 @@ extFloat80_t uint64_t sigA; uint16_t uiZ64; uint64_t sigZ; - struct uint128 uiZ; uint64_t lastBitMask, roundBitsMask; // handle unsupported extended double-precision floating encodings @@ -66,8 +65,7 @@ extFloat80_t *------------------------------------------------------------------------*/ if (0x403E <= exp) { if ((exp == 0x7FFF) && (uint64_t) (sigA<<1)) { - uiZ = softfloat_propagateNaNExtF80UI(uiA64, sigA, 0, 0, status); - return packToExtF80(uiZ.v64, uiZ.v0); + return softfloat_propagateNaNExtF80UI(uiA64, sigA, 0, 0, status); } return a; } diff --git a/bochs/cpu/softfloat3e/extF80_scale.c b/bochs/cpu/softfloat3e/extF80_scale.c new file mode 100644 index 0000000000..f4f58ca2f9 --- /dev/null +++ b/bochs/cpu/softfloat3e/extF80_scale.c @@ -0,0 +1,137 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 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. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Scales extended double-precision floating-point value in operand `a' by +| value `b'. The function truncates the value in the second operand 'b' to +| an integral value and adds that value to the exponent of the operand 'a'. +| The operation performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +extFloat80_t extF80_scale(extFloat80_t a, extFloat80_t b, softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + int32_t expB; + uint64_t sigB; + struct exp32_sig64 normExpSig; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { +invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + + if (expA == 0x7FFF) { + if ((sigA<<1) || ((expB == 0x7FFF) && (sigB<<1))) { + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + } + if ((expB == 0x7FFF) && signB) goto invalid; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + return a; + } + if (expB == 0x7FFF) { + if (sigB<<1) { + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + } + if ((expA | sigA) == 0) { + if (! signB) goto invalid; + return a; + } + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + if (signB) return packToExtF80(signA, 0, 0); + return packToExtF80(signA, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (! expA) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + if (! sigA) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + if (expB < 0x3FFF) + return softfloat_normRoundPackToExtF80(signA, expA, sigA, 0, 80, status); + } + if (!expB) { + if (!sigB) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + } + + if (expB > 0x400E) { + /* generate appropriate overflow/underflow */ + return softfloat_roundPackToExtF80(signA, signB ? -0x3FFF : 0x7FFF, sigA, 0, 80, status); + } + + if (expB < 0x3FFF) return a; + + int shiftCount = 0x403E - expB; + sigB >>= shiftCount; + int32_t scale = (int32_t) sigB; + if (signB) scale = -scale; /* -32768..32767 */ + + return softfloat_roundPackToExtF80(signA, expA + scale, sigA, 0, 80, status); +} diff --git a/bochs/cpu/softfloat3e/extF80_sqrt.c b/bochs/cpu/softfloat3e/extF80_sqrt.c index 1853c957ff..9e5c5e09ad 100644 --- a/bochs/cpu/softfloat3e/extF80_sqrt.c +++ b/bochs/cpu/softfloat3e/extF80_sqrt.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" @@ -46,9 +47,6 @@ extFloat80_t extF80_sqrt(extFloat80_t a, struct softfloat_status_t *status) bool signA; int32_t expA; uint64_t sigA; - struct uint128 uiZ; - uint16_t uiZ64; - uint64_t uiZ0; struct exp32_sig64 normExpSig; int32_t expZ; uint32_t sig32A, recipSqrt32, sig32Z; @@ -72,8 +70,7 @@ extFloat80_t extF80_sqrt(extFloat80_t a, struct softfloat_status_t *status) *------------------------------------------------------------------------*/ if (expA == 0x7FFF) { if (sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) { - uiZ = softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status); - return packToExtF80(uiZ.v64, uiZ.v0); + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status); } if (! signA) return a; goto invalid; diff --git a/bochs/cpu/softfloat3e/extF80_to_f128.c b/bochs/cpu/softfloat3e/extF80_to_f128.c index 03976038c3..cf3e6d8c59 100644 --- a/bochs/cpu/softfloat3e/extF80_to_f128.c +++ b/bochs/cpu/softfloat3e/extF80_to_f128.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/extF80_to_f16.c b/bochs/cpu/softfloat3e/extF80_to_f16.c index 28523f302b..23f7311204 100644 --- a/bochs/cpu/softfloat3e/extF80_to_f16.c +++ b/bochs/cpu/softfloat3e/extF80_to_f16.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float16_t extF80_to_f16(extFloat80_t a, struct softfloat_status_t *status) +float16 extF80_to_f16(extFloat80_t a, struct softfloat_status_t *status) { uint16_t uiA64; uint64_t uiA0; diff --git a/bochs/cpu/softfloat3e/extF80_to_f32.c b/bochs/cpu/softfloat3e/extF80_to_f32.c index 75a6d836ce..9217d18003 100644 --- a/bochs/cpu/softfloat3e/extF80_to_f32.c +++ b/bochs/cpu/softfloat3e/extF80_to_f32.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float32_t extF80_to_f32(extFloat80_t a, struct softfloat_status_t *status) +float32 extF80_to_f32(extFloat80_t a, struct softfloat_status_t *status) { uint16_t uiA64; uint64_t uiA0; diff --git a/bochs/cpu/softfloat3e/extF80_to_f64.c b/bochs/cpu/softfloat3e/extF80_to_f64.c index 31ef43eeaa..1463c8c10f 100644 --- a/bochs/cpu/softfloat3e/extF80_to_f64.c +++ b/bochs/cpu/softfloat3e/extF80_to_f64.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float64_t extF80_to_f64(extFloat80_t a, struct softfloat_status_t *status) +float64 extF80_to_f64(extFloat80_t a, struct softfloat_status_t *status) { uint16_t uiA64; uint64_t uiA0; diff --git a/bochs/cpu/softfloat3e/extF80_to_i32.c b/bochs/cpu/softfloat3e/extF80_to_i32.c index 430c80f169..4a5e870f1a 100644 --- a/bochs/cpu/softfloat3e/extF80_to_i32.c +++ b/bochs/cpu/softfloat3e/extF80_to_i32.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/extF80_to_i64.c b/bochs/cpu/softfloat3e/extF80_to_i64.c index 39832dd6bc..f0ee5dd88e 100644 --- a/bochs/cpu/softfloat3e/extF80_to_i64.c +++ b/bochs/cpu/softfloat3e/extF80_to_i64.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/extF80_to_ui32.c b/bochs/cpu/softfloat3e/extF80_to_ui32.c index 62c98621e0..8b46ebe59b 100644 --- a/bochs/cpu/softfloat3e/extF80_to_ui32.c +++ b/bochs/cpu/softfloat3e/extF80_to_ui32.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/extF80_to_ui64.c b/bochs/cpu/softfloat3e/extF80_to_ui64.c index 28e8ce7733..5c7e673339 100644 --- a/bochs/cpu/softfloat3e/extF80_to_ui64.c +++ b/bochs/cpu/softfloat3e/extF80_to_ui64.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/f128_div.c b/bochs/cpu/softfloat3e/f128_div.c index f709ae0d35..837eb15aa0 100644 --- a/bochs/cpu/softfloat3e/f128_div.c +++ b/bochs/cpu/softfloat3e/f128_div.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/f128_mul.c b/bochs/cpu/softfloat3e/f128_mul.c index 2c302eb5ed..fd63a4590a 100644 --- a/bochs/cpu/softfloat3e/f128_mul.c +++ b/bochs/cpu/softfloat3e/f128_mul.c @@ -36,6 +36,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" +#include "primitiveTypes.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/f128_mulAdd.c b/bochs/cpu/softfloat3e/f128_mulAdd.c index 8ca9d66c8b..749342f5f1 100644 --- a/bochs/cpu/softfloat3e/f128_mulAdd.c +++ b/bochs/cpu/softfloat3e/f128_mulAdd.c @@ -35,20 +35,298 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" +#include "primitiveTypes.h" #include "softfloat.h" +#include "specialize.h" float128_t f128_mulAdd(float128_t a, float128_t b, float128_t c, uint8_t op, struct softfloat_status_t *status) { + bool signA; + int32_t expA; + struct uint128 sigA; + bool signB; + int32_t expB; + struct uint128 sigB; + bool signC; + int32_t expC; + struct uint128 sigC; + bool signZ; + uint64_t magBits; + struct uint128 uiZ; + struct exp32_sig128 normExpSig; + int32_t expZ; + uint64_t sig256Z[4]; + struct uint128 sigZ; + int32_t shiftDist, expDiff; + struct uint128 x128; + uint64_t sig256C[4]; + static uint64_t zero256[4] = INIT_UINTM4(0, 0, 0, 0); + uint64_t sigZExtra, sig256Z0; uint64_t uiA64, uiA0; uint64_t uiB64, uiB0; uint64_t uiC64, uiC0; - + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ uiA64 = a.v64; uiA0 = a.v0; uiB64 = b.v64; uiB0 = b.v0; uiC64 = c.v64; uiC0 = c.v0; - - return softfloat_mulAddF128(uiA64, uiA0, uiB64, uiB0, uiC64, uiC0, op, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF128UI64(uiA64); + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + signB = signF128UI64(uiB64); + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + signC = signF128UI64(uiC64) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF128UI64(uiC64); + sigC.v64 = fracF128UI64(uiC64); + sigC.v0 = uiC0; + signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))) { + goto propagateNaN_ABC; + } + magBits = expB | sigB.v64 | sigB.v0; + goto infProdArg; + } + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN_ABC; + magBits = expA | sigA.v64 | sigA.v0; + goto infProdArg; + } + if (expC == 0x7FFF) { + if (sigC.v64 | sigC.v0) { + uiZ.v64 = 0; + uiZ.v0 = 0; + goto propagateNaN_ZC; + } + uiZ.v64 = uiC64; + uiZ.v0 = uiC0; + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! (sigA.v64 | sigA.v0)) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! (sigB.v64 | sigB.v0)) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FFE; + sigA.v64 |= UINT64_C(0x0001000000000000); + sigB.v64 |= UINT64_C(0x0001000000000000); + sigA = softfloat_shortShiftLeft128(sigA.v64, sigA.v0, 8); + sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 15); + softfloat_mul128To256M(sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z); + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + shiftDist = 0; + if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { + --expZ; + shiftDist = -1; + } + if (! expC) { + if (! (sigC.v64 | sigC.v0)) { + shiftDist += 8; + goto sigZ; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigC.v64, sigC.v0); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC.v64 |= UINT64_C(0x0001000000000000); + sigC = softfloat_shortShiftLeft128(sigC.v64, sigC.v0, 8); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if (expDiff < 0) { + expZ = expC; + if ((signZ == signC) || (expDiff < -1)) { + shiftDist -= expDiff; + if (shiftDist) { + sigZ = softfloat_shiftRightJam128(sigZ.v64, sigZ.v0, shiftDist); + } + } else { + if (! shiftDist) { + x128 = softfloat_shortShiftRight128(sig256Z[indexWord(4, 1)], sig256Z[indexWord(4, 0)], 1); + sig256Z[indexWord(4, 1)] = (sigZ.v0<<63) | x128.v64; + sig256Z[indexWord(4, 0)] = x128.v0; + sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, 1); + sig256Z[indexWord(4, 3)] = sigZ.v64; + sig256Z[indexWord(4, 2)] = sigZ.v0; + } + } + } else { + if (shiftDist) softfloat_add256M(sig256Z, sig256Z, sig256Z); + if (! expDiff) { + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + } else { + sig256C[indexWord(4, 3)] = sigC.v64; + sig256C[indexWord(4, 2)] = sigC.v0; + sig256C[indexWord(4, 1)] = 0; + sig256C[indexWord(4, 0)] = 0; + softfloat_shiftRightJam256M(sig256C, expDiff, sig256C); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 8; + if (signZ == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + sigZ = softfloat_add128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0); + } else { + softfloat_add256M(sig256Z, sig256C, sig256Z); + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + } + if (sigZ.v64 & UINT64_C(0x0200000000000000)) { + ++expZ; + shiftDist = 9; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff < 0) { + signZ = signC; + if (expDiff < -1) { + sigZ = softfloat_sub128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0); + sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)]; + if (sigZExtra) { + sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, 0, 1); + } + if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { + --expZ; + shiftDist = 7; + } + goto shiftRightRoundPack; + } else { + sig256C[indexWord(4, 3)] = sigC.v64; + sig256C[indexWord(4, 2)] = sigC.v0; + sig256C[indexWord(4, 1)] = 0; + sig256C[indexWord(4, 0)] = 0; + softfloat_sub256M(sig256C, sig256Z, sig256Z); + } + } else if (! expDiff) { + sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, sigC.v64, sigC.v0); + if (! (sigZ.v64 | sigZ.v0) && ! sig256Z[indexWord(4, 1)] && ! sig256Z[indexWord(4, 0)]) { + goto completeCancellation; + } + sig256Z[indexWord(4, 3)] = sigZ.v64; + sig256Z[indexWord(4, 2)] = sigZ.v0; + if (sigZ.v64 & UINT64_C(0x8000000000000000)) { + signZ = ! signZ; + softfloat_sub256M(zero256, sig256Z, sig256Z); + } + } else { + softfloat_sub256M(sig256Z, sig256C, sig256Z); + if (1 < expDiff) { + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { + --expZ; + shiftDist = 7; + } + goto sigZ; + } + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + sigZExtra = sig256Z[indexWord(4, 1)]; + sig256Z0 = sig256Z[indexWord(4, 0)]; + if (sigZ.v64) { + if (sig256Z0) sigZExtra |= 1; + } else { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = sigZExtra; + sigZExtra = sig256Z0; + if (! sigZ.v64) { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = sigZExtra; + sigZExtra = 0; + if (! sigZ.v64) { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = 0; + } + } + } + shiftDist = softfloat_countLeadingZeros64(sigZ.v64); + expZ += 7 - shiftDist; + shiftDist = 15 - shiftDist; + if (0 < shiftDist) goto shiftRightRoundPack; + if (shiftDist) { + shiftDist = -shiftDist; + sigZ = softfloat_shortShiftLeft128(sigZ.v64, sigZ.v0, shiftDist); + x128 = softfloat_shortShiftLeft128(0, sigZExtra, shiftDist); + sigZ.v0 |= x128.v64; + sigZExtra = x128.v0; + } + goto roundPack; + } + sigZ: + sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)]; + shiftRightRoundPack: + sigZExtra = (uint64_t) (sigZ.v0<<(64 - shiftDist)) | (sigZExtra != 0); + sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, shiftDist); + roundPack: + return softfloat_roundPackToF128(signZ, expZ - 1, sigZ.v64, sigZ.v0, sigZExtra, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN_ABC: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + goto propagateNaN_ZC; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if ((sigC.v64 | sigC.v0) && expC == 0x7FFF) goto propagateNaN_ZC; + if (magBits) { + uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0); + uiZ.v0 = 0; + if (expC != 0x7FFF) return uiZ; + if (signZ == signC) return uiZ; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + propagateNaN_ZC: + uiZ = softfloat_propagateNaNF128UI(uiZ.v64, uiZ.v0, uiC64, uiC0, status); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ.v64 = uiC64; + uiZ.v0 = uiC0; + if (! (expC | sigC.v64 | sigC.v0) && (signZ != signC)) { + completeCancellation: + uiZ.v64 = packToF128UI64((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + uiZ.v0 = 0; + } + return uiZ; } diff --git a/bochs/cpu/softfloat3e/f128_roundToInt.c b/bochs/cpu/softfloat3e/f128_roundToInt.c index 5b8c19024a..c3b7287040 100644 --- a/bochs/cpu/softfloat3e/f128_roundToInt.c +++ b/bochs/cpu/softfloat3e/f128_roundToInt.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/f128_sqrt.c b/bochs/cpu/softfloat3e/f128_sqrt.c deleted file mode 100644 index 91c8548437..0000000000 --- a/bochs/cpu/softfloat3e/f128_sqrt.c +++ /dev/null @@ -1,193 +0,0 @@ -/*============================================================================ - -This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic -Package, Release 3e, by John R. Hauser. - -Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 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. - -=============================================================================*/ - -#include -#include -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float128_t f128_sqrt(float128_t a, struct softfloat_status_t *status) -{ - uint64_t uiA64, uiA0; - bool signA; - int32_t expA; - struct uint128 sigA, uiZ; - struct exp32_sig128 normExpSig; - int32_t expZ; - uint32_t sig32A, recipSqrt32, sig32Z; - struct uint128 rem; - uint32_t qs[3]; - uint32_t q; - uint64_t x64, sig64Z; - struct uint128 y, term; - uint64_t sigZExtra; - struct uint128 sigZ; - - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - uiA64 = a.v64; - uiA0 = a.v0; - signA = signF128UI64(uiA64); - expA = expF128UI64(uiA64); - sigA.v64 = fracF128UI64(uiA64); - sigA.v0 = uiA0; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (expA == 0x7FFF) { - if (sigA.v64 | sigA.v0) { - uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, 0, 0, status); - return uiZ; - } - if (! signA) return a; - goto invalid; - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (signA) { - if (! (expA | sigA.v64 | sigA.v0)) return a; - goto invalid; - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (! expA) { - if (! (sigA.v64 | sigA.v0)) return a; - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0); - expA = normExpSig.exp; - sigA = normExpSig.sig; - } - /*------------------------------------------------------------------------ - | (`sig32Z' is guaranteed to be a lower bound on the square root of - | `sig32A', which makes `sig32Z' also a lower bound on the square root of - | `sigA'.) - *------------------------------------------------------------------------*/ - expZ = ((expA - 0x3FFF)>>1) + 0x3FFE; - expA &= 1; - sigA.v64 |= UINT64_C(0x0001000000000000); - sig32A = sigA.v64>>17; - recipSqrt32 = softfloat_approxRecipSqrt32_1(expA, sig32A); - sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32; - if (expA) { - sig32Z >>= 1; - rem = softfloat_shortShiftLeft128(sigA.v64, sigA.v0, 12); - } else { - rem = softfloat_shortShiftLeft128(sigA.v64, sigA.v0, 13); - } - qs[2] = sig32Z; - rem.v64 -= (uint64_t) sig32Z * sig32Z; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - q = ((uint32_t) (rem.v64>>2) * (uint64_t) recipSqrt32)>>32; - x64 = (uint64_t) sig32Z<<32; - sig64Z = x64 + ((uint64_t) q<<3); - y = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); - /*------------------------------------------------------------------------ - | (Repeating this loop is a rare occurrence.) - *------------------------------------------------------------------------*/ - for (;;) { - term = softfloat_mul64ByShifted32To128(x64 + sig64Z, q); - rem = softfloat_sub128(y.v64, y.v0, term.v64, term.v0); - if (! (rem.v64 & UINT64_C(0x8000000000000000))) break; - --q; - sig64Z -= 1<<3; - } - qs[1] = q; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - q = ((rem.v64>>2) * recipSqrt32)>>32; - y = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); - sig64Z <<= 1; - /*------------------------------------------------------------------------ - | (Repeating this loop is a rare occurrence.) - *------------------------------------------------------------------------*/ - for (;;) { - term = softfloat_shortShiftLeft128(0, sig64Z, 32); - term = softfloat_add128(term.v64, term.v0, 0, (uint64_t) q<<6); - term = softfloat_mul128By32(term.v64, term.v0, q); - rem = softfloat_sub128(y.v64, y.v0, term.v64, term.v0); - if (! (rem.v64 & UINT64_C(0x8000000000000000))) break; - --q; - } - qs[0] = q; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - q = (((rem.v64>>2) * recipSqrt32)>>32) + 2; - sigZExtra = (uint64_t) ((uint64_t) q<<59); - term = softfloat_shortShiftLeft128(0, qs[1], 53); - sigZ = - softfloat_add128( - (uint64_t) qs[2]<<18, ((uint64_t) qs[0]<<24) + (q>>5), - term.v64, term.v0 - ); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if ((q & 0xF) <= 2) { - q &= ~3; - sigZExtra = (uint64_t) ((uint64_t) q<<59); - y = softfloat_shortShiftLeft128(sigZ.v64, sigZ.v0, 6); - y.v0 |= sigZExtra>>58; - term = softfloat_sub128(y.v64, y.v0, 0, q); - y = softfloat_mul64ByShifted32To128(term.v0, q); - term = softfloat_mul64ByShifted32To128(term.v64, q); - term = softfloat_add128(term.v64, term.v0, 0, y.v64); - rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 20); - term = softfloat_sub128(term.v64, term.v0, rem.v64, rem.v0); - /*-------------------------------------------------------------------- - | The concatenation of `term' and `y.v0' is now the negative remainder - | (3 words altogether). - *--------------------------------------------------------------------*/ - if (term.v64 & UINT64_C(0x8000000000000000)) { - sigZExtra |= 1; - } else { - if (term.v64 | term.v0 | y.v0) { - if (sigZExtra) { - --sigZExtra; - } else { - sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, 0, 1); - sigZExtra = ~0; - } - } - } - } - return softfloat_roundPackToF128(0, expZ, sigZ.v64, sigZ.v0, sigZExtra, status); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - invalid: - softfloat_raiseFlags(status, softfloat_flag_invalid); - uiZ.v64 = defaultNaNF128UI64; - uiZ.v0 = defaultNaNF128UI0; - return uiZ; -} diff --git a/bochs/cpu/softfloat3e/f128_to_extF80.c b/bochs/cpu/softfloat3e/f128_to_extF80.c index 357067ac31..40d45e5699 100644 --- a/bochs/cpu/softfloat3e/f128_to_extF80.c +++ b/bochs/cpu/softfloat3e/f128_to_extF80.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/f128_to_f32.c b/bochs/cpu/softfloat3e/f128_to_f32.c index caa60efc01..485d68a0ce 100644 --- a/bochs/cpu/softfloat3e/f128_to_f32.c +++ b/bochs/cpu/softfloat3e/f128_to_f32.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float32_t f128_to_f32(float128_t a, struct softfloat_status_t *status) +float32 f128_to_f32(float128_t a, struct softfloat_status_t *status) { uint64_t uiA64, uiA0; bool sign; diff --git a/bochs/cpu/softfloat3e/f128_to_f64.c b/bochs/cpu/softfloat3e/f128_to_f64.c index 7056406253..0809c7102c 100644 --- a/bochs/cpu/softfloat3e/f128_to_f64.c +++ b/bochs/cpu/softfloat3e/f128_to_f64.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float64_t f128_to_f64(float128_t a, struct softfloat_status_t *status) +float64 f128_to_f64(float128_t a, struct softfloat_status_t *status) { uint64_t uiA64, uiA0; bool sign; diff --git a/bochs/cpu/softfloat3e/f128_to_i32.c b/bochs/cpu/softfloat3e/f128_to_i32.c index 4bf149786f..68cf2b3a70 100644 --- a/bochs/cpu/softfloat3e/f128_to_i32.c +++ b/bochs/cpu/softfloat3e/f128_to_i32.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/f128_to_i64.c b/bochs/cpu/softfloat3e/f128_to_i64.c index 29e2ca93a8..288117561e 100644 --- a/bochs/cpu/softfloat3e/f128_to_i64.c +++ b/bochs/cpu/softfloat3e/f128_to_i64.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/f128_to_i64_r_minMag.c b/bochs/cpu/softfloat3e/f128_to_i64_r_minMag.c index 4c384c6282..edeccf1828 100644 --- a/bochs/cpu/softfloat3e/f128_to_i64_r_minMag.c +++ b/bochs/cpu/softfloat3e/f128_to_i64_r_minMag.c @@ -47,7 +47,7 @@ int64_t f128_to_i64_r_minMag(float128_t a, bool exact, struct softfloat_status_t uint64_t sig64, sig0; int32_t shiftDist; int8_t negShiftDist; - int64_t absZ; + uint64_t absZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ diff --git a/bochs/cpu/softfloat3e/f128_to_ui32.c b/bochs/cpu/softfloat3e/f128_to_ui32.c index c6c60333aa..7195d743fe 100644 --- a/bochs/cpu/softfloat3e/f128_to_ui32.c +++ b/bochs/cpu/softfloat3e/f128_to_ui32.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/f128_to_ui64.c b/bochs/cpu/softfloat3e/f128_to_ui64.c index 82f1662323..989bbc046d 100644 --- a/bochs/cpu/softfloat3e/f128_to_ui64.c +++ b/bochs/cpu/softfloat3e/f128_to_ui64.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/f16_addsub.c b/bochs/cpu/softfloat3e/f16_addsub.c index 90d45b9e82..0353e054cd 100644 --- a/bochs/cpu/softfloat3e/f16_addsub.c +++ b/bochs/cpu/softfloat3e/f16_addsub.c @@ -38,10 +38,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "internals.h" #include "softfloat.h" -extern float16_t softfloat_addMagsF16(uint16_t, uint16_t, struct softfloat_status_t *); -extern float16_t softfloat_subMagsF16(uint16_t, uint16_t, struct softfloat_status_t *); +extern float16 softfloat_addMagsF16(uint16_t, uint16_t, struct softfloat_status_t *); +extern float16 softfloat_subMagsF16(uint16_t, uint16_t, struct softfloat_status_t *); -float16_t f16_add(float16_t a, float16_t b, struct softfloat_status_t *status) +float16 f16_add(float16 a, float16 b, struct softfloat_status_t *status) { if (signF16UI((uint16_t) a ^ (uint16_t) b)) { return softfloat_subMagsF16(a, b, status); @@ -50,7 +50,7 @@ float16_t f16_add(float16_t a, float16_t b, struct softfloat_status_t *status) } } -float16_t f16_sub(float16_t a, float16_t b, struct softfloat_status_t *status) +float16 f16_sub(float16 a, float16 b, struct softfloat_status_t *status) { if (signF16UI((uint16_t) a ^ (uint16_t) b)) { return softfloat_addMagsF16(a, b, status); diff --git a/bochs/cpu/softfloat3e/f16_class.c b/bochs/cpu/softfloat3e/f16_class.c index 2d3dd6b386..b375c1544e 100644 --- a/bochs/cpu/softfloat3e/f16_class.c +++ b/bochs/cpu/softfloat3e/f16_class.c @@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "internals.h" #include "softfloat.h" -softfloat_class_t f16_class(float16_t a) +softfloat_class_t f16_class(float16 a) { bool signA; int8_t expA; diff --git a/bochs/cpu/softfloat3e/f16_compare.c b/bochs/cpu/softfloat3e/f16_compare.c index 42cd257e9f..a14eb81040 100644 --- a/bochs/cpu/softfloat3e/f16_compare.c +++ b/bochs/cpu/softfloat3e/f16_compare.c @@ -46,7 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | value `b', or 'float_relation_unordered' otherwise. *----------------------------------------------------------------------------*/ -int f16_compare(float16_t a, float16_t b, bool quiet, struct softfloat_status_t *status) +int f16_compare(float16 a, float16 b, bool quiet, struct softfloat_status_t *status) { softfloat_class_t aClass; softfloat_class_t bClass; diff --git a/bochs/cpu/softfloat3e/f16_div.c b/bochs/cpu/softfloat3e/f16_div.c index 79d30a18e1..c91760b03b 100644 --- a/bochs/cpu/softfloat3e/f16_div.c +++ b/bochs/cpu/softfloat3e/f16_div.c @@ -44,7 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. extern const uint16_t softfloat_approxRecip_1k0s[]; extern const uint16_t softfloat_approxRecip_1k1s[]; -float16_t f16_div(float16_t a, float16_t b, struct softfloat_status_t *status) +float16 f16_div(float16 a, float16 b, struct softfloat_status_t *status) { bool signA; int8_t expA; diff --git a/bochs/cpu/softfloat3e/f16_getExp.c b/bochs/cpu/softfloat3e/f16_getExp.c index a2687c3768..6efc28c94f 100644 --- a/bochs/cpu/softfloat3e/f16_getExp.c +++ b/bochs/cpu/softfloat3e/f16_getExp.c @@ -46,7 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ -float16_t f16_getExp(float16_t a, struct softfloat_status_t *status) +float16 f16_getExp(float16 a, struct softfloat_status_t *status) { int8_t expA; uint16_t sigA; @@ -57,12 +57,12 @@ float16_t f16_getExp(float16_t a, struct softfloat_status_t *status) if (expA == 0x1F) { if (sigA) return softfloat_propagateNaNF16UI(a, 0, status); - return packToF32UI(0, 0x1F, 0); + return packToF16UI(0, 0x1F, 0); } if (! expA) { if (! sigA || softfloat_denormalsAreZeros(status)) - return packToF32UI(1, 0x1F, 0); + return packToF16UI(1, 0x1F, 0); softfloat_raiseFlags(status, softfloat_flag_denormal); normExpSig = softfloat_normSubnormalF16Sig(sigA); diff --git a/bochs/cpu/softfloat3e/f16_getMant.c b/bochs/cpu/softfloat3e/f16_getMant.c index 68db0ad44c..4c39cac5b2 100644 --- a/bochs/cpu/softfloat3e/f16_getMant.c +++ b/bochs/cpu/softfloat3e/f16_getMant.c @@ -47,7 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | Arithmetic. *----------------------------------------------------------------------------*/ -float16_t f16_getMant(float16_t a, softfloat_status_t *status, int sign_ctrl, int interv) +float16 f16_getMant(float16 a, softfloat_status_t *status, int sign_ctrl, int interv) { bool signA; int8_t expA; diff --git a/bochs/cpu/softfloat3e/f16_minmax.c b/bochs/cpu/softfloat3e/f16_minmax.c index cf1e979e30..3aa1454f0c 100644 --- a/bochs/cpu/softfloat3e/f16_minmax.c +++ b/bochs/cpu/softfloat3e/f16_minmax.c @@ -43,7 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | smaller of them. *----------------------------------------------------------------------------*/ -float16_t f16_min(float16_t a, float16_t b, struct softfloat_status_t *status) +float16 f16_min(float16 a, float16 b, struct softfloat_status_t *status) { if (softfloat_denormalsAreZeros(status)) { a = f16_denormal_to_zero(a); @@ -58,7 +58,7 @@ float16_t f16_min(float16_t a, float16_t b, struct softfloat_status_t *status) | larger of them. *----------------------------------------------------------------------------*/ -float16_t f16_max(float16_t a, float16_t b, struct softfloat_status_t *status) +float16 f16_max(float16 a, float16 b, struct softfloat_status_t *status) { if (softfloat_denormalsAreZeros(status)) { a = f16_denormal_to_zero(a); diff --git a/bochs/cpu/softfloat3e/f16_mul.c b/bochs/cpu/softfloat3e/f16_mul.c index 0850275d80..2e7e74826a 100644 --- a/bochs/cpu/softfloat3e/f16_mul.c +++ b/bochs/cpu/softfloat3e/f16_mul.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -float16_t f16_mul(float16_t a, float16_t b, struct softfloat_status_t *status) +float16 f16_mul(float16 a, float16 b, struct softfloat_status_t *status) { bool signA; int8_t expA; diff --git a/bochs/cpu/softfloat3e/f16_mulAdd.c b/bochs/cpu/softfloat3e/f16_mulAdd.c index 77fdc7e121..0e630a9b7c 100644 --- a/bochs/cpu/softfloat3e/f16_mulAdd.c +++ b/bochs/cpu/softfloat3e/f16_mulAdd.c @@ -35,9 +35,198 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" +#include "specialize.h" -float16_t f16_mulAdd(float16_t a, float16_t b, float16_t c, uint8_t op, struct softfloat_status_t *status) +float16 f16_mulAdd(float16 a, float16 b, float16 c, uint8_t op, struct softfloat_status_t *status) { - return softfloat_mulAddF16(a, b, c, op, status); + bool signA; + int8_t expA; + uint16_t sigA; + bool signB; + int8_t expB; + uint16_t sigB; + bool signC; + int8_t expC; + uint16_t sigC; + bool signProd; + uint16_t magBits, uiA, uiB, uiC, uiZ; + struct exp8_sig16 normExpSig; + int8_t expProd; + uint32_t sigProd; + bool signZ; + int8_t expZ; + uint16_t sigZ; + int8_t expDiff; + uint32_t sig32Z, sig32C; + int8_t shiftDist; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA = a; + uiB = b; + uiC = c; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(uiA); + expA = expF16UI(uiA); + sigA = fracF16UI(uiA); + signB = signF16UI(uiB); + expB = expF16UI(uiB); + sigB = fracF16UI(uiB); + signC = signF16UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF16UI(uiC); + sigC = fracF16UI(uiC); + signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + bool aisNaN = (expA == 0x1F) && sigA; + bool bisNaN = (expB == 0x1F) && sigB; + bool cisNaN = (expC == 0x1F) && sigC; + if (aisNaN | bisNaN | cisNaN) { + uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF16UI(uiA, uiB, status) : 0; + return softfloat_propagateNaNF16UI(uiZ, uiC, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + if (!expC) sigC = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x1F) { + magBits = expB | sigB; + goto infProdArg; + } + if (expB == 0x1F) { + magBits = expA | sigA; + goto infProdArg; + } + if (expC == 0x1F) { + if ((sigA && !expA) || (sigB && !expB)) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + return packToF16UI(signC, 0x1F, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expProd = expA + expB - 0xE; + sigA = (sigA | 0x0400)<<4; + sigB = (sigB | 0x0400)<<4; + sigProd = (uint32_t) sigA * sigB; + if (sigProd < 0x20000000) { + --expProd; + sigProd <<= 1; + } + signZ = signProd; + if (! expC) { + if (! sigC) { + expZ = expProd - 1; + sigZ = sigProd>>15 | ((sigProd & 0x7FFF) != 0); + goto roundPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigC); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | 0x0400)<<3; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expProd - expC; + if (signProd == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + expZ = expC; + sigZ = sigC + softfloat_shiftRightJam32(sigProd, 16 - expDiff); + } else { + expZ = expProd; + sig32Z = sigProd + softfloat_shiftRightJam32((uint32_t) sigC<<16, expDiff); + sigZ = sig32Z>>16 | ((sig32Z & 0xFFFF) != 0); + } + if (sigZ < 0x4000) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig32C = (uint32_t) sigC<<16; + if (expDiff < 0) { + signZ = signC; + expZ = expC; + sig32Z = sig32C - softfloat_shiftRightJam32(sigProd, -expDiff); + } else if (! expDiff) { + expZ = expProd; + sig32Z = sigProd - sig32C; + if (! sig32Z) goto completeCancellation; + if (sig32Z & 0x80000000) { + signZ = ! signZ; + sig32Z = -sig32Z; + } + } else { + expZ = expProd; + sig32Z = sigProd - softfloat_shiftRightJam32(sig32C, expDiff); + } + shiftDist = softfloat_countLeadingZeros32(sig32Z) - 1; + expZ -= shiftDist; + shiftDist -= 16; + if (shiftDist < 0) { + sigZ = sig32Z>>(-shiftDist) | ((uint32_t) (sig32Z<<(shiftDist & 31)) != 0); + } else { + sigZ = (uint16_t) sig32Z< #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float32_t f32_mul(float32_t a, float32_t b, struct softfloat_status_t *status) +float32 f32_mul(float32 a, float32 b, struct softfloat_status_t *status) { bool signA; int16_t expA; diff --git a/bochs/cpu/softfloat3e/f32_mulAdd.c b/bochs/cpu/softfloat3e/f32_mulAdd.c index 92c73c6152..101b20f18b 100644 --- a/bochs/cpu/softfloat3e/f32_mulAdd.c +++ b/bochs/cpu/softfloat3e/f32_mulAdd.c @@ -35,9 +35,199 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" +#include "specialize.h" -float32_t f32_mulAdd(float32_t a, float32_t b, float32_t c, uint8_t op, struct softfloat_status_t *status) +float32 f32_mulAdd(float32 a, float32 b, float32 c, uint8_t op, struct softfloat_status_t *status) { - return softfloat_mulAddF32(a, b, c, op, status); + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + bool signC; + int16_t expC; + uint32_t sigC; + bool signProd; + uint32_t magBits, uiA, uiB, uiC, uiZ; + struct exp16_sig32 normExpSig; + int16_t expProd; + uint64_t sigProd; + bool signZ; + int16_t expZ; + uint32_t sigZ; + int16_t expDiff; + uint64_t sig64Z, sig64C; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA = a; + uiB = b; + uiC = c; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(uiA); + expA = expF32UI(uiA); + sigA = fracF32UI(uiA); + signB = signF32UI(uiB); + expB = expF32UI(uiB); + sigB = fracF32UI(uiB); + signC = signF32UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF32UI(uiC); + sigC = fracF32UI(uiC); + signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + bool aisNaN = (expA == 0xFF) && sigA; + bool bisNaN = (expB == 0xFF) && sigB; + bool cisNaN = (expC == 0xFF) && sigC; + if (aisNaN | bisNaN | cisNaN) { + uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF32UI(uiA, uiB, status) : 0; + return softfloat_propagateNaNF32UI(uiZ, uiC, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + if (!expC) sigC = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + magBits = expB | sigB; + goto infProdArg; + } + if (expB == 0xFF) { + magBits = expA | sigA; + goto infProdArg; + } + if (expC == 0xFF) { + if ((sigA && !expA) || (sigB && !expB)) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + return packToF32UI(signC, 0xFF, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expProd = expA + expB - 0x7E; + sigA = (sigA | 0x00800000)<<7; + sigB = (sigB | 0x00800000)<<7; + sigProd = (uint64_t) sigA * sigB; + if (sigProd < UINT64_C(0x2000000000000000)) { + --expProd; + sigProd <<= 1; + } + signZ = signProd; + if (! expC) { + if (! sigC) { + expZ = expProd - 1; + sigZ = softfloat_shortShiftRightJam64(sigProd, 31); + goto roundPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigC); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | 0x00800000)<<6; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expProd - expC; + if (signProd == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + expZ = expC; + sigZ = sigC + softfloat_shiftRightJam64(sigProd, 32 - expDiff); + } else { + expZ = expProd; + sig64Z = sigProd + softfloat_shiftRightJam64((uint64_t) sigC<<32, expDiff); + sigZ = softfloat_shortShiftRightJam64(sig64Z, 32); + } + if (sigZ < 0x40000000) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64C = (uint64_t) sigC<<32; + if (expDiff < 0) { + signZ = signC; + expZ = expC; + sig64Z = sig64C - softfloat_shiftRightJam64(sigProd, -expDiff); + } else if (! expDiff) { + expZ = expProd; + sig64Z = sigProd - sig64C; + if (! sig64Z) goto completeCancellation; + if (sig64Z & UINT64_C(0x8000000000000000)) { + signZ = ! signZ; + sig64Z = -sig64Z; + } + } else { + expZ = expProd; + sig64Z = sigProd - softfloat_shiftRightJam64(sig64C, expDiff); + } + shiftDist = softfloat_countLeadingZeros64(sig64Z) - 1; + expZ -= shiftDist; + shiftDist -= 32; + if (shiftDist < 0) { + sigZ = softfloat_shortShiftRightJam64(sig64Z, -shiftDist); + } else { + sigZ = (uint32_t) sig64Z< #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float32_t f32_sqrt(float32_t a, struct softfloat_status_t *status) +float32 f32_sqrt(float32 a, struct softfloat_status_t *status) { bool signA; int16_t expA; diff --git a/bochs/cpu/softfloat3e/f32_to_extF80.c b/bochs/cpu/softfloat3e/f32_to_extF80.c index 6b7ce1b50e..095f85165d 100644 --- a/bochs/cpu/softfloat3e/f32_to_extF80.c +++ b/bochs/cpu/softfloat3e/f32_to_extF80.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -extFloat80_t f32_to_extF80(float32_t a, struct softfloat_status_t *status) +extFloat80_t f32_to_extF80(float32 a, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f32_to_f128.c b/bochs/cpu/softfloat3e/f32_to_f128.c index 9b105f39c3..6d3fafec29 100644 --- a/bochs/cpu/softfloat3e/f32_to_f128.c +++ b/bochs/cpu/softfloat3e/f32_to_f128.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -float128_t f32_to_f128(float32_t a, struct softfloat_status_t *status) +float128_t f32_to_f128(float32 a, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f32_to_f16.c b/bochs/cpu/softfloat3e/f32_to_f16.c index 59402398d3..9253a958a5 100644 --- a/bochs/cpu/softfloat3e/f32_to_f16.c +++ b/bochs/cpu/softfloat3e/f32_to_f16.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -float16_t f32_to_f16(float32_t a, struct softfloat_status_t *status) +float16 f32_to_f16(float32 a, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f32_to_f64.c b/bochs/cpu/softfloat3e/f32_to_f64.c index be1e532559..28ebb61b6c 100644 --- a/bochs/cpu/softfloat3e/f32_to_f64.c +++ b/bochs/cpu/softfloat3e/f32_to_f64.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -float64_t f32_to_f64(float32_t a, struct softfloat_status_t *status) +float64 f32_to_f64(float32 a, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f32_to_i32.c b/bochs/cpu/softfloat3e/f32_to_i32.c index 59ff442b71..2b3df52a3c 100644 --- a/bochs/cpu/softfloat3e/f32_to_i32.c +++ b/bochs/cpu/softfloat3e/f32_to_i32.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -int32_t f32_to_i32(float32_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +int32_t f32_to_i32(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f32_to_i32_r_minMag.c b/bochs/cpu/softfloat3e/f32_to_i32_r_minMag.c index 0c2d68365b..d83c7bcaa0 100644 --- a/bochs/cpu/softfloat3e/f32_to_i32_r_minMag.c +++ b/bochs/cpu/softfloat3e/f32_to_i32_r_minMag.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -int32_t f32_to_i32_r_minMag(float32_t a, bool exact, struct softfloat_status_t *status) +int32_t f32_to_i32_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) { int16_t exp; uint32_t sig; diff --git a/bochs/cpu/softfloat3e/f32_to_i64.c b/bochs/cpu/softfloat3e/f32_to_i64.c index d2b2deb4b5..8f715c4e24 100644 --- a/bochs/cpu/softfloat3e/f32_to_i64.c +++ b/bochs/cpu/softfloat3e/f32_to_i64.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -int64_t f32_to_i64(float32_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +int64_t f32_to_i64(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f32_to_i64_r_minMag.c b/bochs/cpu/softfloat3e/f32_to_i64_r_minMag.c index f600f23cf9..ab813b9df6 100644 --- a/bochs/cpu/softfloat3e/f32_to_i64_r_minMag.c +++ b/bochs/cpu/softfloat3e/f32_to_i64_r_minMag.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -int64_t f32_to_i64_r_minMag(float32_t a, bool exact, struct softfloat_status_t *status) +int64_t f32_to_i64_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) { int16_t exp; uint32_t sig; diff --git a/bochs/cpu/softfloat3e/f32_to_ui32.c b/bochs/cpu/softfloat3e/f32_to_ui32.c index d70768f55f..5a8d574142 100644 --- a/bochs/cpu/softfloat3e/f32_to_ui32.c +++ b/bochs/cpu/softfloat3e/f32_to_ui32.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -uint32_t f32_to_ui32(float32_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +uint32_t f32_to_ui32(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f32_to_ui32_r_minMag.c b/bochs/cpu/softfloat3e/f32_to_ui32_r_minMag.c index 1d5ec62ca7..26bdae31f2 100644 --- a/bochs/cpu/softfloat3e/f32_to_ui32_r_minMag.c +++ b/bochs/cpu/softfloat3e/f32_to_ui32_r_minMag.c @@ -40,7 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -uint32_t f32_to_ui32_r_minMag(float32_t a, bool exact, struct softfloat_status_t *status) +uint32_t f32_to_ui32_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) { int16_t exp; uint32_t sig; diff --git a/bochs/cpu/softfloat3e/f32_to_ui64.c b/bochs/cpu/softfloat3e/f32_to_ui64.c index 433e7cee60..c5de58b23b 100644 --- a/bochs/cpu/softfloat3e/f32_to_ui64.c +++ b/bochs/cpu/softfloat3e/f32_to_ui64.c @@ -37,10 +37,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -uint64_t f32_to_ui64(float32_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +uint64_t f32_to_ui64(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f32_to_ui64_r_minMag.c b/bochs/cpu/softfloat3e/f32_to_ui64_r_minMag.c index ec0f505129..71227e4877 100644 --- a/bochs/cpu/softfloat3e/f32_to_ui64_r_minMag.c +++ b/bochs/cpu/softfloat3e/f32_to_ui64_r_minMag.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -uint64_t f32_to_ui64_r_minMag(float32_t a, bool exact, struct softfloat_status_t *status) +uint64_t f32_to_ui64_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) { int16_t exp; uint32_t sig; diff --git a/bochs/cpu/softfloat3e/f64_addsub.c b/bochs/cpu/softfloat3e/f64_addsub.c index 865059dcb6..6c5acb4f77 100644 --- a/bochs/cpu/softfloat3e/f64_addsub.c +++ b/bochs/cpu/softfloat3e/f64_addsub.c @@ -38,10 +38,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "internals.h" #include "softfloat.h" -extern float64_t softfloat_addMagsF64(uint64_t, uint64_t, bool, struct softfloat_status_t *); -extern float64_t softfloat_subMagsF64(uint64_t, uint64_t, bool, struct softfloat_status_t *); +extern float64 softfloat_addMagsF64(uint64_t, uint64_t, bool, struct softfloat_status_t *); +extern float64 softfloat_subMagsF64(uint64_t, uint64_t, bool, struct softfloat_status_t *); -float64_t f64_add(float64_t a, float64_t b, struct softfloat_status_t *status) +float64 f64_add(float64 a, float64 b, struct softfloat_status_t *status) { bool signA; bool signB; @@ -55,7 +55,7 @@ float64_t f64_add(float64_t a, float64_t b, struct softfloat_status_t *status) } } -float64_t f64_sub(float64_t a, float64_t b, struct softfloat_status_t *status) +float64 f64_sub(float64 a, float64 b, struct softfloat_status_t *status) { bool signA; bool signB; diff --git a/bochs/cpu/softfloat3e/f64_class.c b/bochs/cpu/softfloat3e/f64_class.c index 43970e57de..1d44a63518 100644 --- a/bochs/cpu/softfloat3e/f64_class.c +++ b/bochs/cpu/softfloat3e/f64_class.c @@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "internals.h" #include "softfloat.h" -softfloat_class_t f64_class(float64_t a) +softfloat_class_t f64_class(float64 a) { bool signA; int16_t expA; diff --git a/bochs/cpu/softfloat3e/f64_compare.c b/bochs/cpu/softfloat3e/f64_compare.c index 8ee6710ec4..aca292fdaf 100644 --- a/bochs/cpu/softfloat3e/f64_compare.c +++ b/bochs/cpu/softfloat3e/f64_compare.c @@ -46,7 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | value `b', or 'float_relation_unordered' otherwise. *----------------------------------------------------------------------------*/ -int f64_compare(float64_t a, float64_t b, bool quiet, struct softfloat_status_t *status) +int f64_compare(float64 a, float64 b, bool quiet, struct softfloat_status_t *status) { softfloat_class_t aClass; softfloat_class_t bClass; diff --git a/bochs/cpu/softfloat3e/f64_div.c b/bochs/cpu/softfloat3e/f64_div.c index 949b4972e8..89f74f1b10 100644 --- a/bochs/cpu/softfloat3e/f64_div.c +++ b/bochs/cpu/softfloat3e/f64_div.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float64_t f64_div(float64_t a, float64_t b, struct softfloat_status_t *status) +float64 f64_div(float64 a, float64 b, struct softfloat_status_t *status) { bool signA; int16_t expA; diff --git a/bochs/cpu/softfloat3e/f64_frc.c b/bochs/cpu/softfloat3e/f64_frc.c index 1a741d2337..e39847665e 100644 --- a/bochs/cpu/softfloat3e/f64_frc.c +++ b/bochs/cpu/softfloat3e/f64_frc.c @@ -46,7 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ -float64_t f64_frc(float64_t a, softfloat_status_t *status) +float64 f64_frc(float64 a, softfloat_status_t *status) { int roundingMode = softfloat_getRoundingMode(status); diff --git a/bochs/cpu/softfloat3e/f64_getExp.c b/bochs/cpu/softfloat3e/f64_getExp.c index 6fd98e9813..b76cc996d5 100644 --- a/bochs/cpu/softfloat3e/f64_getExp.c +++ b/bochs/cpu/softfloat3e/f64_getExp.c @@ -46,7 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ -float64_t f64_getExp(float64_t a, struct softfloat_status_t *status) +float64 f64_getExp(float64 a, struct softfloat_status_t *status) { int16_t expA; uint64_t sigA; diff --git a/bochs/cpu/softfloat3e/f64_getMant.c b/bochs/cpu/softfloat3e/f64_getMant.c index 4571f4526b..459200cacf 100644 --- a/bochs/cpu/softfloat3e/f64_getMant.c +++ b/bochs/cpu/softfloat3e/f64_getMant.c @@ -47,7 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | Arithmetic. *----------------------------------------------------------------------------*/ -float64_t f64_getMant(float64_t a, softfloat_status_t *status, int sign_ctrl, int interv) +float64 f64_getMant(float64 a, softfloat_status_t *status, int sign_ctrl, int interv) { bool signA; int16_t expA; diff --git a/bochs/cpu/softfloat3e/f64_minmax.c b/bochs/cpu/softfloat3e/f64_minmax.c index d81d136b1d..e74841dfa7 100644 --- a/bochs/cpu/softfloat3e/f64_minmax.c +++ b/bochs/cpu/softfloat3e/f64_minmax.c @@ -43,7 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | smaller of them. *----------------------------------------------------------------------------*/ -float64_t f64_min(float64_t a, float64_t b, struct softfloat_status_t *status) +float64 f64_min(float64 a, float64 b, struct softfloat_status_t *status) { if (softfloat_denormalsAreZeros(status)) { a = f64_denormal_to_zero(a); @@ -58,7 +58,7 @@ float64_t f64_min(float64_t a, float64_t b, struct softfloat_status_t *status) | larger of them. *----------------------------------------------------------------------------*/ -float64_t f64_max(float64_t a, float64_t b, struct softfloat_status_t *status) +float64 f64_max(float64 a, float64 b, struct softfloat_status_t *status) { if (softfloat_denormalsAreZeros(status)) { a = f64_denormal_to_zero(a); diff --git a/bochs/cpu/softfloat3e/f64_mul.c b/bochs/cpu/softfloat3e/f64_mul.c index 02a4e9215b..c1e98f2b6d 100644 --- a/bochs/cpu/softfloat3e/f64_mul.c +++ b/bochs/cpu/softfloat3e/f64_mul.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float64_t f64_mul(float64_t a, float64_t b, struct softfloat_status_t *status) +float64 f64_mul(float64 a, float64 b, struct softfloat_status_t *status) { bool signA; int16_t expA; diff --git a/bochs/cpu/softfloat3e/f64_mulAdd.c b/bochs/cpu/softfloat3e/f64_mulAdd.c index db3d143c12..9623b49800 100644 --- a/bochs/cpu/softfloat3e/f64_mulAdd.c +++ b/bochs/cpu/softfloat3e/f64_mulAdd.c @@ -35,9 +35,209 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" +#include "specialize.h" -float64_t f64_mulAdd(float64_t a, float64_t b, float64_t c, uint8_t op, struct softfloat_status_t *status) +float64 f64_mulAdd(float64 a, float64 b, float64 c, uint8_t op, struct softfloat_status_t *status) { - return softfloat_mulAddF64(a, b, c, op, status); + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + bool signC; + int16_t expC; + uint64_t sigC; + bool signZ; + uint64_t magBits, uiA, uiB, uiC, uiZ; + struct exp16_sig64 normExpSig; + int16_t expZ; + struct uint128 sig128Z; + uint64_t sigZ; + int16_t expDiff; + struct uint128 sig128C; + int8_t shiftDist; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA = a; + uiB = b; + uiC = c; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(uiA); + expA = expF64UI(uiA); + sigA = fracF64UI(uiA); + signB = signF64UI(uiB); + expB = expF64UI(uiB); + sigB = fracF64UI(uiB); + signC = signF64UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF64UI(uiC); + sigC = fracF64UI(uiC); + signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + bool aisNaN = (expA == 0x7FF) && sigA; + bool bisNaN = (expB == 0x7FF) && sigB; + bool cisNaN = (expC == 0x7FF) && sigC; + if (aisNaN | bisNaN | cisNaN) { + uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF64UI(uiA, uiB, status) : 0; + return softfloat_propagateNaNF64UI(uiZ, uiC, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + if (!expC) sigC = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + magBits = expB | sigB; + goto infProdArg; + } + if (expB == 0x7FF) { + magBits = expA | sigA; + goto infProdArg; + } + if (expC == 0x7FF) { + if ((sigA && !expA) || (sigB && !expB)) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + return packToF64UI(signC, 0x7FF, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FE; + sigA = (sigA | UINT64_C(0x0010000000000000))<<10; + sigB = (sigB | UINT64_C(0x0010000000000000))<<10; + sig128Z = softfloat_mul64To128(sigA, sigB); + if (sig128Z.v64 < UINT64_C(0x2000000000000000)) { + --expZ; + sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0); + } + if (! expC) { + if (! sigC) { + --expZ; + sigZ = sig128Z.v64<<1 | (sig128Z.v0 != 0); + goto roundPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigC); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | UINT64_C(0x0010000000000000))<<9; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if (expDiff < 0) { + expZ = expC; + if ((signZ == signC) || (expDiff < -1)) { + sig128Z.v64 = softfloat_shiftRightJam64(sig128Z.v64, -expDiff); + } else { + sig128Z = softfloat_shortShiftRightJam128(sig128Z.v64, sig128Z.v0, 1); + } + } else if (expDiff) { + sig128C = softfloat_shiftRightJam128(sigC, 0, expDiff); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signZ == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + sigZ = (sigC + sig128Z.v64) | (sig128Z.v0 != 0); + } else { + sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0); + sigZ = sig128Z.v64 | (sig128Z.v0 != 0); + } + if (sigZ < UINT64_C(0x4000000000000000)) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff < 0) { + signZ = signC; + sig128Z = softfloat_sub128(sigC, 0, sig128Z.v64, sig128Z.v0); + } else if (! expDiff) { + sig128Z.v64 = sig128Z.v64 - sigC; + if (! (sig128Z.v64 | sig128Z.v0)) goto completeCancellation; + if (sig128Z.v64 & UINT64_C(0x8000000000000000)) { + signZ = ! signZ; + sig128Z = softfloat_sub128(0, 0, sig128Z.v64, sig128Z.v0); + } + } else { + sig128Z = softfloat_sub128(sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0); + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (! sig128Z.v64) { + expZ -= 64; + sig128Z.v64 = sig128Z.v0; + sig128Z.v0 = 0; + } + shiftDist = softfloat_countLeadingZeros64(sig128Z.v64) - 1; + expZ -= shiftDist; + if (shiftDist < 0) { + sigZ = softfloat_shortShiftRightJam64(sig128Z.v64, -shiftDist); + } else { + sig128Z = softfloat_shortShiftLeft128(sig128Z.v64, sig128Z.v0, shiftDist); + sigZ = sig128Z.v64; + } + sigZ |= (sig128Z.v0 != 0); + } + roundPack: + return softfloat_roundPackToF64(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if (magBits) { + uiZ = packToF64UI(signZ, 0x7FF, 0); + if (signZ == signC || expC != 0x7FF) { + if ((sigA && !expA) || (sigB && !expB) || (sigC && !expC)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return uiZ; + } + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ = defaultNaNF64UI; + return softfloat_propagateNaNF64UI(uiZ, uiC, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ = packToF64UI(signC, expC, sigC); + if (!expC && sigC) { + /* Exact zero plus a denormal */ + softfloat_raiseFlags(status, softfloat_flag_denormal); + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(signC, 0, 0); + } + } + if (! (expC | sigC) && (signZ != signC)) { + completeCancellation: + uiZ = packToF64UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + return uiZ; } diff --git a/bochs/cpu/softfloat3e/f64_range.c b/bochs/cpu/softfloat3e/f64_range.c index fe4aa3e02b..1025f474dc 100644 --- a/bochs/cpu/softfloat3e/f64_range.c +++ b/bochs/cpu/softfloat3e/f64_range.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -float64_t f64_range(float64_t a, float64_t b, bool is_max, bool is_abs, int sign_ctrl, softfloat_status_t *status) +float64 f64_range(float64 a, float64 b, bool is_max, bool is_abs, int sign_ctrl, softfloat_status_t *status) { bool signA; int16_t expA; @@ -103,7 +103,7 @@ float64_t f64_range(float64_t a, float64_t b, bool is_max, bool is_abs, int sign z = signA ? b : a; } } else { - float64_t tmp_a = a, tmp_b = b; + float64 tmp_a = a, tmp_b = b; if (is_abs) { tmp_a = tmp_a & ~UINT64_C(0x8000000000000000); // clear the sign bit tmp_b = tmp_b & ~UINT64_C(0x8000000000000000); diff --git a/bochs/cpu/softfloat3e/f64_roundToInt.c b/bochs/cpu/softfloat3e/f64_roundToInt.c index 591f1574f1..3c5f7fb8c2 100644 --- a/bochs/cpu/softfloat3e/f64_roundToInt.c +++ b/bochs/cpu/softfloat3e/f64_roundToInt.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -float64_t f64_roundToInt(float64_t a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +float64 f64_roundToInt(float64 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) { int16_t exp; int64_t frac; diff --git a/bochs/cpu/softfloat3e/f64_scalef.c b/bochs/cpu/softfloat3e/f64_scalef.c index 068466738b..7a552ccc3b 100644 --- a/bochs/cpu/softfloat3e/f64_scalef.c +++ b/bochs/cpu/softfloat3e/f64_scalef.c @@ -49,7 +49,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ -float64_t f64_scalef(float64_t a, float64_t b, struct softfloat_status_t *status) +float64 f64_scalef(float64 a, float64 b, struct softfloat_status_t *status) { bool signA; int16_t expA; diff --git a/bochs/cpu/softfloat3e/f64_sqrt.c b/bochs/cpu/softfloat3e/f64_sqrt.c index 16beed8368..d3ea81af86 100644 --- a/bochs/cpu/softfloat3e/f64_sqrt.c +++ b/bochs/cpu/softfloat3e/f64_sqrt.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float64_t f64_sqrt(float64_t a, struct softfloat_status_t *status) +float64 f64_sqrt(float64 a, struct softfloat_status_t *status) { bool signA; int16_t expA; diff --git a/bochs/cpu/softfloat3e/f64_to_extF80.c b/bochs/cpu/softfloat3e/f64_to_extF80.c index 6fab74d0b9..9284d69bbb 100644 --- a/bochs/cpu/softfloat3e/f64_to_extF80.c +++ b/bochs/cpu/softfloat3e/f64_to_extF80.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -extFloat80_t f64_to_extF80(float64_t a, struct softfloat_status_t *status) +extFloat80_t f64_to_extF80(float64 a, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f64_to_f128.c b/bochs/cpu/softfloat3e/f64_to_f128.c index b6472fe4a6..cfae728249 100644 --- a/bochs/cpu/softfloat3e/f64_to_f128.c +++ b/bochs/cpu/softfloat3e/f64_to_f128.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float128_t f64_to_f128(float64_t a, struct softfloat_status_t *status) +float128_t f64_to_f128(float64 a, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f64_to_f16.c b/bochs/cpu/softfloat3e/f64_to_f16.c index 6f4e4bdee0..fe8dea057a 100644 --- a/bochs/cpu/softfloat3e/f64_to_f16.c +++ b/bochs/cpu/softfloat3e/f64_to_f16.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float16_t f64_to_f16(float64_t a, struct softfloat_status_t *status) +float16 f64_to_f16(float64 a, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f64_to_f32.c b/bochs/cpu/softfloat3e/f64_to_f32.c index 7fb2ce20b0..7ebbf428f3 100644 --- a/bochs/cpu/softfloat3e/f64_to_f32.c +++ b/bochs/cpu/softfloat3e/f64_to_f32.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float32_t f64_to_f32(float64_t a, struct softfloat_status_t *status) +float32 f64_to_f32(float64 a, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f64_to_i32.c b/bochs/cpu/softfloat3e/f64_to_i32.c index f797d3c51d..c296e0bd5e 100644 --- a/bochs/cpu/softfloat3e/f64_to_i32.c +++ b/bochs/cpu/softfloat3e/f64_to_i32.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -int32_t f64_to_i32(float64_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +int32_t f64_to_i32(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f64_to_i32_r_minMag.c b/bochs/cpu/softfloat3e/f64_to_i32_r_minMag.c index 25cfd28501..c58d17ab2f 100644 --- a/bochs/cpu/softfloat3e/f64_to_i32_r_minMag.c +++ b/bochs/cpu/softfloat3e/f64_to_i32_r_minMag.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -int32_t f64_to_i32_r_minMag(float64_t a, bool exact, struct softfloat_status_t *status) +int32_t f64_to_i32_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) { int16_t exp; uint64_t sig; diff --git a/bochs/cpu/softfloat3e/f64_to_i64.c b/bochs/cpu/softfloat3e/f64_to_i64.c index 8a9fe703fd..96381033ba 100644 --- a/bochs/cpu/softfloat3e/f64_to_i64.c +++ b/bochs/cpu/softfloat3e/f64_to_i64.c @@ -37,10 +37,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -int64_t f64_to_i64(float64_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +int64_t f64_to_i64(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f64_to_i64_r_minMag.c b/bochs/cpu/softfloat3e/f64_to_i64_r_minMag.c index fec7ffbc60..72617b84dc 100644 --- a/bochs/cpu/softfloat3e/f64_to_i64_r_minMag.c +++ b/bochs/cpu/softfloat3e/f64_to_i64_r_minMag.c @@ -40,7 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -int64_t f64_to_i64_r_minMag(float64_t a, bool exact, struct softfloat_status_t *status) +int64_t f64_to_i64_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f64_to_ui32.c b/bochs/cpu/softfloat3e/f64_to_ui32.c index 4194abdc67..1dad1bc321 100644 --- a/bochs/cpu/softfloat3e/f64_to_ui32.c +++ b/bochs/cpu/softfloat3e/f64_to_ui32.c @@ -37,10 +37,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -uint32_t f64_to_ui32(float64_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +uint32_t f64_to_ui32(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f64_to_ui32_r_minMag.c b/bochs/cpu/softfloat3e/f64_to_ui32_r_minMag.c index 5684873459..f89fce4ba8 100644 --- a/bochs/cpu/softfloat3e/f64_to_ui32_r_minMag.c +++ b/bochs/cpu/softfloat3e/f64_to_ui32_r_minMag.c @@ -40,7 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -uint32_t f64_to_ui32_r_minMag(float64_t a, bool exact, struct softfloat_status_t *status) +uint32_t f64_to_ui32_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) { int16_t exp; uint64_t sig; diff --git a/bochs/cpu/softfloat3e/f64_to_ui64.c b/bochs/cpu/softfloat3e/f64_to_ui64.c index b5b2028386..98e6402e2e 100644 --- a/bochs/cpu/softfloat3e/f64_to_ui64.c +++ b/bochs/cpu/softfloat3e/f64_to_ui64.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -uint64_t f64_to_ui64(float64_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +uint64_t f64_to_ui64(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) { bool sign; int16_t exp; diff --git a/bochs/cpu/softfloat3e/f64_to_ui64_r_minMag.c b/bochs/cpu/softfloat3e/f64_to_ui64_r_minMag.c index b55537b7aa..e7bda4c67e 100644 --- a/bochs/cpu/softfloat3e/f64_to_ui64_r_minMag.c +++ b/bochs/cpu/softfloat3e/f64_to_ui64_r_minMag.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -uint64_t f64_to_ui64_r_minMag(float64_t a, bool exact, struct softfloat_status_t *status) +uint64_t f64_to_ui64_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) { int16_t exp; uint64_t sig; diff --git a/bochs/cpu/softfloat3e/i32_to_extF80.c b/bochs/cpu/softfloat3e/i32_to_extF80.c index 5ef8e82948..edd92ced0e 100644 --- a/bochs/cpu/softfloat3e/i32_to_extF80.c +++ b/bochs/cpu/softfloat3e/i32_to_extF80.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" extFloat80_t i32_to_extF80(int32_t a) diff --git a/bochs/cpu/softfloat3e/i32_to_f128.c b/bochs/cpu/softfloat3e/i32_to_f128.c index e2a57b68bd..1ae64e46b7 100644 --- a/bochs/cpu/softfloat3e/i32_to_f128.c +++ b/bochs/cpu/softfloat3e/i32_to_f128.c @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" float128_t i32_to_f128(int32_t a) diff --git a/bochs/cpu/softfloat3e/i32_to_f16.c b/bochs/cpu/softfloat3e/i32_to_f16.c index 25d6669f5b..3d017a7b7a 100644 --- a/bochs/cpu/softfloat3e/i32_to_f16.c +++ b/bochs/cpu/softfloat3e/i32_to_f16.c @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float16_t i32_to_f16(int32_t a, struct softfloat_status_t *status) +float16 i32_to_f16(int32_t a, struct softfloat_status_t *status) { bool sign; uint32_t absA; diff --git a/bochs/cpu/softfloat3e/i32_to_f32.c b/bochs/cpu/softfloat3e/i32_to_f32.c index 14325326a2..f2742d24dc 100644 --- a/bochs/cpu/softfloat3e/i32_to_f32.c +++ b/bochs/cpu/softfloat3e/i32_to_f32.c @@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "internals.h" #include "softfloat.h" -float32_t i32_to_f32(int32_t a, struct softfloat_status_t *status) +float32 i32_to_f32(int32_t a, struct softfloat_status_t *status) { bool sign; uint32_t absA; diff --git a/bochs/cpu/softfloat3e/i32_to_f64.c b/bochs/cpu/softfloat3e/i32_to_f64.c index f5f1142915..7aaa4e1c28 100644 --- a/bochs/cpu/softfloat3e/i32_to_f64.c +++ b/bochs/cpu/softfloat3e/i32_to_f64.c @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float64_t i32_to_f64(int32_t a) +float64 i32_to_f64(int32_t a) { bool sign; uint32_t absA; diff --git a/bochs/cpu/softfloat3e/i64_to_extF80.c b/bochs/cpu/softfloat3e/i64_to_extF80.c index c1f5b2515b..4ac8fefc3f 100644 --- a/bochs/cpu/softfloat3e/i64_to_extF80.c +++ b/bochs/cpu/softfloat3e/i64_to_extF80.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" extFloat80_t i64_to_extF80(int64_t a) diff --git a/bochs/cpu/softfloat3e/i64_to_f128.c b/bochs/cpu/softfloat3e/i64_to_f128.c index 707b5dfd72..4d80a9e7ab 100644 --- a/bochs/cpu/softfloat3e/i64_to_f128.c +++ b/bochs/cpu/softfloat3e/i64_to_f128.c @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" float128_t i64_to_f128(int64_t a) diff --git a/bochs/cpu/softfloat3e/i64_to_f16.c b/bochs/cpu/softfloat3e/i64_to_f16.c index 7909bb0378..43873610a4 100644 --- a/bochs/cpu/softfloat3e/i64_to_f16.c +++ b/bochs/cpu/softfloat3e/i64_to_f16.c @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float16_t i64_to_f16(int64_t a, struct softfloat_status_t *status) +float16 i64_to_f16(int64_t a, struct softfloat_status_t *status) { bool sign; uint64_t absA; diff --git a/bochs/cpu/softfloat3e/i64_to_f32.c b/bochs/cpu/softfloat3e/i64_to_f32.c index 4729dcd95a..ae929be2d9 100644 --- a/bochs/cpu/softfloat3e/i64_to_f32.c +++ b/bochs/cpu/softfloat3e/i64_to_f32.c @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float32_t i64_to_f32(int64_t a, struct softfloat_status_t *status) +float32 i64_to_f32(int64_t a, struct softfloat_status_t *status) { bool sign; uint64_t absA; diff --git a/bochs/cpu/softfloat3e/i64_to_f64.c b/bochs/cpu/softfloat3e/i64_to_f64.c index 26182fa106..b217354af5 100644 --- a/bochs/cpu/softfloat3e/i64_to_f64.c +++ b/bochs/cpu/softfloat3e/i64_to_f64.c @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float64_t i64_to_f64(int64_t a, struct softfloat_status_t *status) +float64 i64_to_f64(int64_t a, struct softfloat_status_t *status) { bool sign; uint64_t absA; diff --git a/bochs/cpu/softfloat3e/include/internals.h b/bochs/cpu/softfloat3e/include/internals.h index 2808ca1634..2a2ed8bc44 100644 --- a/bochs/cpu/softfloat3e/include/internals.h +++ b/bochs/cpu/softfloat3e/include/internals.h @@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include "primitives.h" +//#include "primitives.h" #include "softfloat_types.h" struct softfloat_status_t; @@ -46,14 +46,10 @@ struct softfloat_status_t; /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ uint32_t softfloat_roundToUI32(bool, uint64_t, uint8_t, bool, struct softfloat_status_t *); - -uint64_t - softfloat_roundToUI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *); +uint64_t softfloat_roundToUI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *); int32_t softfloat_roundToI32(bool, uint64_t, uint8_t, bool, struct softfloat_status_t *); - -int64_t - softfloat_roundToI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *); +int64_t softfloat_roundToI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *); /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ @@ -67,29 +63,23 @@ int64_t struct exp8_sig16 { int8_t exp; uint16_t sig; }; struct exp8_sig16 softfloat_normSubnormalF16Sig(uint16_t); -float16_t softfloat_roundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *); -float16_t softfloat_normRoundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *); - -float16_t - softfloat_mulAddF16(uint16_t, uint16_t, uint16_t, uint8_t, struct softfloat_status_t *); +float16 softfloat_roundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *); +float16 softfloat_normRoundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *); /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define signF32UI(a) ((bool) ((uint32_t) (a)>>31)) #define expF32UI(a) ((int16_t) ((a)>>23) & 0xFF) #define fracF32UI(a) ((a) & 0x007FFFFF) -#define packToF32UI(sign, exp, sig) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig)) +#define packToF32UI(sign, exp, sig) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (uint32_t)(sig)) #define isNaNF32UI(a) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF)) struct exp16_sig32 { int16_t exp; uint32_t sig; }; struct exp16_sig32 softfloat_normSubnormalF32Sig(uint32_t); -float32_t softfloat_roundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *); -float32_t softfloat_normRoundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *); - -float32_t - softfloat_mulAddF32(uint32_t, uint32_t, uint32_t, uint8_t, struct softfloat_status_t *); +float32 softfloat_roundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *); +float32 softfloat_normRoundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *); /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ @@ -103,11 +93,8 @@ float32_t struct exp16_sig64 { int16_t exp; uint64_t sig; }; struct exp16_sig64 softfloat_normSubnormalF64Sig(uint64_t); -float64_t softfloat_roundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *); -float64_t softfloat_normRoundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *); - -float64_t - softfloat_mulAddF64(uint64_t, uint64_t, uint64_t, uint8_t, struct softfloat_status_t *); +float64 softfloat_roundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *); +float64 softfloat_normRoundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *); /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ @@ -148,15 +135,4 @@ float128_t float128_t softfloat_normRoundPackToF128(bool, int32_t, uint64_t, uint64_t, struct softfloat_status_t *); -float128_t - softfloat_mulAddF128( - uint64_t, - uint64_t, - uint64_t, - uint64_t, - uint64_t, - uint64_t, - uint8_t, - struct softfloat_status_t *status); - #endif diff --git a/bochs/cpu/softfloat3e/include/primitiveTypes.h b/bochs/cpu/softfloat3e/include/primitiveTypes.h index 42a61ebd6f..04e72e675e 100644 --- a/bochs/cpu/softfloat3e/include/primitiveTypes.h +++ b/bochs/cpu/softfloat3e/include/primitiveTypes.h @@ -36,19 +36,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef primitiveTypes_h #define primitiveTypes_h 1 -#include #include "config.h" -#ifdef BX_LITTLE_ENDIAN -struct uint128 { uint64_t v0, v64; }; -struct uint64_extra { uint64_t extra, v; }; -struct uint128_extra { uint64_t extra; struct uint128 v; }; -#else -struct uint128 { uint64_t v64, v0; }; -struct uint64_extra { uint64_t v, extra; }; -struct uint128_extra { struct uint128 v; uint64_t extra; }; -#endif - /*---------------------------------------------------------------------------- | These macros are used to isolate the differences in word order between big- | endian and little-endian platforms. diff --git a/bochs/cpu/softfloat3e/include/primitives.h b/bochs/cpu/softfloat3e/include/primitives.h index b7ba02cc34..f10d164536 100644 --- a/bochs/cpu/softfloat3e/include/primitives.h +++ b/bochs/cpu/softfloat3e/include/primitives.h @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "config.h" -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_shortShiftRightJam64 /*---------------------------------------------------------------------------- diff --git a/bochs/cpu/softfloat3e/include/softfloat-compare.h b/bochs/cpu/softfloat3e/include/softfloat-compare.h index 2dfca51226..b7f13af317 100644 --- a/bochs/cpu/softfloat3e/include/softfloat-compare.h +++ b/bochs/cpu/softfloat3e/include/softfloat-compare.h @@ -40,227 +40,227 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ======= float16 ======= // -typedef int (*float16_compare_method)(float16_t, float16_t, softfloat_status_t *status); +typedef int (*float16_compare_method)(float16, float16, softfloat_status_t *status); // 0x00 -BX_CPP_INLINE int f16_eq_ordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_eq_ordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation == float_relation_equal); + return (relation == softfloat_relation_equal); } // 0x01 -BX_CPP_INLINE int f16_lt_ordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_lt_ordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation == float_relation_less); + return (relation == softfloat_relation_less); } // 0x02 -BX_CPP_INLINE int f16_le_ordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_le_ordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_equal); } // 0x03 -BX_CPP_INLINE int f16_unordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_unordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation == float_relation_unordered); + return (relation == softfloat_relation_unordered); } // 0x04 -BX_CPP_INLINE int f16_neq_unordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_neq_unordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation != float_relation_equal); + return (relation != softfloat_relation_equal); } // 0x05 -BX_CPP_INLINE int f16_nlt_unordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_nlt_unordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation != float_relation_less); + return (relation != softfloat_relation_less); } // 0x06 -BX_CPP_INLINE int f16_nle_unordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_nle_unordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); + return (relation != softfloat_relation_less) && (relation != softfloat_relation_equal); } // 0x07 -BX_CPP_INLINE int f16_ordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_ordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation != float_relation_unordered); + return (relation != softfloat_relation_unordered); } // 0x08 -BX_CPP_INLINE int f16_eq_unordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_eq_unordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); + return (relation == softfloat_relation_equal) || (relation == softfloat_relation_unordered); } // 0x09 -BX_CPP_INLINE int f16_nge_unordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_nge_unordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_unordered); } // 0x0a -BX_CPP_INLINE int f16_ngt_unordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_ngt_unordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation != float_relation_greater); + return (relation != softfloat_relation_greater); } // 0x0b -BX_CPP_INLINE int f16_false_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_false_quiet(float16 a, float16 b, softfloat_status_t *status) { f16_compare_quiet(a, b, status); return 0; } // 0x0c -BX_CPP_INLINE int f16_neq_ordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_neq_ordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); + return (relation != softfloat_relation_equal) && (relation != softfloat_relation_unordered); } // 0x0d -BX_CPP_INLINE int f16_ge_ordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_ge_ordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); + return (relation == softfloat_relation_greater) || (relation == softfloat_relation_equal); } // 0x0e -BX_CPP_INLINE int f16_gt_ordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_gt_ordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation == float_relation_greater); + return (relation == softfloat_relation_greater); } // 0x0f -BX_CPP_INLINE int f16_true_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_true_quiet(float16 a, float16 b, softfloat_status_t *status) { f16_compare_quiet(a, b, status); return 1; } // 0x10 -BX_CPP_INLINE int f16_eq_ordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_eq_ordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation == float_relation_equal); + return (relation == softfloat_relation_equal); } // 0x11 -BX_CPP_INLINE int f16_lt_ordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_lt_ordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation == float_relation_less); + return (relation == softfloat_relation_less); } // 0x12 -BX_CPP_INLINE int f16_le_ordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_le_ordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_equal); } // 0x13 -BX_CPP_INLINE int f16_unordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_unordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation == float_relation_unordered); + return (relation == softfloat_relation_unordered); } // 0x14 -BX_CPP_INLINE int f16_neq_unordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_neq_unordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation != float_relation_equal); + return (relation != softfloat_relation_equal); } // 0x15 -BX_CPP_INLINE int f16_nlt_unordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_nlt_unordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation != float_relation_less); + return (relation != softfloat_relation_less); } // 0x16 -BX_CPP_INLINE int f16_nle_unordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_nle_unordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); + return (relation != softfloat_relation_less) && (relation != softfloat_relation_equal); } // 0x17 -BX_CPP_INLINE int f16_ordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_ordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation != float_relation_unordered); + return (relation != softfloat_relation_unordered); } // 0x18 -BX_CPP_INLINE int f16_eq_unordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_eq_unordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); + return (relation == softfloat_relation_equal) || (relation == softfloat_relation_unordered); } // 0x19 -BX_CPP_INLINE int f16_nge_unordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_nge_unordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_unordered); } // 0x1a -BX_CPP_INLINE int f16_ngt_unordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_ngt_unordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation != float_relation_greater); + return (relation != softfloat_relation_greater); } // 0x1b -BX_CPP_INLINE int f16_false_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_false_signalling(float16 a, float16 b, softfloat_status_t *status) { f16_compare(a, b, status); return 0; } // 0x1c -BX_CPP_INLINE int f16_neq_ordered_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_neq_ordered_signalling(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); + return (relation != softfloat_relation_equal) && (relation != softfloat_relation_unordered); } // 0x1d -BX_CPP_INLINE int f16_ge_ordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_ge_ordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); + return (relation == softfloat_relation_greater) || (relation == softfloat_relation_equal); } // 0x1e -BX_CPP_INLINE int f16_gt_ordered_quiet(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_gt_ordered_quiet(float16 a, float16 b, softfloat_status_t *status) { int relation = f16_compare_quiet(a, b, status); - return (relation == float_relation_greater); + return (relation == softfloat_relation_greater); } // 0x1f -BX_CPP_INLINE int f16_true_signalling(float16_t a, float16_t b, softfloat_status_t *status) +BX_CPP_INLINE int f16_true_signalling(float16 a, float16 b, softfloat_status_t *status) { f16_compare(a, b, status); return 1; @@ -268,227 +268,227 @@ BX_CPP_INLINE int f16_true_signalling(float16_t a, float16_t b, softfloat_status // ======= float32 ======= // -typedef int (*float32_compare_method)(float32_t, float32_t, softfloat_status_t *status); +typedef int (*float32_compare_method)(float32, float32, softfloat_status_t *status); // 0x00 -BX_CPP_INLINE int f32_eq_ordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_eq_ordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation == float_relation_equal); + return (relation == softfloat_relation_equal); } // 0x01 -BX_CPP_INLINE int f32_lt_ordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_lt_ordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation == float_relation_less); + return (relation == softfloat_relation_less); } // 0x02 -BX_CPP_INLINE int f32_le_ordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_le_ordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_equal); } // 0x03 -BX_CPP_INLINE int f32_unordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_unordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation == float_relation_unordered); + return (relation == softfloat_relation_unordered); } // 0x04 -BX_CPP_INLINE int f32_neq_unordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_neq_unordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation != float_relation_equal); + return (relation != softfloat_relation_equal); } // 0x05 -BX_CPP_INLINE int f32_nlt_unordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_nlt_unordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation != float_relation_less); + return (relation != softfloat_relation_less); } // 0x06 -BX_CPP_INLINE int f32_nle_unordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_nle_unordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); + return (relation != softfloat_relation_less) && (relation != softfloat_relation_equal); } // 0x07 -BX_CPP_INLINE int f32_ordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_ordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation != float_relation_unordered); + return (relation != softfloat_relation_unordered); } // 0x08 -BX_CPP_INLINE int f32_eq_unordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_eq_unordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); + return (relation == softfloat_relation_equal) || (relation == softfloat_relation_unordered); } // 0x09 -BX_CPP_INLINE int f32_nge_unordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_nge_unordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_unordered); } // 0x0a -BX_CPP_INLINE int f32_ngt_unordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_ngt_unordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation != float_relation_greater); + return (relation != softfloat_relation_greater); } // 0x0b -BX_CPP_INLINE int f32_false_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_false_quiet(float32 a, float32 b, softfloat_status_t *status) { f32_compare_quiet(a, b, status); return 0; } // 0x0c -BX_CPP_INLINE int f32_neq_ordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_neq_ordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); + return (relation != softfloat_relation_equal) && (relation != softfloat_relation_unordered); } // 0x0d -BX_CPP_INLINE int f32_ge_ordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_ge_ordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); + return (relation == softfloat_relation_greater) || (relation == softfloat_relation_equal); } // 0x0e -BX_CPP_INLINE int f32_gt_ordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_gt_ordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation == float_relation_greater); + return (relation == softfloat_relation_greater); } // 0x0f -BX_CPP_INLINE int f32_true_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_true_quiet(float32 a, float32 b, softfloat_status_t *status) { f32_compare_quiet(a, b, status); return 1; } // 0x10 -BX_CPP_INLINE int f32_eq_ordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_eq_ordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation == float_relation_equal); + return (relation == softfloat_relation_equal); } // 0x11 -BX_CPP_INLINE int f32_lt_ordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_lt_ordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation == float_relation_less); + return (relation == softfloat_relation_less); } // 0x12 -BX_CPP_INLINE int f32_le_ordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_le_ordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_equal); } // 0x13 -BX_CPP_INLINE int f32_unordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_unordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation == float_relation_unordered); + return (relation == softfloat_relation_unordered); } // 0x14 -BX_CPP_INLINE int f32_neq_unordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_neq_unordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation != float_relation_equal); + return (relation != softfloat_relation_equal); } // 0x15 -BX_CPP_INLINE int f32_nlt_unordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_nlt_unordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation != float_relation_less); + return (relation != softfloat_relation_less); } // 0x16 -BX_CPP_INLINE int f32_nle_unordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_nle_unordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); + return (relation != softfloat_relation_less) && (relation != softfloat_relation_equal); } // 0x17 -BX_CPP_INLINE int f32_ordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_ordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation != float_relation_unordered); + return (relation != softfloat_relation_unordered); } // 0x18 -BX_CPP_INLINE int f32_eq_unordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_eq_unordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); + return (relation == softfloat_relation_equal) || (relation == softfloat_relation_unordered); } // 0x19 -BX_CPP_INLINE int f32_nge_unordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_nge_unordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_unordered); } // 0x1a -BX_CPP_INLINE int f32_ngt_unordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_ngt_unordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation != float_relation_greater); + return (relation != softfloat_relation_greater); } // 0x1b -BX_CPP_INLINE int f32_false_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_false_signalling(float32 a, float32 b, softfloat_status_t *status) { f32_compare(a, b, status); return 0; } // 0x1c -BX_CPP_INLINE int f32_neq_ordered_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_neq_ordered_signalling(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); + return (relation != softfloat_relation_equal) && (relation != softfloat_relation_unordered); } // 0x1d -BX_CPP_INLINE int f32_ge_ordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_ge_ordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); + return (relation == softfloat_relation_greater) || (relation == softfloat_relation_equal); } // 0x1e -BX_CPP_INLINE int f32_gt_ordered_quiet(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_gt_ordered_quiet(float32 a, float32 b, softfloat_status_t *status) { int relation = f32_compare_quiet(a, b, status); - return (relation == float_relation_greater); + return (relation == softfloat_relation_greater); } // 0x1f -BX_CPP_INLINE int f32_true_signalling(float32_t a, float32_t b, softfloat_status_t *status) +BX_CPP_INLINE int f32_true_signalling(float32 a, float32 b, softfloat_status_t *status) { f32_compare(a, b, status); return 1; @@ -496,227 +496,227 @@ BX_CPP_INLINE int f32_true_signalling(float32_t a, float32_t b, softfloat_status // ======= float64 ======= // -typedef int (*float64_compare_method)(float64_t, float64_t, softfloat_status_t *status); +typedef int (*float64_compare_method)(float64, float64, softfloat_status_t *status); // 0x00 -BX_CPP_INLINE int f64_eq_ordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_eq_ordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation == float_relation_equal); + return (relation == softfloat_relation_equal); } // 0x01 -BX_CPP_INLINE int f64_lt_ordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_lt_ordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation == float_relation_less); + return (relation == softfloat_relation_less); } // 0x02 -BX_CPP_INLINE int f64_le_ordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_le_ordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_equal); } // 0x03 -BX_CPP_INLINE int f64_unordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_unordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation == float_relation_unordered); + return (relation == softfloat_relation_unordered); } // 0x04 -BX_CPP_INLINE int f64_neq_unordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_neq_unordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation != float_relation_equal); + return (relation != softfloat_relation_equal); } // 0x05 -BX_CPP_INLINE int f64_nlt_unordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_nlt_unordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation != float_relation_less); + return (relation != softfloat_relation_less); } // 0x06 -BX_CPP_INLINE int f64_nle_unordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_nle_unordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); + return (relation != softfloat_relation_less) && (relation != softfloat_relation_equal); } // 0x07 -BX_CPP_INLINE int f64_ordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_ordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation != float_relation_unordered); + return (relation != softfloat_relation_unordered); } // 0x08 -BX_CPP_INLINE int f64_eq_unordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_eq_unordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); + return (relation == softfloat_relation_equal) || (relation == softfloat_relation_unordered); } // 0x09 -BX_CPP_INLINE int f64_nge_unordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_nge_unordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_unordered); } // 0x0a -BX_CPP_INLINE int f64_ngt_unordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_ngt_unordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation != float_relation_greater); + return (relation != softfloat_relation_greater); } // 0x0b -BX_CPP_INLINE int f64_false_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_false_quiet(float64 a, float64 b, softfloat_status_t *status) { f64_compare_quiet(a, b, status); return 0; } // 0x0c -BX_CPP_INLINE int f64_neq_ordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_neq_ordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); + return (relation != softfloat_relation_equal) && (relation != softfloat_relation_unordered); } // 0x0d -BX_CPP_INLINE int f64_ge_ordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_ge_ordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); + return (relation == softfloat_relation_greater) || (relation == softfloat_relation_equal); } // 0x0e -BX_CPP_INLINE int f64_gt_ordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_gt_ordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation == float_relation_greater); + return (relation == softfloat_relation_greater); } // 0x0f -BX_CPP_INLINE int f64_true_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_true_quiet(float64 a, float64 b, softfloat_status_t *status) { f64_compare_quiet(a, b, status); return 1; } // 0x10 -BX_CPP_INLINE int f64_eq_ordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_eq_ordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation == float_relation_equal); + return (relation == softfloat_relation_equal); } // 0x11 -BX_CPP_INLINE int f64_lt_ordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_lt_ordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation == float_relation_less); + return (relation == softfloat_relation_less); } // 0x12 -BX_CPP_INLINE int f64_le_ordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_le_ordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_equal); } // 0x13 -BX_CPP_INLINE int f64_unordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_unordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation == float_relation_unordered); + return (relation == softfloat_relation_unordered); } // 0x14 -BX_CPP_INLINE int f64_neq_unordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_neq_unordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation != float_relation_equal); + return (relation != softfloat_relation_equal); } // 0x15 -BX_CPP_INLINE int f64_nlt_unordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_nlt_unordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation != float_relation_less); + return (relation != softfloat_relation_less); } // 0x16 -BX_CPP_INLINE int f64_nle_unordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_nle_unordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); + return (relation != softfloat_relation_less) && (relation != softfloat_relation_equal); } // 0x17 -BX_CPP_INLINE int f64_ordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_ordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation != float_relation_unordered); + return (relation != softfloat_relation_unordered); } // 0x18 -BX_CPP_INLINE int f64_eq_unordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_eq_unordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); + return (relation == softfloat_relation_equal) || (relation == softfloat_relation_unordered); } // 0x19 -BX_CPP_INLINE int f64_nge_unordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_nge_unordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); + return (relation == softfloat_relation_less) || (relation == softfloat_relation_unordered); } // 0x1a -BX_CPP_INLINE int f64_ngt_unordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_ngt_unordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation != float_relation_greater); + return (relation != softfloat_relation_greater); } // 0x1b -BX_CPP_INLINE int f64_false_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_false_signalling(float64 a, float64 b, softfloat_status_t *status) { f64_compare(a, b, status); return 0; } // 0x1c -BX_CPP_INLINE int f64_neq_ordered_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_neq_ordered_signalling(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); + return (relation != softfloat_relation_equal) && (relation != softfloat_relation_unordered); } // 0x1d -BX_CPP_INLINE int f64_ge_ordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_ge_ordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); + return (relation == softfloat_relation_greater) || (relation == softfloat_relation_equal); } // 0x1e -BX_CPP_INLINE int f64_gt_ordered_quiet(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_gt_ordered_quiet(float64 a, float64 b, softfloat_status_t *status) { int relation = f64_compare_quiet(a, b, status); - return (relation == float_relation_greater); + return (relation == softfloat_relation_greater); } // 0x1f -BX_CPP_INLINE int f64_true_signalling(float64_t a, float64_t b, softfloat_status_t *status) +BX_CPP_INLINE int f64_true_signalling(float64 a, float64 b, softfloat_status_t *status) { f64_compare(a, b, status); return 1; diff --git a/bochs/cpu/softfloat3e/include/softfloat-extra.h b/bochs/cpu/softfloat3e/include/softfloat-extra.h index 2c4d4bb110..d0278ac487 100644 --- a/bochs/cpu/softfloat3e/include/softfloat-extra.h +++ b/bochs/cpu/softfloat3e/include/softfloat-extra.h @@ -40,22 +40,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ======= float16 ======= // -BX_CPP_INLINE bool f16_sign(float16_t a) +BX_CPP_INLINE bool f16_sign(float16 a) { return signF16UI(a); } -BX_CPP_INLINE int8_t f16_exp(float16_t a) +BX_CPP_INLINE int8_t f16_exp(float16 a) { return expF16UI(a); } -BX_CPP_INLINE uint16_t f16_fraction(float16_t a) +BX_CPP_INLINE uint16_t f16_fraction(float16 a) { return fracF16UI(a); } -BX_CPP_INLINE float16_t f16_denormal_to_zero(float16_t a) +BX_CPP_INLINE float16 f16_denormal_to_zero(float16 a) { if (! expF16UI(a) && fracF16UI(a)) return a & 0x8000; @@ -64,22 +64,22 @@ BX_CPP_INLINE float16_t f16_denormal_to_zero(float16_t a) // ======= float32 ======= // -BX_CPP_INLINE bool f32_sign(float32_t a) +BX_CPP_INLINE bool f32_sign(float32 a) { return signF32UI(a); } -BX_CPP_INLINE int16_t f32_exp(float32_t a) +BX_CPP_INLINE int16_t f32_exp(float32 a) { return expF32UI(a); } -BX_CPP_INLINE uint32_t f32_fraction(float32_t a) +BX_CPP_INLINE uint32_t f32_fraction(float32 a) { return fracF32UI(a); } -BX_CPP_INLINE float32_t f32_denormal_to_zero(float32_t a) +BX_CPP_INLINE float32 f32_denormal_to_zero(float32 a) { if (! expF32UI(a) && fracF32UI(a)) return a & 0x80000000; @@ -88,22 +88,22 @@ BX_CPP_INLINE float32_t f32_denormal_to_zero(float32_t a) // ======= float64 ======= // -BX_CPP_INLINE bool f64_sign(float64_t a) +BX_CPP_INLINE bool f64_sign(float64 a) { return signF64UI(a); } -BX_CPP_INLINE int16_t f64_exp(float64_t a) +BX_CPP_INLINE int16_t f64_exp(float64 a) { return expF64UI(a); } -BX_CPP_INLINE uint64_t f64_fraction(float64_t a) +BX_CPP_INLINE uint64_t f64_fraction(float64 a) { return fracF64UI(a); } -BX_CPP_INLINE float64_t f64_denormal_to_zero(float64_t a) +BX_CPP_INLINE float64 f64_denormal_to_zero(float64 a) { if (! expF64UI(a) && fracF64UI(a)) return a & ((uint64_t)(1) << 63); @@ -117,4 +117,19 @@ BX_CPP_INLINE bool extF80_isUnsupported(extFloat80_t a) return ((a.signExp & 0x7FFF) && !(a.signif & BX_CONST64(0x8000000000000000))); } +BX_CPP_INLINE bool extF80_sign(extFloat80_t a) +{ + return signExtF80UI64(a.signExp); +} + +BX_CPP_INLINE int16_t extF80_exp(extFloat80_t a) +{ + return expExtF80UI64(a.signExp); +} + +BX_CPP_INLINE uint64_t extF80_fraction(extFloat80_t a) +{ + return a.signif; +} + #endif diff --git a/bochs/cpu/softfloat3e/include/softfloat.h b/bochs/cpu/softfloat3e/include/softfloat.h index 531e1e4124..3e5d6c75ef 100644 --- a/bochs/cpu/softfloat3e/include/softfloat.h +++ b/bochs/cpu/softfloat3e/include/softfloat.h @@ -47,11 +47,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "softfloat_types.h" - #include "softfloat-extra.h" -#define FLOATX80 - struct softfloat_status_t { uint8_t softfloat_roundingMode; @@ -67,20 +64,8 @@ struct softfloat_status_t | Valid values are 32, 64, and 80. *----------------------------------------------------------------------------*/ uint8_t extF80_roundingPrecision; - -#define float_rounding_mode softfloat_roundingMode -#define float_exception_flags softfloat_exceptionFlags -#define flush_underflow_to_zero softfloat_flush_underflow_to_zero -#define denormals_are_zeros softfloat_denormals_are_zeros -#define float_rounding_precision extF80_roundingPrecision -#define float_exception_masks softfloat_exceptionMasks -#define float_suppress_exception softfloat_suppressException - - int float_nan_handling_mode; /* flag register */ // redundant }; -typedef struct softfloat_status_t float_status_t; - /*---------------------------------------------------------------------------- | Software floating-point rounding mode. *----------------------------------------------------------------------------*/ @@ -108,6 +93,10 @@ enum softfloat_exception_flag_t { softfloat_flag_inexact = 0x20 }; +static const unsigned softfloat_all_exceptions_mask = 0x3f; + +#define FLOATX80 + #ifdef FLOATX80 #define RAISE_SW_C1 0x0200 #endif @@ -221,97 +210,97 @@ BX_CPP_INLINE void softfloat_setRoundingUp(struct softfloat_status_t *status) { /*---------------------------------------------------------------------------- | Integer-to-floating-point conversion routines. *----------------------------------------------------------------------------*/ -float16_t ui16_to_f16(uint16_t, struct softfloat_status_t *); -float16_t ui32_to_f16(uint32_t, struct softfloat_status_t *); -float32_t ui32_to_f32(uint32_t, struct softfloat_status_t *); -float64_t ui32_to_f64(uint32_t); +float16 ui16_to_f16(uint16_t, struct softfloat_status_t *); +float16 ui32_to_f16(uint32_t, struct softfloat_status_t *); +float32 ui32_to_f32(uint32_t, struct softfloat_status_t *); +float64 ui32_to_f64(uint32_t); extFloat80_t ui32_to_extF80(uint32_t); float128_t ui32_to_f128(uint32_t); -float16_t ui64_to_f16(uint64_t, struct softfloat_status_t *); -float32_t ui64_to_f32(uint64_t, struct softfloat_status_t *); -float64_t ui64_to_f64(uint64_t, struct softfloat_status_t *); +float16 ui64_to_f16(uint64_t, struct softfloat_status_t *); +float32 ui64_to_f32(uint64_t, struct softfloat_status_t *); +float64 ui64_to_f64(uint64_t, struct softfloat_status_t *); extFloat80_t ui64_to_extF80(uint64_t); float128_t ui64_to_f128(uint64_t); -float16_t i16_to_f16(int16_t, struct softfloat_status_t *); -float16_t i32_to_f16(int32_t, struct softfloat_status_t *); -float32_t i32_to_f32(int32_t, struct softfloat_status_t *); -float64_t i32_to_f64(int32_t); +float16 i16_to_f16(int16_t, struct softfloat_status_t *); +float16 i32_to_f16(int32_t, struct softfloat_status_t *); +float32 i32_to_f32(int32_t, struct softfloat_status_t *); +float64 i32_to_f64(int32_t); extFloat80_t i32_to_extF80(int32_t); float128_t i32_to_f128(int32_t); -float16_t i64_to_f16(int64_t, struct softfloat_status_t *); -float32_t i64_to_f32(int64_t, struct softfloat_status_t *); -float64_t i64_to_f64(int64_t, struct softfloat_status_t *); +float16 i64_to_f16(int64_t, struct softfloat_status_t *); +float32 i64_to_f32(int64_t, struct softfloat_status_t *); +float64 i64_to_f64(int64_t, struct softfloat_status_t *); extFloat80_t i64_to_extF80(int64_t); float128_t i64_to_f128(int64_t); -BX_CPP_INLINE float16_t i16_to_f16(int16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE float16 i16_to_f16(int16_t a, struct softfloat_status_t *status) { return i32_to_f16((int32_t)(a), status); } -BX_CPP_INLINE float16_t ui16_to_f16(uint16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE float16 ui16_to_f16(uint16_t a, struct softfloat_status_t *status) { return ui32_to_f16((uint32_t)(a), status); } /*---------------------------------------------------------------------------- | 16-bit (half-precision) floating-point operations. *----------------------------------------------------------------------------*/ -uint32_t f16_to_ui32(float16_t, uint8_t, bool, struct softfloat_status_t *); -uint64_t f16_to_ui64(float16_t, uint8_t, bool, struct softfloat_status_t *); -int32_t f16_to_i32(float16_t, uint8_t, bool, struct softfloat_status_t *); -int64_t f16_to_i64(float16_t, uint8_t, bool, struct softfloat_status_t *); -uint32_t f16_to_ui32_r_minMag(float16_t, bool, struct softfloat_status_t *); -uint64_t f16_to_ui64_r_minMag(float16_t, bool, struct softfloat_status_t *); -int32_t f16_to_i32_r_minMag(float16_t, bool, struct softfloat_status_t *); -int64_t f16_to_i64_r_minMag(float16_t, bool, struct softfloat_status_t *); -float32_t f16_to_f32(float16_t, struct softfloat_status_t *); -float64_t f16_to_f64(float16_t, struct softfloat_status_t *); -extFloat80_t f16_to_extF80(float16_t, struct softfloat_status_t *); -float16_t f16_roundToInt(float16_t, uint8_t, uint8_t, bool, struct softfloat_status_t *); -float16_t f16_add(float16_t, float16_t, struct softfloat_status_t *); -float16_t f16_sub(float16_t, float16_t, struct softfloat_status_t *); -float16_t f16_mul(float16_t, float16_t, struct softfloat_status_t *); -float16_t f16_mulAdd(float16_t, float16_t, float16_t, uint8_t op, struct softfloat_status_t *); -float16_t f16_div(float16_t, float16_t, struct softfloat_status_t *); -float16_t f16_min(float16_t, float16_t, struct softfloat_status_t *); -float16_t f16_max(float16_t, float16_t, struct softfloat_status_t *); -float16_t f16_getExp(float16_t, struct softfloat_status_t *); -float16_t f16_getMant(float16_t, struct softfloat_status_t *, int, int); -float16_t f16_range(float16_t, float16_t, bool is_max, bool is_abs, int sign_ctrl, softfloat_status_t *); -int f16_compare(float16_t, float16_t, bool, struct softfloat_status_t *); -float16_t f16_sqrt(float16_t, struct softfloat_status_t *); -softfloat_class_t f16_class(float16_t); - -bool f16_isSignalingNaN(float16_t); -bool f16_isNaN(float16_t); - -bool f16_sign(float16_t); -int8_t f16_exp(float16_t); -uint16_t f16_fraction(float16_t); -float16_t f16_denormal_to_zero(float16_t); - -BX_CPP_INLINE int f16_compare(float16_t a, float16_t b, softfloat_status_t *status) { +uint32_t f16_to_ui32(float16, uint8_t, bool, struct softfloat_status_t *); +uint64_t f16_to_ui64(float16, uint8_t, bool, struct softfloat_status_t *); +int32_t f16_to_i32(float16, uint8_t, bool, struct softfloat_status_t *); +int64_t f16_to_i64(float16, uint8_t, bool, struct softfloat_status_t *); +uint32_t f16_to_ui32_r_minMag(float16, bool, struct softfloat_status_t *); +uint64_t f16_to_ui64_r_minMag(float16, bool, struct softfloat_status_t *); +int32_t f16_to_i32_r_minMag(float16, bool, struct softfloat_status_t *); +int64_t f16_to_i64_r_minMag(float16, bool, struct softfloat_status_t *); +float32 f16_to_f32(float16, struct softfloat_status_t *); +float64 f16_to_f64(float16, struct softfloat_status_t *); +extFloat80_t f16_to_extF80(float16, struct softfloat_status_t *); +float16 f16_roundToInt(float16, uint8_t, uint8_t, bool, struct softfloat_status_t *); +float16 f16_add(float16, float16, struct softfloat_status_t *); +float16 f16_sub(float16, float16, struct softfloat_status_t *); +float16 f16_mul(float16, float16, struct softfloat_status_t *); +float16 f16_mulAdd(float16, float16, float16, uint8_t op, struct softfloat_status_t *); +float16 f16_div(float16, float16, struct softfloat_status_t *); +float16 f16_min(float16, float16, struct softfloat_status_t *); +float16 f16_max(float16, float16, struct softfloat_status_t *); +float16 f16_getExp(float16, struct softfloat_status_t *); +float16 f16_getMant(float16, struct softfloat_status_t *, int, int); +float16 f16_range(float16, float16, bool is_max, bool is_abs, int sign_ctrl, softfloat_status_t *); +int f16_compare(float16, float16, bool, struct softfloat_status_t *); +float16 f16_sqrt(float16, struct softfloat_status_t *); +softfloat_class_t f16_class(float16); + +bool f16_isSignalingNaN(float16); +bool f16_isNaN(float16); + +bool f16_sign(float16); +int8_t f16_exp(float16); +uint16_t f16_fraction(float16); +float16 f16_denormal_to_zero(float16); + +BX_CPP_INLINE int f16_compare(float16 a, float16 b, softfloat_status_t *status) { return f16_compare(a, b, 0, status); } -BX_CPP_INLINE int f16_compare_quiet(float16_t a, float16_t b, softfloat_status_t *status) { +BX_CPP_INLINE int f16_compare_quiet(float16 a, float16 b, softfloat_status_t *status) { return f16_compare(a, b, 1, status); } -BX_CPP_INLINE float16_t f16_roundToInt(float16_t a, uint8_t scale, struct softfloat_status_t *status) { +BX_CPP_INLINE float16 f16_roundToInt(float16 a, uint8_t scale, struct softfloat_status_t *status) { return f16_roundToInt(a, scale, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE float16_t f16_roundToInt(float16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE float16 f16_roundToInt(float16 a, struct softfloat_status_t *status) { return f16_roundToInt(a, 0, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE int64_t f16_to_i64(float16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int64_t f16_to_i64(float16 a, struct softfloat_status_t *status) { return f16_to_i64(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE int32_t f16_to_i32(float16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int32_t f16_to_i32(float16 a, struct softfloat_status_t *status) { return f16_to_i32(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE int16_t f16_to_i16(float16_t a, softfloat_status_t *status) +BX_CPP_INLINE int16_t f16_to_i16(float16 a, softfloat_status_t *status) { int32_t val_32 = f16_to_i32(a, status); int16_t val_16 = (int16_t) val_32; @@ -322,14 +311,14 @@ BX_CPP_INLINE int16_t f16_to_i16(float16_t a, softfloat_status_t *status) return val_16; } -BX_CPP_INLINE int64_t f16_to_i64_round_to_zero(float16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int64_t f16_to_i64_round_to_zero(float16 a, struct softfloat_status_t *status) { return f16_to_i64_r_minMag(a, true, status); } -BX_CPP_INLINE int32_t f16_to_i32_round_to_zero(float16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int32_t f16_to_i32_round_to_zero(float16 a, struct softfloat_status_t *status) { return f16_to_i32_r_minMag(a, true, status); } -BX_CPP_INLINE int16_t f16_to_i16_round_to_zero(float16_t a, softfloat_status_t *status) +BX_CPP_INLINE int16_t f16_to_i16_round_to_zero(float16 a, softfloat_status_t *status) { int32_t val_32 = f16_to_i32_round_to_zero(a, status); int16_t val_16 = (int16_t) val_32; @@ -340,14 +329,14 @@ BX_CPP_INLINE int16_t f16_to_i16_round_to_zero(float16_t a, softfloat_status_t * return val_16; } -BX_CPP_INLINE uint64_t f16_to_ui64(float16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint64_t f16_to_ui64(float16 a, struct softfloat_status_t *status) { return f16_to_ui64(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE uint32_t f16_to_ui32(float16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint32_t f16_to_ui32(float16 a, struct softfloat_status_t *status) { return f16_to_ui32(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE uint16_t f16_to_ui16(float16_t a, softfloat_status_t *status) +BX_CPP_INLINE uint16_t f16_to_ui16(float16 a, softfloat_status_t *status) { uint32_t val_32 = f16_to_ui32(a, status); if (val_32 > 0xFFFF) { @@ -357,14 +346,14 @@ BX_CPP_INLINE uint16_t f16_to_ui16(float16_t a, softfloat_status_t *status) return (uint16_t) val_32; } -BX_CPP_INLINE uint64_t f16_to_ui64_round_to_zero(float16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint64_t f16_to_ui64_round_to_zero(float16 a, struct softfloat_status_t *status) { return f16_to_ui64_r_minMag(a, true, status); } -BX_CPP_INLINE uint32_t f16_to_ui32_round_to_zero(float16_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint32_t f16_to_ui32_round_to_zero(float16 a, struct softfloat_status_t *status) { return f16_to_ui32_r_minMag(a, true, status); } -BX_CPP_INLINE uint16_t f16_to_ui16_round_to_zero(float16_t a, softfloat_status_t *status) +BX_CPP_INLINE uint16_t f16_to_ui16_round_to_zero(float16 a, softfloat_status_t *status) { uint32_t val_32 = f16_to_ui32_round_to_zero(a, status); if (val_32 > 0xFFFF) { @@ -374,208 +363,208 @@ BX_CPP_INLINE uint16_t f16_to_ui16_round_to_zero(float16_t a, softfloat_status_t return (uint16_t) val_32; } -BX_CPP_INLINE float16_t f16_fmadd(float16_t a, float16_t b, float16_t c, softfloat_status_t *status) { +BX_CPP_INLINE float16 f16_fmadd(float16 a, float16 b, float16 c, softfloat_status_t *status) { return f16_mulAdd(a, b, c, 0, status); } -BX_CPP_INLINE float16_t f16_fmsub(float16_t a, float16_t b, float16_t c, softfloat_status_t *status) { +BX_CPP_INLINE float16 f16_fmsub(float16 a, float16 b, float16 c, softfloat_status_t *status) { return f16_mulAdd(a, b, c, softfloat_muladd_negate_c, status); } -BX_CPP_INLINE float16_t f16_fnmadd(float16_t a, float16_t b, float16_t c, softfloat_status_t *status) { +BX_CPP_INLINE float16 f16_fnmadd(float16 a, float16 b, float16 c, softfloat_status_t *status) { return f16_mulAdd(a, b, c, softfloat_muladd_negate_product, status); } -BX_CPP_INLINE float16_t f16_fnmsub(float16_t a, float16_t b, float16_t c, softfloat_status_t *status) { +BX_CPP_INLINE float16 f16_fnmsub(float16 a, float16 b, float16 c, softfloat_status_t *status) { return f16_mulAdd(a, b, c, softfloat_muladd_negate_result, status); } /*---------------------------------------------------------------------------- | 32-bit (single-precision) floating-point operations. *----------------------------------------------------------------------------*/ -uint32_t f32_to_ui32(float32_t, uint8_t, bool, struct softfloat_status_t *); -uint64_t f32_to_ui64(float32_t, uint8_t, bool, struct softfloat_status_t *); -int32_t f32_to_i32(float32_t, uint8_t, bool, struct softfloat_status_t *); -int64_t f32_to_i64(float32_t, uint8_t, bool, struct softfloat_status_t *); -uint32_t f32_to_ui32_r_minMag(float32_t, bool, struct softfloat_status_t *); -uint64_t f32_to_ui64_r_minMag(float32_t, bool, struct softfloat_status_t *); -int32_t f32_to_i32_r_minMag(float32_t, bool, struct softfloat_status_t *); -int64_t f32_to_i64_r_minMag(float32_t, bool, struct softfloat_status_t *); -float16_t f32_to_f16(float32_t, struct softfloat_status_t *); -float64_t f32_to_f64(float32_t, struct softfloat_status_t *); -extFloat80_t f32_to_extF80(float32_t, struct softfloat_status_t *); -float128_t f32_to_f128(float32_t, struct softfloat_status_t *); -float32_t f32_roundToInt(float32_t, uint8_t, uint8_t, bool, struct softfloat_status_t *); -float32_t f32_add(float32_t, float32_t, struct softfloat_status_t *); -float32_t f32_sub(float32_t, float32_t, struct softfloat_status_t *); -float32_t f32_mul(float32_t, float32_t, struct softfloat_status_t *); -float32_t f32_mulAdd(float32_t, float32_t, float32_t, uint8_t op, struct softfloat_status_t *); -float32_t f32_div(float32_t, float32_t, struct softfloat_status_t *); -float32_t f32_min(float32_t, float32_t, struct softfloat_status_t *); -float32_t f32_max(float32_t, float32_t, struct softfloat_status_t *); -float32_t f32_scalef(float32_t, float32_t, struct softfloat_status_t *); -float32_t f32_getExp(float32_t, struct softfloat_status_t *); -float32_t f32_getMant(float32_t, struct softfloat_status_t *, int, int); -float32_t f32_range(float32_t, float32_t, bool is_max, bool is_abs, int sign_ctrl, softfloat_status_t *); -float32_t f32_frc(float32_t, struct softfloat_status_t *); -int f32_compare(float32_t, float32_t, bool, struct softfloat_status_t *); -float32_t f32_sqrt(float32_t, struct softfloat_status_t *); -softfloat_class_t f32_class(float32_t); - -bool f32_isSignalingNaN(float32_t); -bool f32_isNaN(float32_t); - -bool f32_sign(float32_t); -int16_t f32_exp(float32_t); -uint32_t f32_fraction(float32_t); -float32_t f32_denormal_to_zero(float32_t); - -BX_CPP_INLINE int f32_compare(float32_t a, float32_t b, softfloat_status_t *status) { +uint32_t f32_to_ui32(float32, uint8_t, bool, struct softfloat_status_t *); +uint64_t f32_to_ui64(float32, uint8_t, bool, struct softfloat_status_t *); +int32_t f32_to_i32(float32, uint8_t, bool, struct softfloat_status_t *); +int64_t f32_to_i64(float32, uint8_t, bool, struct softfloat_status_t *); +uint32_t f32_to_ui32_r_minMag(float32, bool, struct softfloat_status_t *); +uint64_t f32_to_ui64_r_minMag(float32, bool, struct softfloat_status_t *); +int32_t f32_to_i32_r_minMag(float32, bool, struct softfloat_status_t *); +int64_t f32_to_i64_r_minMag(float32, bool, struct softfloat_status_t *); +float16 f32_to_f16(float32, struct softfloat_status_t *); +float64 f32_to_f64(float32, struct softfloat_status_t *); +extFloat80_t f32_to_extF80(float32, struct softfloat_status_t *); +float128_t f32_to_f128(float32, struct softfloat_status_t *); +float32 f32_roundToInt(float32, uint8_t, uint8_t, bool, struct softfloat_status_t *); +float32 f32_add(float32, float32, struct softfloat_status_t *); +float32 f32_sub(float32, float32, struct softfloat_status_t *); +float32 f32_mul(float32, float32, struct softfloat_status_t *); +float32 f32_mulAdd(float32, float32, float32, uint8_t op, struct softfloat_status_t *); +float32 f32_div(float32, float32, struct softfloat_status_t *); +float32 f32_min(float32, float32, struct softfloat_status_t *); +float32 f32_max(float32, float32, struct softfloat_status_t *); +float32 f32_scalef(float32, float32, struct softfloat_status_t *); +float32 f32_getExp(float32, struct softfloat_status_t *); +float32 f32_getMant(float32, struct softfloat_status_t *, int, int); +float32 f32_range(float32, float32, bool is_max, bool is_abs, int sign_ctrl, softfloat_status_t *); +float32 f32_frc(float32, struct softfloat_status_t *); +int f32_compare(float32, float32, bool, struct softfloat_status_t *); +float32 f32_sqrt(float32, struct softfloat_status_t *); +softfloat_class_t f32_class(float32); + +bool f32_isSignalingNaN(float32); +bool f32_isNaN(float32); + +bool f32_sign(float32); +int16_t f32_exp(float32); +uint32_t f32_fraction(float32); +float32 f32_denormal_to_zero(float32); + +BX_CPP_INLINE int f32_compare(float32 a, float32 b, softfloat_status_t *status) { return f32_compare(a, b, 0, status); } -BX_CPP_INLINE int f32_compare_quiet(float32_t a, float32_t b, softfloat_status_t *status) { +BX_CPP_INLINE int f32_compare_quiet(float32 a, float32 b, softfloat_status_t *status) { return f32_compare(a, b, 1, status); } -BX_CPP_INLINE float32_t f32_roundToInt(float32_t a, uint8_t scale, struct softfloat_status_t *status) { +BX_CPP_INLINE float32 f32_roundToInt(float32 a, uint8_t scale, struct softfloat_status_t *status) { return f32_roundToInt(a, scale, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE float32_t f32_roundToInt(float32_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE float32 f32_roundToInt(float32 a, struct softfloat_status_t *status) { return f32_roundToInt(a, 0, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE int32_t f32_to_i32(float32_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int32_t f32_to_i32(float32 a, struct softfloat_status_t *status) { return f32_to_i32(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE int64_t f32_to_i64(float32_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int64_t f32_to_i64(float32 a, struct softfloat_status_t *status) { return f32_to_i64(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE int32_t f32_to_i32_round_to_zero(float32_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int32_t f32_to_i32_round_to_zero(float32 a, struct softfloat_status_t *status) { return f32_to_i32_r_minMag(a, true, status); } -BX_CPP_INLINE int64_t f32_to_i64_round_to_zero(float32_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int64_t f32_to_i64_round_to_zero(float32 a, struct softfloat_status_t *status) { return f32_to_i64_r_minMag(a, true, status); } -BX_CPP_INLINE uint32_t f32_to_ui32(float32_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint32_t f32_to_ui32(float32 a, struct softfloat_status_t *status) { return f32_to_ui32(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE uint64_t f32_to_ui64(float32_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint64_t f32_to_ui64(float32 a, struct softfloat_status_t *status) { return f32_to_ui64(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE uint32_t f32_to_ui32_round_to_zero(float32_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint32_t f32_to_ui32_round_to_zero(float32 a, struct softfloat_status_t *status) { return f32_to_ui32_r_minMag(a, true, status); } -BX_CPP_INLINE uint64_t f32_to_ui64_round_to_zero(float32_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint64_t f32_to_ui64_round_to_zero(float32 a, struct softfloat_status_t *status) { return f32_to_ui64_r_minMag(a, true, status); } -BX_CPP_INLINE float32_t f32_fmadd(float32_t a, float32_t b, float32_t c, softfloat_status_t *status) { +BX_CPP_INLINE float32 f32_fmadd(float32 a, float32 b, float32 c, softfloat_status_t *status) { return f32_mulAdd(a, b, c, 0, status); } -BX_CPP_INLINE float32_t f32_fmsub(float32_t a, float32_t b, float32_t c, softfloat_status_t *status) { +BX_CPP_INLINE float32 f32_fmsub(float32 a, float32 b, float32 c, softfloat_status_t *status) { return f32_mulAdd(a, b, c, softfloat_muladd_negate_c, status); } -BX_CPP_INLINE float32_t f32_fnmadd(float32_t a, float32_t b, float32_t c, softfloat_status_t *status) { +BX_CPP_INLINE float32 f32_fnmadd(float32 a, float32 b, float32 c, softfloat_status_t *status) { return f32_mulAdd(a, b, c, softfloat_muladd_negate_product, status); } -BX_CPP_INLINE float32_t f32_fnmsub(float32_t a, float32_t b, float32_t c, softfloat_status_t *status) { +BX_CPP_INLINE float32 f32_fnmsub(float32 a, float32 b, float32 c, softfloat_status_t *status) { return f32_mulAdd(a, b, c, softfloat_muladd_negate_result, status); } /*---------------------------------------------------------------------------- | 64-bit (double-precision) floating-point operations. *----------------------------------------------------------------------------*/ -uint32_t f64_to_ui32(float64_t, uint8_t, bool, struct softfloat_status_t *); -uint64_t f64_to_ui64(float64_t, uint8_t, bool, struct softfloat_status_t *); -int32_t f64_to_i32(float64_t, uint8_t, bool, struct softfloat_status_t *); -int64_t f64_to_i64(float64_t, uint8_t, bool, struct softfloat_status_t *); -uint32_t f64_to_ui32_r_minMag(float64_t, bool, struct softfloat_status_t *); -uint64_t f64_to_ui64_r_minMag(float64_t, bool, struct softfloat_status_t *); -int32_t f64_to_i32_r_minMag(float64_t, bool, struct softfloat_status_t *); -int64_t f64_to_i64_r_minMag(float64_t, bool, struct softfloat_status_t *); -float16_t f64_to_f16(float64_t, struct softfloat_status_t *); -float32_t f64_to_f32(float64_t, struct softfloat_status_t *); -extFloat80_t f64_to_extF80(float64_t, struct softfloat_status_t *); -float128_t f64_to_f128(float64_t, struct softfloat_status_t *); -float64_t f64_roundToInt(float64_t, uint8_t, uint8_t, bool, struct softfloat_status_t *); -float64_t f64_add(float64_t, float64_t, struct softfloat_status_t *); -float64_t f64_sub(float64_t, float64_t, struct softfloat_status_t *); -float64_t f64_mul(float64_t, float64_t, struct softfloat_status_t *); -float64_t f64_mulAdd(float64_t, float64_t, float64_t, uint8_t op, struct softfloat_status_t *); -float64_t f64_div(float64_t, float64_t, struct softfloat_status_t *); -float64_t f64_min(float64_t, float64_t, struct softfloat_status_t *); -float64_t f64_max(float64_t, float64_t, struct softfloat_status_t *); -float64_t f64_scalef(float64_t, float64_t, struct softfloat_status_t *); -float64_t f64_getExp(float64_t, struct softfloat_status_t *); -float64_t f64_getMant(float64_t, struct softfloat_status_t *, int, int); -float64_t f64_range(float64_t, float64_t, bool is_max, bool is_abs, int sign_ctrl, softfloat_status_t *); -float64_t f64_frc(float64_t, struct softfloat_status_t *); -int f64_compare(float64_t, float64_t, bool, struct softfloat_status_t *); -float64_t f64_sqrt(float64_t, struct softfloat_status_t *); -softfloat_class_t f64_class(float64_t); - -bool f64_isSignalingNaN(float64_t); -bool f64_isNaN(float64_t); - -bool f64_sign(float64_t); -int16_t f64_exp(float64_t); -uint64_t f64_fraction(float64_t); -float64_t f64_denormal_to_zero(float64_t); - -BX_CPP_INLINE int f64_compare(float64_t a, float64_t b, softfloat_status_t *status) { +uint32_t f64_to_ui32(float64, uint8_t, bool, struct softfloat_status_t *); +uint64_t f64_to_ui64(float64, uint8_t, bool, struct softfloat_status_t *); +int32_t f64_to_i32(float64, uint8_t, bool, struct softfloat_status_t *); +int64_t f64_to_i64(float64, uint8_t, bool, struct softfloat_status_t *); +uint32_t f64_to_ui32_r_minMag(float64, bool, struct softfloat_status_t *); +uint64_t f64_to_ui64_r_minMag(float64, bool, struct softfloat_status_t *); +int32_t f64_to_i32_r_minMag(float64, bool, struct softfloat_status_t *); +int64_t f64_to_i64_r_minMag(float64, bool, struct softfloat_status_t *); +float16 f64_to_f16(float64, struct softfloat_status_t *); +float32 f64_to_f32(float64, struct softfloat_status_t *); +extFloat80_t f64_to_extF80(float64, struct softfloat_status_t *); +float128_t f64_to_f128(float64, struct softfloat_status_t *); +float64 f64_roundToInt(float64, uint8_t, uint8_t, bool, struct softfloat_status_t *); +float64 f64_add(float64, float64, struct softfloat_status_t *); +float64 f64_sub(float64, float64, struct softfloat_status_t *); +float64 f64_mul(float64, float64, struct softfloat_status_t *); +float64 f64_mulAdd(float64, float64, float64, uint8_t op, struct softfloat_status_t *); +float64 f64_div(float64, float64, struct softfloat_status_t *); +float64 f64_min(float64, float64, struct softfloat_status_t *); +float64 f64_max(float64, float64, struct softfloat_status_t *); +float64 f64_scalef(float64, float64, struct softfloat_status_t *); +float64 f64_getExp(float64, struct softfloat_status_t *); +float64 f64_getMant(float64, struct softfloat_status_t *, int, int); +float64 f64_range(float64, float64, bool is_max, bool is_abs, int sign_ctrl, softfloat_status_t *); +float64 f64_frc(float64, struct softfloat_status_t *); +int f64_compare(float64, float64, bool, struct softfloat_status_t *); +float64 f64_sqrt(float64, struct softfloat_status_t *); +softfloat_class_t f64_class(float64); + +bool f64_isSignalingNaN(float64); +bool f64_isNaN(float64); + +bool f64_sign(float64); +int16_t f64_exp(float64); +uint64_t f64_fraction(float64); +float64 f64_denormal_to_zero(float64); + +BX_CPP_INLINE int f64_compare(float64 a, float64 b, softfloat_status_t *status) { return f64_compare(a, b, 0, status); } -BX_CPP_INLINE int f64_compare_quiet(float64_t a, float64_t b, softfloat_status_t *status) { +BX_CPP_INLINE int f64_compare_quiet(float64 a, float64 b, softfloat_status_t *status) { return f64_compare(a, b, 1, status); } -BX_CPP_INLINE float64_t f64_roundToInt(float64_t a, uint8_t scale, struct softfloat_status_t *status) { +BX_CPP_INLINE float64 f64_roundToInt(float64 a, uint8_t scale, struct softfloat_status_t *status) { return f64_roundToInt(a, scale, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE float64_t f64_roundToInt(float64_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE float64 f64_roundToInt(float64 a, struct softfloat_status_t *status) { return f64_roundToInt(a, 0, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE int32_t f64_to_i32(float64_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int32_t f64_to_i32(float64 a, struct softfloat_status_t *status) { return f64_to_i32(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE int64_t f64_to_i64(float64_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int64_t f64_to_i64(float64 a, struct softfloat_status_t *status) { return f64_to_i64(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE int32_t f64_to_i32_round_to_zero(float64_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int32_t f64_to_i32_round_to_zero(float64 a, struct softfloat_status_t *status) { return f64_to_i32_r_minMag(a, true, status); } -BX_CPP_INLINE int64_t f64_to_i64_round_to_zero(float64_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE int64_t f64_to_i64_round_to_zero(float64 a, struct softfloat_status_t *status) { return f64_to_i64_r_minMag(a, true, status); } -BX_CPP_INLINE uint32_t f64_to_ui32(float64_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint32_t f64_to_ui32(float64 a, struct softfloat_status_t *status) { return f64_to_ui32(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE uint64_t f64_to_ui64(float64_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint64_t f64_to_ui64(float64 a, struct softfloat_status_t *status) { return f64_to_ui64(a, softfloat_getRoundingMode(status), true, status); } -BX_CPP_INLINE uint32_t f64_to_ui32_round_to_zero(float64_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint32_t f64_to_ui32_round_to_zero(float64 a, struct softfloat_status_t *status) { return f64_to_ui32_r_minMag(a, true, status); } -BX_CPP_INLINE uint64_t f64_to_ui64_round_to_zero(float64_t a, struct softfloat_status_t *status) { +BX_CPP_INLINE uint64_t f64_to_ui64_round_to_zero(float64 a, struct softfloat_status_t *status) { return f64_to_ui64_r_minMag(a, true, status); } -BX_CPP_INLINE float64_t f64_fmadd(float64_t a, float64_t b, float64_t c, softfloat_status_t *status) { +BX_CPP_INLINE float64 f64_fmadd(float64 a, float64 b, float64 c, softfloat_status_t *status) { return f64_mulAdd(a, b, c, 0, status); } -BX_CPP_INLINE float64_t f64_fmsub(float64_t a, float64_t b, float64_t c, softfloat_status_t *status) { +BX_CPP_INLINE float64 f64_fmsub(float64 a, float64 b, float64 c, softfloat_status_t *status) { return f64_mulAdd(a, b, c, softfloat_muladd_negate_c, status); } -BX_CPP_INLINE float64_t f64_fnmadd(float64_t a, float64_t b, float64_t c, softfloat_status_t *status) { +BX_CPP_INLINE float64 f64_fnmadd(float64 a, float64 b, float64 c, softfloat_status_t *status) { return f64_mulAdd(a, b, c, softfloat_muladd_negate_product, status); } -BX_CPP_INLINE float64_t f64_fnmsub(float64_t a, float64_t b, float64_t c, softfloat_status_t *status) { +BX_CPP_INLINE float64 f64_fnmsub(float64 a, float64 b, float64 c, softfloat_status_t *status) { return f64_mulAdd(a, b, c, softfloat_muladd_negate_result, status); } @@ -590,9 +579,9 @@ uint32_t extF80_to_ui32_r_minMag(extFloat80_t, bool, struct softfloat_status_t * uint64_t extF80_to_ui64_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); int32_t extF80_to_i32_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); int64_t extF80_to_i64_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); -float16_t extF80_to_f16(extFloat80_t, struct softfloat_status_t *); -float32_t extF80_to_f32(extFloat80_t, struct softfloat_status_t *); -float64_t extF80_to_f64(extFloat80_t, struct softfloat_status_t *); +float16 extF80_to_f16(extFloat80_t, struct softfloat_status_t *); +float32 extF80_to_f32(extFloat80_t, struct softfloat_status_t *); +float64 extF80_to_f64(extFloat80_t, struct softfloat_status_t *); float128_t extF80_to_f128(extFloat80_t, struct softfloat_status_t *); extFloat80_t extF80_roundToInt(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); extFloat80_t extF80_add(extFloat80_t, extFloat80_t, struct softfloat_status_t *); @@ -600,7 +589,9 @@ extFloat80_t extF80_sub(extFloat80_t, extFloat80_t, struct softfloat_status_t *) extFloat80_t extF80_mul(extFloat80_t, extFloat80_t, struct softfloat_status_t *); extFloat80_t extF80_div(extFloat80_t, extFloat80_t, struct softfloat_status_t *); extFloat80_t extF80_rem(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_scale(extFloat80_t, extFloat80_t, struct softfloat_status_t *); extFloat80_t extF80_sqrt(extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_extract(extFloat80_t *, struct softfloat_status_t *); int extF80_compare(extFloat80_t, extFloat80_t, int, softfloat_status_t *); softfloat_class_t extF80_class(extFloat80_t); @@ -658,6 +649,10 @@ bool extF80_isUnsupported(extFloat80_t); bool extF80_isSignalingNaN(extFloat80_t); bool extF80_isNaN(extFloat80_t); +bool extF80_sign(float64); +int16_t extF80_exp(float64); +uint64_t extF80_fraction(float64); + /*---------------------------------------------------------------------------- | 128-bit (quadruple-precision) floating-point operations. *----------------------------------------------------------------------------*/ @@ -669,8 +664,8 @@ uint32_t f128_to_ui32_r_minMag(float128_t, bool, struct softfloat_status_t *); uint64_t f128_to_ui64_r_minMag(float128_t, bool, struct softfloat_status_t *); int32_t f128_to_i32_r_minMag(float128_t, bool, struct softfloat_status_t *); int64_t f128_to_i64_r_minMag(float128_t, bool, struct softfloat_status_t *); -float32_t f128_to_f32(float128_t, struct softfloat_status_t *); -float64_t f128_to_f64(float128_t, struct softfloat_status_t *); +float32 f128_to_f32(float128_t, struct softfloat_status_t *); +float64 f128_to_f64(float128_t, struct softfloat_status_t *); extFloat80_t f128_to_extF80(float128_t, struct softfloat_status_t *); float128_t f128_roundToInt(float128_t, uint8_t, bool, struct softfloat_status_t *); float128_t f128_add(float128_t, float128_t, struct softfloat_status_t *); diff --git a/bochs/cpu/softfloat3e/include/softfloat_types.h b/bochs/cpu/softfloat3e/include/softfloat_types.h index e2f819e5d2..5d4b9dd48a 100644 --- a/bochs/cpu/softfloat3e/include/softfloat_types.h +++ b/bochs/cpu/softfloat3e/include/softfloat_types.h @@ -39,45 +39,53 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "config.h" +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point types. +*----------------------------------------------------------------------------*/ +typedef uint16_t float16, bfloat16; +typedef uint32_t float32; +typedef uint64_t float64; + +#ifdef BX_LITTLE_ENDIAN +struct uint128 { uint64_t v0, v64; }; +struct uint64_extra { uint64_t extra, v; }; +struct uint128_extra { uint64_t extra; struct uint128 v; }; +#else +struct uint128 { uint64_t v64, v0; }; +struct uint64_extra { uint64_t v, extra; }; +struct uint128_extra { struct uint128 v; uint64_t extra; }; +#endif + /*---------------------------------------------------------------------------- | Types used to pass 16-bit, 32-bit, 64-bit, and 128-bit floating-point | arguments and results to/from functions. These types must be exactly -| 16 bits, 32 bits, 64 bits, and 128 bits in size, respectively. Where a -| platform has "native" support for IEEE-Standard floating-point formats, -| the types below may, if desired, be defined as aliases for the native types -| (typically 'float' and 'double', and possibly 'long double'). +| 16 bits, 32 bits, 64 bits, and 128 bits in size, respectively. *----------------------------------------------------------------------------*/ -typedef struct f16_t { +struct f16_t { uint16_t v; +#ifdef __cplusplus f16_t(uint64_t v16): v(v16) {} operator uint16_t() const { return v; } -} float16_t; +#endif +}; -typedef struct f32_t { +struct f32_t { uint32_t v; +#ifdef __cplusplus f32_t(uint64_t v32): v(v32) {} operator uint32_t() const { return v; } -} float32_t; +#endif +}; -typedef struct f64_t { +struct f64_t { uint64_t v; +#ifdef __cplusplus f64_t(uint64_t v64): v(v64) {} operator uint64_t() const { return v; } -} float64_t; - -#ifdef BX_BIG_ENDIAN -struct float128 { - Bit64u hi, lo; -}; -#else -struct float128 { - Bit64u lo, hi; -}; #endif +}; -#include "primitiveTypes.h" - -typedef uint128 f128_t, float128_t; +typedef uint128 float128_t; /*---------------------------------------------------------------------------- | The format of an 80-bit extended floating-point number in memory. This @@ -85,35 +93,15 @@ typedef uint128 f128_t, float128_t; | named 'signif'. *----------------------------------------------------------------------------*/ -#ifdef BX_BIG_ENDIAN -struct floatx80 { // leave alignment to compiler - Bit16u exp; - Bit64u fraction; -}; -#else -struct floatx80 { - Bit64u fraction; - Bit16u exp; -}; -#endif - #ifdef BX_LITTLE_ENDIAN struct extFloat80M { uint64_t signif; uint16_t signExp; - - extFloat80M(): signif(0), signExp(0) {} - extFloat80M(struct floatx80 a): signif(a.fraction), signExp(a.exp) {} - operator floatx80() const { floatx80 x; x.fraction = signif; x.exp = signExp; return x; } }; #else struct extFloat80M { uint16_t signExp; uint64_t signif; - - extFloat80M(): signExp(0), signif(0) {} - extFloat80M(struct floatx80 a): signExp(a.exp), signif(a.fraction) {} - operator floatx80() const { floatx80 x; x.fraction = signif; x.exp = signExp; return x; } }; #endif @@ -129,6 +117,6 @@ struct extFloat80M { | must align exactly with the locations in memory of the sign, exponent, and | significand of the native type. *----------------------------------------------------------------------------*/ -typedef struct extFloat80M extFloat80_t; +typedef struct extFloat80M extFloat80_t, floatx80; #endif diff --git a/bochs/cpu/softfloat3e/8086-SSE/specialize.h b/bochs/cpu/softfloat3e/include/specialize.h similarity index 99% rename from bochs/cpu/softfloat3e/8086-SSE/specialize.h rename to bochs/cpu/softfloat3e/include/specialize.h index fb6e0efb85..7345e9c332 100644 --- a/bochs/cpu/softfloat3e/8086-SSE/specialize.h +++ b/bochs/cpu/softfloat3e/include/specialize.h @@ -38,7 +38,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include "primitiveTypes.h" #include "softfloat.h" /*---------------------------------------------------------------------------- @@ -220,14 +219,13 @@ struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN *aPtr); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 +extFloat80_t softfloat_propagateNaNExtF80UI( uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, - struct softfloat_status_t *status -); + struct softfloat_status_t *status); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. diff --git a/bochs/cpu/softfloat3e/isNaN.c b/bochs/cpu/softfloat3e/isNaN.c index c10014d040..895d76f7c9 100644 --- a/bochs/cpu/softfloat3e/isNaN.c +++ b/bochs/cpu/softfloat3e/isNaN.c @@ -38,17 +38,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -bool f16_isNaN(float16_t a) +bool f16_isNaN(float16 a) { return isNaNF16UI(a); } -bool f32_isNaN(float32_t a) +bool f32_isNaN(float32 a) { return isNaNF32UI(a); } -bool f64_isNaN(float64_t a) +bool f64_isNaN(float64 a) { return isNaNF64UI(a); } diff --git a/bochs/cpu/softfloat3e/isSignalingNaN.c b/bochs/cpu/softfloat3e/isSignalingNaN.c index 4e0a58acc3..fc9b008bf0 100644 --- a/bochs/cpu/softfloat3e/isSignalingNaN.c +++ b/bochs/cpu/softfloat3e/isSignalingNaN.c @@ -38,17 +38,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -bool f16_isSignalingNaN(float16_t a) +bool f16_isSignalingNaN(float16 a) { return softfloat_isSigNaNF16UI(a); } -bool f32_isSignalingNaN(float32_t a) +bool f32_isSignalingNaN(float32 a) { return softfloat_isSigNaNF32UI(a); } -bool f64_isSignalingNaN(float64_t a) +bool f64_isSignalingNaN(float64 a) { return softfloat_isSigNaNF64UI(a); } diff --git a/bochs/cpu/softfloat3e/s_add128.c b/bochs/cpu/softfloat3e/s_add128.c index 2c234fbd0e..8efabb8501 100644 --- a/bochs/cpu/softfloat3e/s_add128.c +++ b/bochs/cpu/softfloat3e/s_add128.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_add128 diff --git a/bochs/cpu/softfloat3e/s_addMagsExtF80.c b/bochs/cpu/softfloat3e/s_addMagsExtF80.c index b955805667..9920bbb592 100644 --- a/bochs/cpu/softfloat3e/s_addMagsExtF80.c +++ b/bochs/cpu/softfloat3e/s_addMagsExtF80.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" @@ -50,7 +51,6 @@ extFloat80_t softfloat_addMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB struct exp32_sig64 normExpSig; int32_t expZ; struct uint64_extra sig64Extra; - struct uint128 uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ @@ -143,6 +143,5 @@ extFloat80_t softfloat_addMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: - uiZ = softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); - return packToExtF80(uiZ.v64, uiZ.v0); + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); } diff --git a/bochs/cpu/softfloat3e/s_addMagsF128.c b/bochs/cpu/softfloat3e/s_addMagsF128.c index 6bae85ba08..b831796cc4 100644 --- a/bochs/cpu/softfloat3e/s_addMagsF128.c +++ b/bochs/cpu/softfloat3e/s_addMagsF128.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" float128_t softfloat_addMagsF128(uint64_t uiA64, uint64_t uiA0, uint64_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status) diff --git a/bochs/cpu/softfloat3e/s_addMagsF16.c b/bochs/cpu/softfloat3e/s_addMagsF16.c index 00835b9026..022f254a80 100644 --- a/bochs/cpu/softfloat3e/s_addMagsF16.c +++ b/bochs/cpu/softfloat3e/s_addMagsF16.c @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -float16_t softfloat_addMagsF16(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status) +float16 softfloat_addMagsF16(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status) { int8_t expA; uint16_t sigA; diff --git a/bochs/cpu/softfloat3e/s_addMagsF32.c b/bochs/cpu/softfloat3e/s_addMagsF32.c index bc4ea870a3..df902348a4 100644 --- a/bochs/cpu/softfloat3e/s_addMagsF32.c +++ b/bochs/cpu/softfloat3e/s_addMagsF32.c @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" -float32_t softfloat_addMagsF32(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status) +float32 softfloat_addMagsF32(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status) { int16_t expA; uint32_t sigA; diff --git a/bochs/cpu/softfloat3e/s_addMagsF64.c b/bochs/cpu/softfloat3e/s_addMagsF64.c index ec4bd9c486..a315860f6c 100644 --- a/bochs/cpu/softfloat3e/s_addMagsF64.c +++ b/bochs/cpu/softfloat3e/s_addMagsF64.c @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" -float64_t softfloat_addMagsF64(uint64_t uiA, uint64_t uiB, bool signZ, struct softfloat_status_t *status) +float64 softfloat_addMagsF64(uint64_t uiA, uint64_t uiB, bool signZ, struct softfloat_status_t *status) { int16_t expA; uint64_t sigA; diff --git a/bochs/cpu/softfloat3e/s_mul128By32.c b/bochs/cpu/softfloat3e/s_mul128By32.c index 3c0b69588f..920ad57330 100644 --- a/bochs/cpu/softfloat3e/s_mul128By32.c +++ b/bochs/cpu/softfloat3e/s_mul128By32.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_mul128By32 diff --git a/bochs/cpu/softfloat3e/s_mul128To256M.c b/bochs/cpu/softfloat3e/s_mul128To256M.c index 2d8fa02e6f..25ae9fb791 100644 --- a/bochs/cpu/softfloat3e/s_mul128To256M.c +++ b/bochs/cpu/softfloat3e/s_mul128To256M.c @@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define softfloat_mul128To256M softfloat_mul128To256M #include "primitives.h" +#include "primitiveTypes.h" void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr) diff --git a/bochs/cpu/softfloat3e/s_mul64ByShifted32To128.c b/bochs/cpu/softfloat3e/s_mul64ByShifted32To128.c index fe5ea67e59..90938ac797 100644 --- a/bochs/cpu/softfloat3e/s_mul64ByShifted32To128.c +++ b/bochs/cpu/softfloat3e/s_mul64ByShifted32To128.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_mul64ByShifted32To128 diff --git a/bochs/cpu/softfloat3e/s_mul64To128.c b/bochs/cpu/softfloat3e/s_mul64To128.c index f1a723bb8b..aa0b57a128 100644 --- a/bochs/cpu/softfloat3e/s_mul64To128.c +++ b/bochs/cpu/softfloat3e/s_mul64To128.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_mul64To128 diff --git a/bochs/cpu/softfloat3e/s_mulAddF128.c b/bochs/cpu/softfloat3e/s_mulAddF128.c deleted file mode 100644 index cdb4311ff6..0000000000 --- a/bochs/cpu/softfloat3e/s_mulAddF128.c +++ /dev/null @@ -1,331 +0,0 @@ -/*============================================================================ - -This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic -Package, Release 3e, by John R. Hauser. - -Copyright 2011, 2012, 2013, 2014, 2015, 2016 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. - -=============================================================================*/ - -#include -#include -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float128_t - softfloat_mulAddF128( - uint64_t uiA64, - uint64_t uiA0, - uint64_t uiB64, - uint64_t uiB0, - uint64_t uiC64, - uint64_t uiC0, - uint8_t op, - struct softfloat_status_t *status -) -{ - bool signA; - int32_t expA; - struct uint128 sigA; - bool signB; - int32_t expB; - struct uint128 sigB; - bool signC; - int32_t expC; - struct uint128 sigC; - bool signZ; - uint64_t magBits; - struct uint128 uiZ; - struct exp32_sig128 normExpSig; - int32_t expZ; - uint64_t sig256Z[4]; - struct uint128 sigZ; - int32_t shiftDist, expDiff; - struct uint128 x128; - uint64_t sig256C[4]; - static uint64_t zero256[4] = INIT_UINTM4(0, 0, 0, 0); - uint64_t sigZExtra, sig256Z0; - - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - signA = signF128UI64(uiA64); - expA = expF128UI64(uiA64); - sigA.v64 = fracF128UI64(uiA64); - sigA.v0 = uiA0; - signB = signF128UI64(uiB64); - expB = expF128UI64(uiB64); - sigB.v64 = fracF128UI64(uiB64); - sigB.v0 = uiB0; - signC = signF128UI64(uiC64) ^ ((op & softfloat_mulAdd_subC) != 0); - expC = expF128UI64(uiC64); - sigC.v64 = fracF128UI64(uiC64); - sigC.v0 = uiC0; - signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (expA == 0x7FFF) { - if ((sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))) { - goto propagateNaN_ABC; - } - magBits = expB | sigB.v64 | sigB.v0; - goto infProdArg; - } - if (expB == 0x7FFF) { - if (sigB.v64 | sigB.v0) goto propagateNaN_ABC; - magBits = expA | sigA.v64 | sigA.v0; - goto infProdArg; - } - if (expC == 0x7FFF) { - if (sigC.v64 | sigC.v0) { - uiZ.v64 = 0; - uiZ.v0 = 0; - goto propagateNaN_ZC; - } - uiZ.v64 = uiC64; - uiZ.v0 = uiC0; - return uiZ; - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (! expA) { - if (! (sigA.v64 | sigA.v0)) goto zeroProd; - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0); - expA = normExpSig.exp; - sigA = normExpSig.sig; - } - if (! expB) { - if (! (sigB.v64 | sigB.v0)) goto zeroProd; - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0); - expB = normExpSig.exp; - sigB = normExpSig.sig; - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - expZ = expA + expB - 0x3FFE; - sigA.v64 |= UINT64_C(0x0001000000000000); - sigB.v64 |= UINT64_C(0x0001000000000000); - sigA = softfloat_shortShiftLeft128(sigA.v64, sigA.v0, 8); - sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 15); - softfloat_mul128To256M(sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z); - sigZ.v64 = sig256Z[indexWord(4, 3)]; - sigZ.v0 = sig256Z[indexWord(4, 2)]; - shiftDist = 0; - if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { - --expZ; - shiftDist = -1; - } - if (! expC) { - if (! (sigC.v64 | sigC.v0)) { - shiftDist += 8; - goto sigZ; - } - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF128Sig(sigC.v64, sigC.v0); - expC = normExpSig.exp; - sigC = normExpSig.sig; - } - sigC.v64 |= UINT64_C(0x0001000000000000); - sigC = softfloat_shortShiftLeft128(sigC.v64, sigC.v0, 8); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - expDiff = expZ - expC; - if (expDiff < 0) { - expZ = expC; - if ((signZ == signC) || (expDiff < -1)) { - shiftDist -= expDiff; - if (shiftDist) { - sigZ = softfloat_shiftRightJam128(sigZ.v64, sigZ.v0, shiftDist); - } - } else { - if (! shiftDist) { - x128 = softfloat_shortShiftRight128(sig256Z[indexWord(4, 1)], sig256Z[indexWord(4, 0)], 1); - sig256Z[indexWord(4, 1)] = (sigZ.v0<<63) | x128.v64; - sig256Z[indexWord(4, 0)] = x128.v0; - sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, 1); - sig256Z[indexWord(4, 3)] = sigZ.v64; - sig256Z[indexWord(4, 2)] = sigZ.v0; - } - } - } else { - if (shiftDist) softfloat_add256M(sig256Z, sig256Z, sig256Z); - if (! expDiff) { - sigZ.v64 = sig256Z[indexWord(4, 3)]; - sigZ.v0 = sig256Z[indexWord(4, 2)]; - } else { - sig256C[indexWord(4, 3)] = sigC.v64; - sig256C[indexWord(4, 2)] = sigC.v0; - sig256C[indexWord(4, 1)] = 0; - sig256C[indexWord(4, 0)] = 0; - softfloat_shiftRightJam256M(sig256C, expDiff, sig256C); - } - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - shiftDist = 8; - if (signZ == signC) { - /*-------------------------------------------------------------------- - *--------------------------------------------------------------------*/ - if (expDiff <= 0) { - sigZ = softfloat_add128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0); - } else { - softfloat_add256M(sig256Z, sig256C, sig256Z); - sigZ.v64 = sig256Z[indexWord(4, 3)]; - sigZ.v0 = sig256Z[indexWord(4, 2)]; - } - if (sigZ.v64 & UINT64_C(0x0200000000000000)) { - ++expZ; - shiftDist = 9; - } - } else { - /*-------------------------------------------------------------------- - *--------------------------------------------------------------------*/ - if (expDiff < 0) { - signZ = signC; - if (expDiff < -1) { - sigZ = softfloat_sub128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0); - sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)]; - if (sigZExtra) { - sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, 0, 1); - } - if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { - --expZ; - shiftDist = 7; - } - goto shiftRightRoundPack; - } else { - sig256C[indexWord(4, 3)] = sigC.v64; - sig256C[indexWord(4, 2)] = sigC.v0; - sig256C[indexWord(4, 1)] = 0; - sig256C[indexWord(4, 0)] = 0; - softfloat_sub256M(sig256C, sig256Z, sig256Z); - } - } else if (! expDiff) { - sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, sigC.v64, sigC.v0); - if (! (sigZ.v64 | sigZ.v0) && ! sig256Z[indexWord(4, 1)] && ! sig256Z[indexWord(4, 0)]) { - goto completeCancellation; - } - sig256Z[indexWord(4, 3)] = sigZ.v64; - sig256Z[indexWord(4, 2)] = sigZ.v0; - if (sigZ.v64 & UINT64_C(0x8000000000000000)) { - signZ = ! signZ; - softfloat_sub256M(zero256, sig256Z, sig256Z); - } - } else { - softfloat_sub256M(sig256Z, sig256C, sig256Z); - if (1 < expDiff) { - sigZ.v64 = sig256Z[indexWord(4, 3)]; - sigZ.v0 = sig256Z[indexWord(4, 2)]; - if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { - --expZ; - shiftDist = 7; - } - goto sigZ; - } - } - /*-------------------------------------------------------------------- - *--------------------------------------------------------------------*/ - sigZ.v64 = sig256Z[indexWord(4, 3)]; - sigZ.v0 = sig256Z[indexWord(4, 2)]; - sigZExtra = sig256Z[indexWord(4, 1)]; - sig256Z0 = sig256Z[indexWord(4, 0)]; - if (sigZ.v64) { - if (sig256Z0) sigZExtra |= 1; - } else { - expZ -= 64; - sigZ.v64 = sigZ.v0; - sigZ.v0 = sigZExtra; - sigZExtra = sig256Z0; - if (! sigZ.v64) { - expZ -= 64; - sigZ.v64 = sigZ.v0; - sigZ.v0 = sigZExtra; - sigZExtra = 0; - if (! sigZ.v64) { - expZ -= 64; - sigZ.v64 = sigZ.v0; - sigZ.v0 = 0; - } - } - } - shiftDist = softfloat_countLeadingZeros64(sigZ.v64); - expZ += 7 - shiftDist; - shiftDist = 15 - shiftDist; - if (0 < shiftDist) goto shiftRightRoundPack; - if (shiftDist) { - shiftDist = -shiftDist; - sigZ = softfloat_shortShiftLeft128(sigZ.v64, sigZ.v0, shiftDist); - x128 = softfloat_shortShiftLeft128(0, sigZExtra, shiftDist); - sigZ.v0 |= x128.v64; - sigZExtra = x128.v0; - } - goto roundPack; - } - sigZ: - sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)]; - shiftRightRoundPack: - sigZExtra = (uint64_t) (sigZ.v0<<(64 - shiftDist)) | (sigZExtra != 0); - sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, shiftDist); - roundPack: - return softfloat_roundPackToF128(signZ, expZ - 1, sigZ.v64, sigZ.v0, sigZExtra, status); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - propagateNaN_ABC: - uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); - goto propagateNaN_ZC; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - infProdArg: - if ((sigC.v64 | sigC.v0) && expC == 0x7FFF) goto propagateNaN_ZC; - if (magBits) { - uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0); - uiZ.v0 = 0; - if (expC != 0x7FFF) return uiZ; - if (signZ == signC) return uiZ; - } - softfloat_raiseFlags(status, softfloat_flag_invalid); - uiZ.v64 = defaultNaNF128UI64; - uiZ.v0 = defaultNaNF128UI0; - propagateNaN_ZC: - uiZ = softfloat_propagateNaNF128UI(uiZ.v64, uiZ.v0, uiC64, uiC0, status); - return uiZ; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - zeroProd: - uiZ.v64 = uiC64; - uiZ.v0 = uiC0; - if (! (expC | sigC.v64 | sigC.v0) && (signZ != signC)) { - completeCancellation: - uiZ.v64 = packToF128UI64((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); - uiZ.v0 = 0; - } - return uiZ; -} diff --git a/bochs/cpu/softfloat3e/s_mulAddF16.c b/bochs/cpu/softfloat3e/s_mulAddF16.c deleted file mode 100644 index 5e765c945a..0000000000 --- a/bochs/cpu/softfloat3e/s_mulAddF16.c +++ /dev/null @@ -1,227 +0,0 @@ -/*============================================================================ - -This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic -Package, Release 3e, by John R. Hauser. - -Copyright 2011, 2012, 2013, 2014, 2015, 2016 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. - -=============================================================================*/ - -#include -#include -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float16_t softfloat_mulAddF16(uint16_t uiA, uint16_t uiB, uint16_t uiC, uint8_t op, struct softfloat_status_t *status) -{ - bool signA; - int8_t expA; - uint16_t sigA; - bool signB; - int8_t expB; - uint16_t sigB; - bool signC; - int8_t expC; - uint16_t sigC; - bool signProd; - uint16_t magBits, uiZ; - struct exp8_sig16 normExpSig; - int8_t expProd; - uint32_t sigProd; - bool signZ; - int8_t expZ; - uint16_t sigZ; - int8_t expDiff; - uint32_t sig32Z, sig32C; - int8_t shiftDist; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - signA = signF16UI(uiA); - expA = expF16UI(uiA); - sigA = fracF16UI(uiA); - signB = signF16UI(uiB); - expB = expF16UI(uiB); - sigB = fracF16UI(uiB); - signC = signF16UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); - expC = expF16UI(uiC); - sigC = fracF16UI(uiC); - signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - bool aisNaN = (expA == 0x1F) && sigA; - bool bisNaN = (expB == 0x1F) && sigB; - bool cisNaN = (expC == 0x1F) && sigC; - if (aisNaN | bisNaN | cisNaN) { - uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF16UI(uiA, uiB, status) : 0; - return softfloat_propagateNaNF16UI(uiZ, uiC, status); - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (softfloat_denormalsAreZeros(status)) { - if (!expA) sigA = 0; - if (!expB) sigB = 0; - if (!expC) sigC = 0; - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (expA == 0x1F) { - magBits = expB | sigB; - goto infProdArg; - } - if (expB == 0x1F) { - magBits = expA | sigA; - goto infProdArg; - } - if (expC == 0x1F) { - if ((sigA && !expA) || (sigB && !expB)) { - softfloat_raiseFlags(status, softfloat_flag_denormal); - } - return packToF16UI(signC, 0x1F, 0); - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (! expA) { - if (! sigA) goto zeroProd; - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF16Sig(sigA); - expA = normExpSig.exp; - sigA = normExpSig.sig; - } - if (! expB) { - if (! sigB) goto zeroProd; - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF16Sig(sigB); - expB = normExpSig.exp; - sigB = normExpSig.sig; - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - expProd = expA + expB - 0xE; - sigA = (sigA | 0x0400)<<4; - sigB = (sigB | 0x0400)<<4; - sigProd = (uint32_t) sigA * sigB; - if (sigProd < 0x20000000) { - --expProd; - sigProd <<= 1; - } - signZ = signProd; - if (! expC) { - if (! sigC) { - expZ = expProd - 1; - sigZ = sigProd>>15 | ((sigProd & 0x7FFF) != 0); - goto roundPack; - } - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF16Sig(sigC); - expC = normExpSig.exp; - sigC = normExpSig.sig; - } - sigC = (sigC | 0x0400)<<3; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - expDiff = expProd - expC; - if (signProd == signC) { - /*-------------------------------------------------------------------- - *--------------------------------------------------------------------*/ - if (expDiff <= 0) { - expZ = expC; - sigZ = sigC + softfloat_shiftRightJam32(sigProd, 16 - expDiff); - } else { - expZ = expProd; - sig32Z = sigProd + softfloat_shiftRightJam32((uint32_t) sigC<<16, expDiff); - sigZ = sig32Z>>16 | ((sig32Z & 0xFFFF) != 0); - } - if (sigZ < 0x4000) { - --expZ; - sigZ <<= 1; - } - } else { - /*-------------------------------------------------------------------- - *--------------------------------------------------------------------*/ - sig32C = (uint32_t) sigC<<16; - if (expDiff < 0) { - signZ = signC; - expZ = expC; - sig32Z = sig32C - softfloat_shiftRightJam32(sigProd, -expDiff); - } else if (! expDiff) { - expZ = expProd; - sig32Z = sigProd - sig32C; - if (! sig32Z) goto completeCancellation; - if (sig32Z & 0x80000000) { - signZ = ! signZ; - sig32Z = -sig32Z; - } - } else { - expZ = expProd; - sig32Z = sigProd - softfloat_shiftRightJam32(sig32C, expDiff); - } - shiftDist = softfloat_countLeadingZeros32(sig32Z) - 1; - expZ -= shiftDist; - shiftDist -= 16; - if (shiftDist < 0) { - sigZ = sig32Z>>(-shiftDist) | ((uint32_t) (sig32Z<<(shiftDist & 31)) != 0); - } else { - sigZ = (uint16_t) sig32Z< -#include -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float32_t softfloat_mulAddF32(uint32_t uiA, uint32_t uiB, uint32_t uiC, uint8_t op, struct softfloat_status_t *status) -{ - bool signA; - int16_t expA; - uint32_t sigA; - bool signB; - int16_t expB; - uint32_t sigB; - bool signC; - int16_t expC; - uint32_t sigC; - bool signProd; - uint32_t magBits, uiZ; - struct exp16_sig32 normExpSig; - int16_t expProd; - uint64_t sigProd; - bool signZ; - int16_t expZ; - uint32_t sigZ; - int16_t expDiff; - uint64_t sig64Z, sig64C; - int8_t shiftDist; - - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - signA = signF32UI(uiA); - expA = expF32UI(uiA); - sigA = fracF32UI(uiA); - signB = signF32UI(uiB); - expB = expF32UI(uiB); - sigB = fracF32UI(uiB); - signC = signF32UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); - expC = expF32UI(uiC); - sigC = fracF32UI(uiC); - signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - bool aisNaN = (expA == 0xFF) && sigA; - bool bisNaN = (expB == 0xFF) && sigB; - bool cisNaN = (expC == 0xFF) && sigC; - if (aisNaN | bisNaN | cisNaN) { - uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF32UI(uiA, uiB, status) : 0; - return softfloat_propagateNaNF32UI(uiZ, uiC, status); - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (softfloat_denormalsAreZeros(status)) { - if (!expA) sigA = 0; - if (!expB) sigB = 0; - if (!expC) sigC = 0; - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (expA == 0xFF) { - magBits = expB | sigB; - goto infProdArg; - } - if (expB == 0xFF) { - magBits = expA | sigA; - goto infProdArg; - } - if (expC == 0xFF) { - if ((sigA && !expA) || (sigB && !expB)) { - softfloat_raiseFlags(status, softfloat_flag_denormal); - } - return packToF32UI(signC, 0xFF, 0); - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (! expA) { - if (! sigA) goto zeroProd; - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF32Sig(sigA); - expA = normExpSig.exp; - sigA = normExpSig.sig; - } - if (! expB) { - if (! sigB) goto zeroProd; - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF32Sig(sigB); - expB = normExpSig.exp; - sigB = normExpSig.sig; - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - expProd = expA + expB - 0x7E; - sigA = (sigA | 0x00800000)<<7; - sigB = (sigB | 0x00800000)<<7; - sigProd = (uint64_t) sigA * sigB; - if (sigProd < UINT64_C(0x2000000000000000)) { - --expProd; - sigProd <<= 1; - } - signZ = signProd; - if (! expC) { - if (! sigC) { - expZ = expProd - 1; - sigZ = softfloat_shortShiftRightJam64(sigProd, 31); - goto roundPack; - } - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF32Sig(sigC); - expC = normExpSig.exp; - sigC = normExpSig.sig; - } - sigC = (sigC | 0x00800000)<<6; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - expDiff = expProd - expC; - if (signProd == signC) { - /*-------------------------------------------------------------------- - *--------------------------------------------------------------------*/ - if (expDiff <= 0) { - expZ = expC; - sigZ = sigC + softfloat_shiftRightJam64(sigProd, 32 - expDiff); - } else { - expZ = expProd; - sig64Z = sigProd + softfloat_shiftRightJam64((uint64_t) sigC<<32, expDiff); - sigZ = softfloat_shortShiftRightJam64(sig64Z, 32); - } - if (sigZ < 0x40000000) { - --expZ; - sigZ <<= 1; - } - } else { - /*-------------------------------------------------------------------- - *--------------------------------------------------------------------*/ - sig64C = (uint64_t) sigC<<32; - if (expDiff < 0) { - signZ = signC; - expZ = expC; - sig64Z = sig64C - softfloat_shiftRightJam64(sigProd, -expDiff); - } else if (! expDiff) { - expZ = expProd; - sig64Z = sigProd - sig64C; - if (! sig64Z) goto completeCancellation; - if (sig64Z & UINT64_C(0x8000000000000000)) { - signZ = ! signZ; - sig64Z = -sig64Z; - } - } else { - expZ = expProd; - sig64Z = sigProd - softfloat_shiftRightJam64(sig64C, expDiff); - } - shiftDist = softfloat_countLeadingZeros64(sig64Z) - 1; - expZ -= shiftDist; - shiftDist -= 32; - if (shiftDist < 0) { - sigZ = softfloat_shortShiftRightJam64(sig64Z, -shiftDist); - } else { - sigZ = (uint32_t) sig64Z< -#include -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float64_t softfloat_mulAddF64(uint64_t uiA, uint64_t uiB, uint64_t uiC, uint8_t op, struct softfloat_status_t *status) -{ - bool signA; - int16_t expA; - uint64_t sigA; - bool signB; - int16_t expB; - uint64_t sigB; - bool signC; - int16_t expC; - uint64_t sigC; - bool signZ; - uint64_t magBits, uiZ; - struct exp16_sig64 normExpSig; - int16_t expZ; - struct uint128 sig128Z; - uint64_t sigZ; - int16_t expDiff; - struct uint128 sig128C; - int8_t shiftDist; - - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - signA = signF64UI(uiA); - expA = expF64UI(uiA); - sigA = fracF64UI(uiA); - signB = signF64UI(uiB); - expB = expF64UI(uiB); - sigB = fracF64UI(uiB); - signC = signF64UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); - expC = expF64UI(uiC); - sigC = fracF64UI(uiC); - signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - bool aisNaN = (expA == 0x7FF) && sigA; - bool bisNaN = (expB == 0x7FF) && sigB; - bool cisNaN = (expC == 0x7FF) && sigC; - if (aisNaN | bisNaN | cisNaN) { - uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF64UI(uiA, uiB, status) : 0; - return softfloat_propagateNaNF64UI(uiZ, uiC, status); - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (softfloat_denormalsAreZeros(status)) { - if (!expA) sigA = 0; - if (!expB) sigB = 0; - if (!expC) sigC = 0; - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (expA == 0x7FF) { - magBits = expB | sigB; - goto infProdArg; - } - if (expB == 0x7FF) { - magBits = expA | sigA; - goto infProdArg; - } - if (expC == 0x7FF) { - if ((sigA && !expA) || (sigB && !expB)) { - softfloat_raiseFlags(status, softfloat_flag_denormal); - } - return packToF64UI(signC, 0x7FF, 0); - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (! expA) { - if (! sigA) goto zeroProd; - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF64Sig(sigA); - expA = normExpSig.exp; - sigA = normExpSig.sig; - } - if (! expB) { - if (! sigB) goto zeroProd; - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF64Sig(sigB); - expB = normExpSig.exp; - sigB = normExpSig.sig; - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - expZ = expA + expB - 0x3FE; - sigA = (sigA | UINT64_C(0x0010000000000000))<<10; - sigB = (sigB | UINT64_C(0x0010000000000000))<<10; - sig128Z = softfloat_mul64To128(sigA, sigB); - if (sig128Z.v64 < UINT64_C(0x2000000000000000)) { - --expZ; - sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0); - } - if (! expC) { - if (! sigC) { - --expZ; - sigZ = sig128Z.v64<<1 | (sig128Z.v0 != 0); - goto roundPack; - } - softfloat_raiseFlags(status, softfloat_flag_denormal); - normExpSig = softfloat_normSubnormalF64Sig(sigC); - expC = normExpSig.exp; - sigC = normExpSig.sig; - } - sigC = (sigC | UINT64_C(0x0010000000000000))<<9; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - expDiff = expZ - expC; - if (expDiff < 0) { - expZ = expC; - if ((signZ == signC) || (expDiff < -1)) { - sig128Z.v64 = softfloat_shiftRightJam64(sig128Z.v64, -expDiff); - } else { - sig128Z = softfloat_shortShiftRightJam128(sig128Z.v64, sig128Z.v0, 1); - } - } else if (expDiff) { - sig128C = softfloat_shiftRightJam128(sigC, 0, expDiff); - } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if (signZ == signC) { - /*-------------------------------------------------------------------- - *--------------------------------------------------------------------*/ - if (expDiff <= 0) { - sigZ = (sigC + sig128Z.v64) | (sig128Z.v0 != 0); - } else { - sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0); - sigZ = sig128Z.v64 | (sig128Z.v0 != 0); - } - if (sigZ < UINT64_C(0x4000000000000000)) { - --expZ; - sigZ <<= 1; - } - } else { - /*-------------------------------------------------------------------- - *--------------------------------------------------------------------*/ - if (expDiff < 0) { - signZ = signC; - sig128Z = softfloat_sub128(sigC, 0, sig128Z.v64, sig128Z.v0); - } else if (! expDiff) { - sig128Z.v64 = sig128Z.v64 - sigC; - if (! (sig128Z.v64 | sig128Z.v0)) goto completeCancellation; - if (sig128Z.v64 & UINT64_C(0x8000000000000000)) { - signZ = ! signZ; - sig128Z = softfloat_sub128(0, 0, sig128Z.v64, sig128Z.v0); - } - } else { - sig128Z = softfloat_sub128(sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0); - } - /*-------------------------------------------------------------------- - *--------------------------------------------------------------------*/ - if (! sig128Z.v64) { - expZ -= 64; - sig128Z.v64 = sig128Z.v0; - sig128Z.v0 = 0; - } - shiftDist = softfloat_countLeadingZeros64(sig128Z.v64) - 1; - expZ -= shiftDist; - if (shiftDist < 0) { - sigZ = softfloat_shortShiftRightJam64(sig128Z.v64, -shiftDist); - } else { - sig128Z = softfloat_shortShiftLeft128(sig128Z.v64, sig128Z.v0, shiftDist); - sigZ = sig128Z.v64; - } - sigZ |= (sig128Z.v0 != 0); - } - roundPack: - return softfloat_roundPackToF64(signZ, expZ, sigZ, status); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - infProdArg: - if (magBits) { - uiZ = packToF64UI(signZ, 0x7FF, 0); - if (signZ == signC || expC != 0x7FF) { - if ((sigA && !expA) || (sigB && !expB) || (sigC && !expC)) - softfloat_raiseFlags(status, softfloat_flag_denormal); - return uiZ; - } - } - softfloat_raiseFlags(status, softfloat_flag_invalid); - uiZ = defaultNaNF64UI; - return softfloat_propagateNaNF64UI(uiZ, uiC, status); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - zeroProd: - uiZ = packToF64UI(signC, expC, sigC); - if (!expC && sigC) { - /* Exact zero plus a denormal */ - softfloat_raiseFlags(status, softfloat_flag_denormal); - if (softfloat_flushUnderflowToZero(status)) { - softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); - return packToF64UI(signC, 0, 0); - } - } - if (! (expC | sigC) && (signZ != signC)) { - completeCancellation: - uiZ = packToF64UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); - } - return uiZ; -} diff --git a/bochs/cpu/softfloat3e/s_normRoundPackToExtF80.c b/bochs/cpu/softfloat3e/s_normRoundPackToExtF80.c index a32250019e..9f40351940 100644 --- a/bochs/cpu/softfloat3e/s_normRoundPackToExtF80.c +++ b/bochs/cpu/softfloat3e/s_normRoundPackToExtF80.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" extFloat80_t softfloat_normRoundPackToExtF80( @@ -44,8 +45,7 @@ extFloat80_t uint64_t sig, uint64_t sigExtra, uint8_t roundingPrecision, - struct softfloat_status_t *status -) + struct softfloat_status_t *status) { int8_t shiftDist; struct uint128 sig128; diff --git a/bochs/cpu/softfloat3e/s_normRoundPackToF128.c b/bochs/cpu/softfloat3e/s_normRoundPackToF128.c index 3f726c97c1..ef7571b1c0 100644 --- a/bochs/cpu/softfloat3e/s_normRoundPackToF128.c +++ b/bochs/cpu/softfloat3e/s_normRoundPackToF128.c @@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" float128_t softfloat_normRoundPackToF128(bool sign, int32_t exp, uint64_t sig64, uint64_t sig0, struct softfloat_status_t *status) { diff --git a/bochs/cpu/softfloat3e/s_normRoundPackToF16.c b/bochs/cpu/softfloat3e/s_normRoundPackToF16.c index a6278385b8..0f11ece8dc 100644 --- a/bochs/cpu/softfloat3e/s_normRoundPackToF16.c +++ b/bochs/cpu/softfloat3e/s_normRoundPackToF16.c @@ -36,8 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" -float16_t softfloat_normRoundPackToF16(bool sign, int16_t exp, uint16_t sig, struct softfloat_status_t *status) +float16 softfloat_normRoundPackToF16(bool sign, int16_t exp, uint16_t sig, struct softfloat_status_t *status) { int8_t shiftDist = softfloat_countLeadingZeros16(sig) - 1; exp -= shiftDist; diff --git a/bochs/cpu/softfloat3e/s_normRoundPackToF32.c b/bochs/cpu/softfloat3e/s_normRoundPackToF32.c index 07b9ada2cc..511e8d1958 100644 --- a/bochs/cpu/softfloat3e/s_normRoundPackToF32.c +++ b/bochs/cpu/softfloat3e/s_normRoundPackToF32.c @@ -36,8 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" -float32_t softfloat_normRoundPackToF32(bool sign, int16_t exp, uint32_t sig, struct softfloat_status_t *status) +float32 softfloat_normRoundPackToF32(bool sign, int16_t exp, uint32_t sig, struct softfloat_status_t *status) { int8_t shiftDist = softfloat_countLeadingZeros32(sig) - 1; exp -= shiftDist; diff --git a/bochs/cpu/softfloat3e/s_normRoundPackToF64.c b/bochs/cpu/softfloat3e/s_normRoundPackToF64.c index 078cde3c6e..eefabc598e 100644 --- a/bochs/cpu/softfloat3e/s_normRoundPackToF64.c +++ b/bochs/cpu/softfloat3e/s_normRoundPackToF64.c @@ -36,8 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" -float64_t softfloat_normRoundPackToF64(bool sign, int16_t exp, uint64_t sig, struct softfloat_status_t *status) +float64 softfloat_normRoundPackToF64(bool sign, int16_t exp, uint64_t sig, struct softfloat_status_t *status) { int8_t shiftDist = softfloat_countLeadingZeros64(sig) - 1; exp -= shiftDist; diff --git a/bochs/cpu/softfloat3e/s_normSubnormalExtF80Sig.c b/bochs/cpu/softfloat3e/s_normSubnormalExtF80Sig.c index 69379865d8..a8a958575c 100644 --- a/bochs/cpu/softfloat3e/s_normSubnormalExtF80Sig.c +++ b/bochs/cpu/softfloat3e/s_normSubnormalExtF80Sig.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint64_t sig) { diff --git a/bochs/cpu/softfloat3e/s_normSubnormalF128Sig.c b/bochs/cpu/softfloat3e/s_normSubnormalF128Sig.c index f54ba27c86..3627397471 100644 --- a/bochs/cpu/softfloat3e/s_normSubnormalF128Sig.c +++ b/bochs/cpu/softfloat3e/s_normSubnormalF128Sig.c @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" struct exp32_sig128 softfloat_normSubnormalF128Sig(uint64_t sig64, uint64_t sig0) { diff --git a/bochs/cpu/softfloat3e/s_normSubnormalF16Sig.c b/bochs/cpu/softfloat3e/s_normSubnormalF16Sig.c index 12acd5d2d6..84c86715ad 100644 --- a/bochs/cpu/softfloat3e/s_normSubnormalF16Sig.c +++ b/bochs/cpu/softfloat3e/s_normSubnormalF16Sig.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" struct exp8_sig16 softfloat_normSubnormalF16Sig(uint16_t sig) { diff --git a/bochs/cpu/softfloat3e/s_normSubnormalF32Sig.c b/bochs/cpu/softfloat3e/s_normSubnormalF32Sig.c index fac8358704..1ae4ec74c4 100644 --- a/bochs/cpu/softfloat3e/s_normSubnormalF32Sig.c +++ b/bochs/cpu/softfloat3e/s_normSubnormalF32Sig.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" struct exp16_sig32 softfloat_normSubnormalF32Sig(uint32_t sig) { @@ -46,6 +47,5 @@ struct exp16_sig32 softfloat_normSubnormalF32Sig(uint32_t sig) z.exp = 1 - shiftDist; z.sig = sig< #include "internals.h" +#include "primitives.h" struct exp16_sig64 softfloat_normSubnormalF64Sig(uint64_t sig) { diff --git a/bochs/cpu/softfloat3e/s_roundPackToExtF80.c b/bochs/cpu/softfloat3e/s_roundPackToExtF80.c index 596ba94959..a4ee145539 100644 --- a/bochs/cpu/softfloat3e/s_roundPackToExtF80.c +++ b/bochs/cpu/softfloat3e/s_roundPackToExtF80.c @@ -36,17 +36,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" extFloat80_t - SoftFloat_roundPackToExtF80(bool sign, int32_t exp, uint64_t sig, uint64_t sigExtra, uint8_t roundingPrecision, struct softfloat_status_t *status) + softfloat_roundPackToExtF80(bool sign, int32_t exp, uint64_t sig, uint64_t sigExtra, uint8_t roundingPrecision, struct softfloat_status_t *status) { uint8_t roundingMode; bool roundNearEven; uint64_t roundIncrement, roundMask, roundBits; bool isTiny, doIncrement; struct uint64_extra sig64Extra; - extFloat80_t z; uint64_t sigExact; /*------------------------------------------------------------------------ @@ -76,35 +76,42 @@ extFloat80_t /*---------------------------------------------------------------- *----------------------------------------------------------------*/ isTiny = (exp < 0) || (sig <= (uint64_t) (sig + roundIncrement)); - sig = softfloat_shiftRightJam64(sig, 1 - exp); - sigExact = sig; - roundBits = sig & roundMask; - sig += roundIncrement; - exp = ((sig & UINT64_C(0x8000000000000000)) != 0); - roundIncrement = roundMask + 1; - if (roundNearEven && (roundBits<<1 == roundIncrement)) { - roundMask |= roundIncrement; - } - sig &= ~roundMask; - if (isTiny) { - if (roundBits || (sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow))) - softfloat_raiseFlags(status, softfloat_flag_underflow); + if (isTiny && sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 0x6000; } - if (roundBits) { - softfloat_raiseFlags(status, softfloat_flag_inexact); - if (sig > sigExact) softfloat_setRoundingUp(status); + else { + sig = softfloat_shiftRightJam64(sig, 1 - exp); + roundBits = sig & roundMask; + sigExact = sig; + sig += roundIncrement; + exp = ((sig & UINT64_C(0x8000000000000000)) != 0); + roundIncrement = roundMask + 1; + if (roundNearEven && (roundBits<<1 == roundIncrement)) { + roundMask |= roundIncrement; + } + sig &= ~roundMask; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > sigExact) softfloat_setRoundingUp(status); + if (isTiny) + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + return packToExtF80(sign, exp, sig); } - return packToExtF80(sign, exp, sig); } if ((0x7FFE < exp) || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))) { - goto overflow; + if (! softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_overflow); + exp -= 0x6000; + } + if ((0x7FFE < exp) || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))) { + goto overflow; + } } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ - if (roundBits) { - softfloat_raiseFlags(status, softfloat_flag_inexact); - } sigExact = sig; sig = (uint64_t) (sig + roundIncrement); if (sig < roundIncrement) { @@ -117,7 +124,10 @@ extFloat80_t roundMask |= roundIncrement; } sig &= ~roundMask; - if (sig > sigExact) softfloat_setRoundingUp(status); + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > sigExact) softfloat_setRoundingUp(status); + } return packToExtF80(sign, exp, sig); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ @@ -134,49 +144,60 @@ extFloat80_t /*---------------------------------------------------------------- *----------------------------------------------------------------*/ isTiny = (exp < 0) || ! doIncrement || (sig < UINT64_C(0xFFFFFFFFFFFFFFFF)); - sig64Extra = softfloat_shiftRightJam64Extra(sig, sigExtra, 1 - exp); - exp = 0; - sig = sig64Extra.v; - sigExtra = sig64Extra.extra; - if (isTiny) { - if (sigExtra || (sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow))) - softfloat_raiseFlags(status, softfloat_flag_underflow); + if (isTiny && sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 0x6000; } - if (sigExtra) - softfloat_raiseFlags(status, softfloat_flag_inexact); - doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); - if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { - doIncrement = - (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; - } - if (doIncrement) { - sigExact = sig; - ++sig; - sig &= ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF)) & roundNearEven); - exp = ((sig & UINT64_C(0x8000000000000000)) != 0); - if (sig > sigExact) - softfloat_setRoundingUp(status); + else { + sig64Extra = softfloat_shiftRightJam64Extra(sig, sigExtra, 1 - exp); + exp = 0; + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + if (sigExtra) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (isTiny) + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + doIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; + } + if (doIncrement) { + sigExact = sig; + ++sig; + sig &= ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF)) & roundNearEven); + exp = ((sig & UINT64_C(0x8000000000000000)) != 0); + if (sig > sigExact) + softfloat_setRoundingUp(status); + } + return packToExtF80(sign, exp, sig); } - return packToExtF80(sign, exp, sig); } if ((0x7FFE < exp) || ((exp == 0x7FFE) && (sig == UINT64_C(0xFFFFFFFFFFFFFFFF)) && doIncrement)) { - /*---------------------------------------------------------------- - *----------------------------------------------------------------*/ - roundMask = 0; + if (! softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_overflow); + exp -= 0x6000; + } + if ((0x7FFE < exp) || ((exp == 0x7FFE) && (sig == UINT64_C(0xFFFFFFFFFFFFFFFF)) && doIncrement)) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + roundMask = 0; overflow: - softfloat_raiseFlags(status, softfloat_flag_overflow | softfloat_flag_inexact); - if (roundNearEven - || (roundingMode == softfloat_round_near_maxMag) - || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) - ) { - exp = 0x7FFF; - sig = UINT64_C(0x8000000000000000); - softfloat_setRoundingUp(status); - } else { - exp = 0x7FFE; - sig = ~roundMask; + softfloat_raiseFlags(status, softfloat_flag_overflow | softfloat_flag_inexact); + if (roundNearEven + || (roundingMode == softfloat_round_near_maxMag) + || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) + ) { + exp = 0x7FFF; + sig = UINT64_C(0x8000000000000000); + softfloat_setRoundingUp(status); + } else { + exp = 0x7FFE; + sig = ~roundMask; + } + return packToExtF80(sign, exp, sig); } - return packToExtF80(sign, exp, sig); } } /*------------------------------------------------------------------------ @@ -197,28 +218,8 @@ extFloat80_t if (sig > sigExact) softfloat_setRoundingUp(status); } - return packToExtF80(sign, exp, sig); -} - -extFloat80_t - softfloat_roundPackToExtF80(bool sign, int32_t exp, uint64_t sig, uint64_t sigExtra, uint8_t roundingPrecision, struct softfloat_status_t *status) -{ - softfloat_status_t round_status = *status; - extFloat80_t result = SoftFloat_roundPackToExtF80(sign, exp, sig, sigExtra, roundingPrecision, status); - - // bias unmasked underflow - if (status->softfloat_exceptionFlags & ~status->softfloat_exceptionMasks & softfloat_flag_underflow) { - softfloat_raiseFlags(&round_status, softfloat_flag_underflow); - result = SoftFloat_roundPackToExtF80(sign, exp + 0x6000, sig, sigExtra, roundingPrecision, &round_status); - *status = round_status; + else { + if (! sig) exp = 0; } - - // bias unmasked overflow - if (status->softfloat_exceptionFlags & ~status->softfloat_exceptionMasks & softfloat_flag_overflow) { - softfloat_raiseFlags(&round_status, softfloat_flag_overflow); - result = SoftFloat_roundPackToExtF80(sign, exp - 0x6000, sig, sigExtra, roundingPrecision, &round_status); - *status = round_status; - } - - return result; + return packToExtF80(sign, exp, sig); } diff --git a/bochs/cpu/softfloat3e/s_roundPackToF128.c b/bochs/cpu/softfloat3e/s_roundPackToF128.c index c3aa86ff86..3d63e79d84 100644 --- a/bochs/cpu/softfloat3e/s_roundPackToF128.c +++ b/bochs/cpu/softfloat3e/s_roundPackToF128.c @@ -36,35 +36,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" +// trimmed for Bochs to support only 'softfloat_round_nearest_even' rounding mode float128_t - softfloat_roundPackToF128( - bool sign, - int32_t exp, - uint64_t sig64, - uint64_t sig0, - uint64_t sigExtra, - struct softfloat_status_t *status -) + softfloat_roundPackToF128(bool sign, int32_t exp, uint64_t sig64, uint64_t sig0, uint64_t sigExtra, struct softfloat_status_t *status) { - uint8_t roundingMode; - bool roundNearEven, doIncrement, isTiny; + bool doIncrement, isTiny; struct uint128_extra sig128Extra; - uint64_t uiZ64, uiZ0; struct uint128 sig128; float128_t z; + sigExtra = 0; // artificially reduce precision to match hardware x86 which uses only 67-bit + sig0 &= UINT64_C(0xFFFFFFFF00000000); // do 80 bits for now + /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ - roundingMode = softfloat_getRoundingMode(status); - roundNearEven = (roundingMode == softfloat_round_near_even); doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); - if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { - doIncrement = - (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) - && sigExtra; - } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if (0x7FFD <= (uint32_t) exp) { @@ -82,11 +71,6 @@ float128_t softfloat_raiseFlags(status, softfloat_flag_underflow); } doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); - if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { - doIncrement = - (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) - && sigExtra; - } } else if ((0x7FFD < exp) || ((exp == 0x7FFD) && softfloat_eq128(sig64, sig0, UINT64_C(0x0001FFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF)) && doIncrement) @@ -94,17 +78,9 @@ float128_t /*---------------------------------------------------------------- *----------------------------------------------------------------*/ softfloat_raiseFlags(status, softfloat_flag_overflow | softfloat_flag_inexact); - if (roundNearEven - || (roundingMode == softfloat_round_near_maxMag) - || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) - ) { - uiZ64 = packToF128UI64(sign, 0x7FFF, 0); - uiZ0 = 0; - } else { - uiZ64 = packToF128UI64(sign, 0x7FFE, UINT64_C(0x0000FFFFFFFFFFFF)); - uiZ0 = UINT64_C(0xFFFFFFFFFFFFFFFF); - } - goto uiZ; + z.v64 = packToF128UI64(sign, 0x7FFF, 0); + z.v0 = 0; + return z; } } /*------------------------------------------------------------------------ @@ -115,17 +91,13 @@ float128_t if (doIncrement) { sig128 = softfloat_add128(sig64, sig0, 0, 1); sig64 = sig128.v64; - sig0 = - sig128.v0 & ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF)) & roundNearEven); + sig0 = sig128.v0 & ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF))); } else { if (! (sig64 | sig0)) exp = 0; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ - uiZ64 = packToF128UI64(sign, exp, sig64); - uiZ0 = sig0; - uiZ: - z.v64 = uiZ64; - z.v0 = uiZ0; + z.v64 = packToF128UI64(sign, exp, sig64); + z.v0 = sig0; return z; } diff --git a/bochs/cpu/softfloat3e/s_roundPackToF16.c b/bochs/cpu/softfloat3e/s_roundPackToF16.c index 287a8b2818..1b9bb178a2 100644 --- a/bochs/cpu/softfloat3e/s_roundPackToF16.c +++ b/bochs/cpu/softfloat3e/s_roundPackToF16.c @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float16_t +float16 softfloat_roundPackToF16(bool sign, int16_t exp, uint16_t sig, struct softfloat_status_t *status) { uint8_t roundingMode; diff --git a/bochs/cpu/softfloat3e/s_roundPackToF32.c b/bochs/cpu/softfloat3e/s_roundPackToF32.c index 7e0919e341..2a1de74971 100644 --- a/bochs/cpu/softfloat3e/s_roundPackToF32.c +++ b/bochs/cpu/softfloat3e/s_roundPackToF32.c @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float32_t +float32 softfloat_roundPackToF32(bool sign, int16_t exp, uint32_t sig, struct softfloat_status_t *status) { uint8_t roundingMode; diff --git a/bochs/cpu/softfloat3e/s_roundPackToF64.c b/bochs/cpu/softfloat3e/s_roundPackToF64.c index 2c25a8281b..65dccd181f 100644 --- a/bochs/cpu/softfloat3e/s_roundPackToF64.c +++ b/bochs/cpu/softfloat3e/s_roundPackToF64.c @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float64_t +float64 softfloat_roundPackToF64(bool sign, int16_t exp, uint64_t sig, struct softfloat_status_t *status) { uint8_t roundingMode; diff --git a/bochs/cpu/softfloat3e/s_shiftRightJam128.c b/bochs/cpu/softfloat3e/s_shiftRightJam128.c index 30c395f4c5..11fb26abfc 100644 --- a/bochs/cpu/softfloat3e/s_shiftRightJam128.c +++ b/bochs/cpu/softfloat3e/s_shiftRightJam128.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_shiftRightJam128 diff --git a/bochs/cpu/softfloat3e/s_shiftRightJam128Extra.c b/bochs/cpu/softfloat3e/s_shiftRightJam128Extra.c index 571c7dc4d9..7f4b3fa825 100644 --- a/bochs/cpu/softfloat3e/s_shiftRightJam128Extra.c +++ b/bochs/cpu/softfloat3e/s_shiftRightJam128Extra.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_shiftRightJam128Extra diff --git a/bochs/cpu/softfloat3e/s_shiftRightJam64Extra.c b/bochs/cpu/softfloat3e/s_shiftRightJam64Extra.c index b7f588d4be..a80bafb35a 100644 --- a/bochs/cpu/softfloat3e/s_shiftRightJam64Extra.c +++ b/bochs/cpu/softfloat3e/s_shiftRightJam64Extra.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_shiftRightJam64Extra diff --git a/bochs/cpu/softfloat3e/s_shortShiftLeft128.c b/bochs/cpu/softfloat3e/s_shortShiftLeft128.c index bf9d2c7f65..dc24172cd7 100644 --- a/bochs/cpu/softfloat3e/s_shortShiftLeft128.c +++ b/bochs/cpu/softfloat3e/s_shortShiftLeft128.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_shortShiftLeft128 diff --git a/bochs/cpu/softfloat3e/s_shortShiftRight128.c b/bochs/cpu/softfloat3e/s_shortShiftRight128.c index 23407ce4fa..8b48b1486b 100644 --- a/bochs/cpu/softfloat3e/s_shortShiftRight128.c +++ b/bochs/cpu/softfloat3e/s_shortShiftRight128.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_shortShiftRight128 diff --git a/bochs/cpu/softfloat3e/s_shortShiftRightJam128.c b/bochs/cpu/softfloat3e/s_shortShiftRightJam128.c index 4c015c4bcf..fbda27b708 100644 --- a/bochs/cpu/softfloat3e/s_shortShiftRightJam128.c +++ b/bochs/cpu/softfloat3e/s_shortShiftRightJam128.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_shortShiftRightJam128 diff --git a/bochs/cpu/softfloat3e/s_shortShiftRightJam128Extra.c b/bochs/cpu/softfloat3e/s_shortShiftRightJam128Extra.c index a8a42dd6f9..8c6ddacf8a 100644 --- a/bochs/cpu/softfloat3e/s_shortShiftRightJam128Extra.c +++ b/bochs/cpu/softfloat3e/s_shortShiftRightJam128Extra.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_shortShiftRightJam128Extra diff --git a/bochs/cpu/softfloat3e/s_shortShiftRightJam64Extra.c b/bochs/cpu/softfloat3e/s_shortShiftRightJam64Extra.c index 2c05d2baa3..0bf9afde38 100644 --- a/bochs/cpu/softfloat3e/s_shortShiftRightJam64Extra.c +++ b/bochs/cpu/softfloat3e/s_shortShiftRightJam64Extra.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_shortShiftRightJam64Extra diff --git a/bochs/cpu/softfloat3e/s_sub128.c b/bochs/cpu/softfloat3e/s_sub128.c index dc85d3b672..d5d5f941b8 100644 --- a/bochs/cpu/softfloat3e/s_sub128.c +++ b/bochs/cpu/softfloat3e/s_sub128.c @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include -#include "primitiveTypes.h" +#include "softfloat_types.h" #ifndef softfloat_sub128 diff --git a/bochs/cpu/softfloat3e/s_subMagsExtF80.c b/bochs/cpu/softfloat3e/s_subMagsExtF80.c index e0c1542a97..1aea75e603 100644 --- a/bochs/cpu/softfloat3e/s_subMagsExtF80.c +++ b/bochs/cpu/softfloat3e/s_subMagsExtF80.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" @@ -49,7 +50,7 @@ extFloat80_t int32_t expDiff; int32_t expZ; uint64_t sigExtra; - struct uint128 sig128, uiZ; + struct uint128 sig128; struct exp32_sig64 normExpSig; /*------------------------------------------------------------------------ @@ -150,6 +151,5 @@ extFloat80_t /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: - uiZ = softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); - return packToExtF80(uiZ.v64, uiZ.v0); + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); } diff --git a/bochs/cpu/softfloat3e/s_subMagsF128.c b/bochs/cpu/softfloat3e/s_subMagsF128.c index e26fce6f6d..7b3a7b2b4a 100644 --- a/bochs/cpu/softfloat3e/s_subMagsF128.c +++ b/bochs/cpu/softfloat3e/s_subMagsF128.c @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" diff --git a/bochs/cpu/softfloat3e/s_subMagsF16.c b/bochs/cpu/softfloat3e/s_subMagsF16.c index 143958a3ff..f725dda947 100644 --- a/bochs/cpu/softfloat3e/s_subMagsF16.c +++ b/bochs/cpu/softfloat3e/s_subMagsF16.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float16_t softfloat_subMagsF16(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status) +float16 softfloat_subMagsF16(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status) { int8_t expA; uint16_t sigA; diff --git a/bochs/cpu/softfloat3e/s_subMagsF32.c b/bochs/cpu/softfloat3e/s_subMagsF32.c index 484d7a12f7..95b41fa541 100644 --- a/bochs/cpu/softfloat3e/s_subMagsF32.c +++ b/bochs/cpu/softfloat3e/s_subMagsF32.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float32_t softfloat_subMagsF32(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status) +float32 softfloat_subMagsF32(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status) { int16_t expA; uint32_t sigA; diff --git a/bochs/cpu/softfloat3e/s_subMagsF64.c b/bochs/cpu/softfloat3e/s_subMagsF64.c index a8aaa0e1d7..ea5663c634 100644 --- a/bochs/cpu/softfloat3e/s_subMagsF64.c +++ b/bochs/cpu/softfloat3e/s_subMagsF64.c @@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "internals.h" +#include "primitives.h" #include "specialize.h" #include "softfloat.h" -float64_t softfloat_subMagsF64(uint64_t uiA, uint64_t uiB, bool signZ, struct softfloat_status_t *status) +float64 softfloat_subMagsF64(uint64_t uiA, uint64_t uiB, bool signZ, struct softfloat_status_t *status) { int16_t expA; uint64_t sigA; diff --git a/bochs/cpu/softfloat3e/ui32_to_extF80.c b/bochs/cpu/softfloat3e/ui32_to_extF80.c index d35310d194..80c6d86b01 100644 --- a/bochs/cpu/softfloat3e/ui32_to_extF80.c +++ b/bochs/cpu/softfloat3e/ui32_to_extF80.c @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" extFloat80_t ui32_to_extF80(uint32_t a) diff --git a/bochs/cpu/softfloat3e/ui32_to_f128.c b/bochs/cpu/softfloat3e/ui32_to_f128.c index a4111ae229..6ef8214a8c 100644 --- a/bochs/cpu/softfloat3e/ui32_to_f128.c +++ b/bochs/cpu/softfloat3e/ui32_to_f128.c @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" float128_t ui32_to_f128(uint32_t a) diff --git a/bochs/cpu/softfloat3e/ui32_to_f16.c b/bochs/cpu/softfloat3e/ui32_to_f16.c index 5af4d41d45..bda5b0b6f6 100644 --- a/bochs/cpu/softfloat3e/ui32_to_f16.c +++ b/bochs/cpu/softfloat3e/ui32_to_f16.c @@ -35,9 +35,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float16_t ui32_to_f16(uint32_t a, struct softfloat_status_t *status) +float16 ui32_to_f16(uint32_t a, struct softfloat_status_t *status) { int8_t shiftDist; uint16_t sig; diff --git a/bochs/cpu/softfloat3e/ui32_to_f32.c b/bochs/cpu/softfloat3e/ui32_to_f32.c index b9e97c7b99..ee6d803464 100644 --- a/bochs/cpu/softfloat3e/ui32_to_f32.c +++ b/bochs/cpu/softfloat3e/ui32_to_f32.c @@ -37,7 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "internals.h" #include "softfloat.h" -float32_t ui32_to_f32(uint32_t a, struct softfloat_status_t *status) +float32 ui32_to_f32(uint32_t a, struct softfloat_status_t *status) { if (! a) { return 0; diff --git a/bochs/cpu/softfloat3e/ui32_to_f64.c b/bochs/cpu/softfloat3e/ui32_to_f64.c index 5e2b173ff6..524d64eedf 100644 --- a/bochs/cpu/softfloat3e/ui32_to_f64.c +++ b/bochs/cpu/softfloat3e/ui32_to_f64.c @@ -35,9 +35,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float64_t ui32_to_f64(uint32_t a) +float64 ui32_to_f64(uint32_t a) { if (! a) { return 0; diff --git a/bochs/cpu/softfloat3e/ui64_to_extF80.c b/bochs/cpu/softfloat3e/ui64_to_extF80.c index 149985b744..5bf7549203 100644 --- a/bochs/cpu/softfloat3e/ui64_to_extF80.c +++ b/bochs/cpu/softfloat3e/ui64_to_extF80.c @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" extFloat80_t ui64_to_extF80(uint64_t a) diff --git a/bochs/cpu/softfloat3e/ui64_to_f128.c b/bochs/cpu/softfloat3e/ui64_to_f128.c index 770319c349..91be29f375 100644 --- a/bochs/cpu/softfloat3e/ui64_to_f128.c +++ b/bochs/cpu/softfloat3e/ui64_to_f128.c @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" float128_t ui64_to_f128(uint64_t a) diff --git a/bochs/cpu/softfloat3e/ui64_to_f16.c b/bochs/cpu/softfloat3e/ui64_to_f16.c index 6afdc005c9..f2339e905a 100644 --- a/bochs/cpu/softfloat3e/ui64_to_f16.c +++ b/bochs/cpu/softfloat3e/ui64_to_f16.c @@ -35,9 +35,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float16_t ui64_to_f16(uint64_t a, struct softfloat_status_t *status) +float16 ui64_to_f16(uint64_t a, struct softfloat_status_t *status) { int8_t shiftDist; uint16_t sig; diff --git a/bochs/cpu/softfloat3e/ui64_to_f32.c b/bochs/cpu/softfloat3e/ui64_to_f32.c index 67530f284e..62db84783d 100644 --- a/bochs/cpu/softfloat3e/ui64_to_f32.c +++ b/bochs/cpu/softfloat3e/ui64_to_f32.c @@ -35,9 +35,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float32_t ui64_to_f32(uint64_t a, struct softfloat_status_t *status) +float32 ui64_to_f32(uint64_t a, struct softfloat_status_t *status) { int8_t shiftDist; uint32_t sig; diff --git a/bochs/cpu/softfloat3e/ui64_to_f64.c b/bochs/cpu/softfloat3e/ui64_to_f64.c index f74947aca3..05f849a1a5 100644 --- a/bochs/cpu/softfloat3e/ui64_to_f64.c +++ b/bochs/cpu/softfloat3e/ui64_to_f64.c @@ -35,9 +35,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "internals.h" +#include "primitives.h" #include "softfloat.h" -float64_t ui64_to_f64(uint64_t a, struct softfloat_status_t *status) +float64 ui64_to_f64(uint64_t a, struct softfloat_status_t *status) { if (! a) { return 0; diff --git a/bochs/cpu/sse_move.cc b/bochs/cpu/sse_move.cc index 8b93127182..e9479a5677 100644 --- a/bochs/cpu/sse_move.cc +++ b/bochs/cpu/sse_move.cc @@ -59,7 +59,7 @@ Bit8u BX_CPU_C::pack_FPU_TW(Bit16u twd) return tag_byte; } -Bit16u BX_CPU_C::unpack_FPU_TW(Bit16u tag_byte) +Bit16u unpack_FPU_TW(const i387_t *i387, Bit16u tag_byte) { Bit32u twd = 0; @@ -106,7 +106,7 @@ Bit16u BX_CPU_C::unpack_FPU_TW(Bit16u tag_byte) for(int index = 7;index >= 0; index--, twd <<= 2, tag_byte <<= 1) { if(tag_byte & 0x80) { - const floatx80 &fpu_reg = BX_FPU_REG(index); + const floatx80 &fpu_reg = i387->st_space[index]; twd |= FPU_tagof(fpu_reg); } else { @@ -238,9 +238,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FXSAVE(bxInstruction_c *i) { const floatx80 &fp = BX_READ_FPU_REG(index); - xmm.xmm64u(0) = fp.fraction; + xmm.xmm64u(0) = fp.signif; xmm.xmm64u(1) = 0; - xmm.xmm16u(4) = fp.exp; + xmm.xmm16u(4) = fp.signExp; write_virtual_xmmword(i->seg(), (eaddr+index*16+32) & asize_mask, &xmm); } @@ -276,34 +276,33 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FXRSTOR(bxInstruction_c *i) exception(BX_NM_EXCEPTION, 0); bx_address eaddr = BX_CPU_RESOLVE_ADDR(i); - read_virtual_xmmword_aligned(i->seg(), eaddr, &xmm); - bx_address asize_mask = i->asize_mask(); - BX_CPU_THIS_PTR the_i387.cwd = xmm.xmm16u(0); - BX_CPU_THIS_PTR the_i387.swd = xmm.xmm16u(1); - BX_CPU_THIS_PTR the_i387.tos = (xmm.xmm16u(1) >> 11) & 0x07; + i387_t restore_i387; + + restore_i387.cwd = xmm.xmm16u(0); + restore_i387.swd = xmm.xmm16u(1); + restore_i387.tos = (xmm.xmm16u(1) >> 11) & 0x07; /* always set bit 6 as '1 */ - BX_CPU_THIS_PTR the_i387.cwd = - (BX_CPU_THIS_PTR the_i387.cwd & ~FPU_CW_Reserved_Bits) | 0x0040; + restore_i387.cwd = (restore_i387.cwd & ~FPU_CW_Reserved_Bits) | 0x0040; /* Restore x87 FPU Opcode */ /* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */ - BX_CPU_THIS_PTR the_i387.foo = xmm.xmm16u(3) & 0x7FF; + restore_i387.foo = xmm.xmm16u(3) & 0x7FF; /* Restore x87 FPU IP */ #if BX_SUPPORT_X86_64 if (i->os64L()) { - BX_CPU_THIS_PTR the_i387.fip = xmm.xmm64u(1); - BX_CPU_THIS_PTR the_i387.fcs = 0; + restore_i387.fip = xmm.xmm64u(1); + restore_i387.fcs = 0; } else #endif { - BX_CPU_THIS_PTR the_i387.fip = xmm.xmm32u(2); - BX_CPU_THIS_PTR the_i387.fcs = xmm.xmm16u(6); + restore_i387.fip = xmm.xmm32u(2); + restore_i387.fcs = xmm.xmm16u(6); } Bit32u tag_byte = xmm.xmmubyte(4); @@ -313,38 +312,39 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FXRSTOR(bxInstruction_c *i) #if BX_SUPPORT_X86_64 if (i->os64L()) { - BX_CPU_THIS_PTR the_i387.fdp = xmm.xmm64u(0); - BX_CPU_THIS_PTR the_i387.fds = 0; + restore_i387.fdp = xmm.xmm64u(0); + restore_i387.fds = 0; } else #endif { - BX_CPU_THIS_PTR the_i387.fdp = xmm.xmm32u(0); - BX_CPU_THIS_PTR the_i387.fds = xmm.xmm16u(2); + restore_i387.fdp = xmm.xmm32u(0); + restore_i387.fds = xmm.xmm16u(2); } - if(/* BX_CPU_THIS_PTR cr4.get_OSFXSR() && */ is_cpu_extension_supported(BX_ISA_SSE)) - { - Bit32u new_mxcsr = xmm.xmm32u(2); - if(new_mxcsr & ~MXCSR_MASK) + Bit32u new_mxcsr = xmm.xmm32u(2); + if (is_cpu_extension_supported(BX_ISA_SSE)) { + if (new_mxcsr & ~MXCSR_MASK) { + BX_ERROR(("%s: corrupted MXCSR state restored new_mxcsr=0x%08x", i->getIaOpcodeNameShort(), new_mxcsr)); exception(BX_GP_EXCEPTION, 0); - - BX_MXCSR_REGISTER = new_mxcsr; + } } /* load i387 register file */ for(index=0; index < 8; index++) { floatx80 reg; - reg.fraction = read_virtual_qword(i->seg(), (eaddr+index*16+32) & asize_mask); - reg.exp = read_virtual_word (i->seg(), (eaddr+index*16+40) & asize_mask); + reg.signif = read_virtual_qword(i->seg(), (eaddr+index*16+32) & asize_mask); + reg.signExp = read_virtual_word (i->seg(), (eaddr+index*16+40) & asize_mask); // update tag only if it is not empty - BX_WRITE_FPU_REGISTER_AND_TAG(reg, + restore_i387.FPU_save_regi(reg, IS_TAG_EMPTY(index) ? FPU_Tag_Empty : FPU_tagof(reg), index); } - BX_CPU_THIS_PTR the_i387.twd = unpack_FPU_TW(tag_byte); + restore_i387.twd = unpack_FPU_TW(&restore_i387, tag_byte); + + BX_CPU_THIS_PTR the_i387 = restore_i387; /* check for unmasked exceptions */ if (FPU_PARTIAL_STATUS & ~FPU_CONTROL_WORD & FPU_CW_Exceptions_Mask) { @@ -362,12 +362,15 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FXRSTOR(bxInstruction_c *i) } #endif - /* If the OSFXSR bit in CR4 is not set, the FXRSTOR instruction does - not restore the states of the XMM and MXCSR registers. */ - if(BX_CPU_THIS_PTR cr4.get_OSFXSR() && is_cpu_extension_supported(BX_ISA_SSE)) - { - /* load XMM register file */ - xrstor_sse_state(i, eaddr+160); + if (is_cpu_extension_supported(BX_ISA_SSE)) { + BX_MXCSR_REGISTER = new_mxcsr; + + /* If the OSFXSR bit in CR4 is not set, the FXRSTOR instruction does + not restore the states of the XMM and MXCSR registers. */ + if (BX_CPU_THIS_PTR cr4.get_OSFXSR()) { + /* load XMM register file */ + xrstor_sse_state(i, eaddr+160); + } } #endif diff --git a/bochs/cpu/sse_pfp.cc b/bochs/cpu/sse_pfp.cc index 61a95bd66a..f3ce2ddf4b 100644 --- a/bochs/cpu/sse_pfp.cc +++ b/bochs/cpu/sse_pfp.cc @@ -50,33 +50,45 @@ void BX_CPU_C::check_exceptionsSSE(int exceptions_flags) } } -float_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr) +softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr) { - float_status_t status; + softfloat_status_t status; - status.float_exception_flags = 0; // clear exceptions before execution - status.float_nan_handling_mode = float_first_operand_nan; - status.float_rounding_mode = mxcsr.get_rounding_mode(); + status.softfloat_exceptionFlags = 0; // clear exceptions before execution + status.softfloat_roundingMode = mxcsr.get_rounding_mode(); // if underflow is masked and FUZ is 1, set it to 1, else to 0 - status.flush_underflow_to_zero = + status.softfloat_flush_underflow_to_zero = (mxcsr.get_flush_masked_underflow() && mxcsr.get_UM()) ? 1 : 0; - status.float_exception_masks = mxcsr.get_exceptions_masks(); - status.float_suppress_exception = 0; - status.denormals_are_zeros = mxcsr.get_DAZ(); + status.softfloat_exceptionMasks = mxcsr.get_exceptions_masks(); + status.softfloat_suppressException = 0; + status.softfloat_denormals_are_zeros = mxcsr.get_DAZ(); return status; } -void mxcsr_to_softfloat_status_word_imm_override(float_status_t &status, Bit8u control) +void mxcsr_to_softfloat_status_word_imm_override(softfloat_status_t &status, Bit8u control) { // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) - status.float_rounding_mode = control & 0x3; + status.softfloat_roundingMode = control & 0x3; // ignore precision exception result if (control & 0x8) - status.float_suppress_exception |= float_flag_inexact; + status.softfloat_suppressException |= softfloat_flag_inexact; } +#if BX_SUPPORT_EVEX +// implement SAE and EVEX encoded rounding control +void softfloat_status_word_rc_override(softfloat_status_t &status, bxInstruction_c *i) +{ + /* must be VL512 otherwise EVEX.LL encodes vector length */ + if (i->modC0() && i->getEvexb()) { + status.softfloat_roundingMode = i->getRC(); + status.softfloat_suppressException = softfloat_all_exceptions_mask; + status.softfloat_exceptionMasks = softfloat_all_exceptions_mask; + } +} +#endif + /* Comparison predicate for CMPSS/CMPPS instructions */ static float32_compare_method compare32[8] = { f32_eq_ordered_quiet, @@ -118,13 +130,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPI2PS_VpsQqR(bxInstruction_c *i) BxPackedMmxRegister op = BX_READ_MMX_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); MMXUD0(op) = i32_to_f32(MMXSD0(op), &status); MMXUD1(op) = i32_to_f32(MMXSD1(op), &status); prepareFPU2MMX(); /* cause FPU2MMX state transition */ - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), MMXUQ(op)); #endif @@ -138,12 +150,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPI2PS_VpsQqM(bxInstruction_c *i) bx_address eaddr = BX_CPU_RESOLVE_ADDR(i); BxPackedMmxRegister op = read_virtual_qword(i->seg(), eaddr); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); MMXUD0(op) = i32_to_f32(MMXSD0(op), &status); MMXUD1(op) = i32_to_f32(MMXSD1(op), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), MMXUQ(op)); #endif @@ -211,9 +223,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SD_VsdEdR(bxInstruction_c *i) #if BX_SUPPORT_X86_64 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SD_VsdEqR(bxInstruction_c *i) { - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); float64 result = i64_to_f64(BX_READ_64BIT_REG(i->src()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), result); BX_NEXT_INSTR(i); @@ -230,9 +242,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SD_VsdEqR(bxInstruction_c *i) void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SS_VssEdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); float32 result = i32_to_f32(BX_READ_32BIT_REG(i->src()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), result); #endif @@ -242,9 +254,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SS_VssEdR(bxInstruction_c *i) #if BX_SUPPORT_X86_64 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SS_VssEqR(bxInstruction_c *i) { - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); float32 result = i64_to_f32(BX_READ_64BIT_REG(i->src()), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), result); BX_NEXT_INSTR(i); @@ -275,13 +287,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPS2PI_PqWps(bxInstruction_c *i) op = read_virtual_qword(i->seg(), eaddr); } - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); MMXSD0(op) = f32_to_i32_round_to_zero(MMXUD0(op), &status); MMXSD1(op) = f32_to_i32_round_to_zero(MMXUD1(op), &status); prepareFPU2MMX(); /* cause FPU2MMX state transition */ - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_MMX_REG(i->dst(), op); #endif @@ -316,13 +328,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPD2PI_PqWpd(bxInstruction_c *i) read_virtual_xmmword_aligned(i->seg(), eaddr, &op); } - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); MMXSD0(result) = f64_to_i32_round_to_zero(op.xmm64u(0), &status); MMXSD1(result) = f64_to_i32_round_to_zero(op.xmm64u(1), &status); prepareFPU2MMX(); /* cause FPU2MMX state transition */ - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_MMX_REG(i->dst(), result); #endif @@ -340,10 +352,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTSD2SI_GdWsdR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32s result = f64_to_i32_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) result); #endif @@ -356,10 +368,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTSD2SI_GqWsdR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64s result = f64_to_i64_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), (Bit64u) result); BX_NEXT_INSTR(i); @@ -377,10 +389,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTSS2SI_GdWssR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32s result = f32_to_i32_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) result); #endif @@ -393,10 +405,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTSS2SI_GqWssR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64s result = f32_to_i64_round_to_zero(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), (Bit64u) result); BX_NEXT_INSTR(i); @@ -428,13 +440,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPS2PI_PqWps(bxInstruction_c *i) op = read_virtual_qword(i->seg(), eaddr); } - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); MMXSD0(op) = f32_to_i32(MMXUD0(op), &status); MMXSD1(op) = f32_to_i32(MMXUD1(op), &status); prepareFPU2MMX(); /* cause FPU2MMX state transition */ - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_MMX_REG(i->dst(), op); #endif @@ -472,13 +484,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPD2PI_PqWpd(bxInstruction_c *i) read_virtual_xmmword_aligned(i->seg(), eaddr, &op); } - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); MMXSD0(result) = f64_to_i32(op.xmm64u(0), &status); MMXSD1(result) = f64_to_i32(op.xmm64u(1), &status); prepareFPU2MMX(); /* cause FPU2MMX state transition */ - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_MMX_REG(i->dst(), result); #endif @@ -497,10 +509,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSD2SI_GdWsdR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32s result = f64_to_i32(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) result); #endif @@ -513,10 +525,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSD2SI_GqWsdR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64s result = f64_to_i64(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), (Bit64u) result); BX_NEXT_INSTR(i); @@ -535,10 +547,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSS2SI_GdWssR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit32s result = f32_to_i32(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) result); #endif @@ -551,10 +563,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSS2SI_GqWssR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); Bit64s result = f32_to_i64(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_64BIT_REG(i->dst(), (Bit64u) result); BX_NEXT_INSTR(i); @@ -575,12 +587,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPS2PD_VpdWpsR(bxInstruction_c *i) // use packed register as 64-bit value with convinient accessors op.u64 = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); result.xmm64u(0) = f32_to_f64(op.u32(0), &status); result.xmm64u(1) = f32_to_f64(op.u32(1), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), result); #endif @@ -599,13 +611,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPD2PS_VpsWpdR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op.xmm32u(0) = f64_to_f32(op.xmm64u(0), &status); op.xmm32u(1) = f64_to_f32(op.xmm64u(1), &status); op.xmm64u(1) = 0; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op); #endif @@ -624,9 +636,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSD2SS_VssWsdR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); float32 result = f64_to_f32(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), result); #endif @@ -643,9 +655,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSS2SD_VsdWssR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); float64 result = f32_to_f64(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), result); #endif @@ -664,14 +676,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTDQ2PS_VpsWdqR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op.xmm32u(0) = i32_to_f32(op.xmm32s(0), &status); op.xmm32u(1) = i32_to_f32(op.xmm32s(1), &status); op.xmm32u(2) = i32_to_f32(op.xmm32s(2), &status); op.xmm32u(3) = i32_to_f32(op.xmm32s(3), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op); #endif @@ -690,14 +702,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPS2DQ_VdqWpsR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op.xmm32s(0) = f32_to_i32(op.xmm32u(0), &status); op.xmm32s(1) = f32_to_i32(op.xmm32u(1), &status); op.xmm32s(2) = f32_to_i32(op.xmm32u(2), &status); op.xmm32s(3) = f32_to_i32(op.xmm32u(3), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op); #endif @@ -715,14 +727,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPS2DQ_VdqWpsR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op.xmm32s(0) = f32_to_i32_round_to_zero(op.xmm32u(0), &status); op.xmm32s(1) = f32_to_i32_round_to_zero(op.xmm32u(1), &status); op.xmm32s(2) = f32_to_i32_round_to_zero(op.xmm32u(2), &status); op.xmm32s(3) = f32_to_i32_round_to_zero(op.xmm32u(3), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op); #endif @@ -740,13 +752,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPD2DQ_VqWpdR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op.xmm32s(0) = f64_to_i32_round_to_zero(op.xmm64u(0), &status); op.xmm32s(1) = f64_to_i32_round_to_zero(op.xmm64u(1), &status); op.xmm64u(1) = 0; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op); #endif @@ -765,13 +777,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPD2DQ_VqWpdR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op.xmm32s(0) = f64_to_i32(op.xmm64u(0), &status); op.xmm32s(1) = f64_to_i32(op.xmm64u(1), &status); op.xmm64u(1) = 0; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op); #endif @@ -811,10 +823,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::UCOMISS_VssWssR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int rc = f32_compare_quiet(op1, op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); #endif @@ -831,10 +843,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::UCOMISD_VsdWsdR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int rc = f64_compare_quiet(op1, op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); #endif @@ -851,10 +863,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::COMISS_VssWssR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int rc = f32_compare(op1, op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); #endif @@ -871,10 +883,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::COMISD_VsdWsdR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); softfloat_status_word_rc_override(status, i); int rc = f64_compare(op1, op2, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); #endif @@ -891,9 +903,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTSD_VsdWsdR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op = f64_sqrt(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op); #endif @@ -910,9 +922,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTSS_VssWssR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); op = f32_sqrt(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op); #endif @@ -927,9 +939,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTSS_VssWssR(bxInstruction_c *i) { \ float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ op1 = (func)(op1, op2, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); \ BX_NEXT_INSTR(i); \ } \ @@ -960,9 +972,9 @@ SSE_SCALAR_SINGLE_FP_CPU_LEVEL6(MAXSS_VssWssR, f32_max); { \ float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); \ \ - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); \ op1 = (func)(op1, op2, &status); \ - check_exceptionsSSE(get_exception_flags(status)); \ + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); \ BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); \ BX_NEXT_INSTR(i); \ } \ @@ -995,7 +1007,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPPS_VpsWpsIbR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); int ib = i->Ib() & 7; op1.xmm32u(0) = compare32[ib](op1.xmm32u(0), op2.xmm32u(0), &status) ? 0xFFFFFFFF : 0; @@ -1003,7 +1015,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPPS_VpsWpsIbR(bxInstruction_c *i) op1.xmm32u(2) = compare32[ib](op1.xmm32u(2), op2.xmm32u(2), &status) ? 0xFFFFFFFF : 0; op1.xmm32u(3) = compare32[ib](op1.xmm32u(3), op2.xmm32u(3), &status) ? 0xFFFFFFFF : 0; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op1); #endif @@ -1020,7 +1032,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPPD_VpdWpdIbR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); int ib = i->Ib() & 7; op1.xmm64u(0) = compare64[ib](op1.xmm64u(0), op2.xmm64u(0), &status) ? @@ -1028,7 +1040,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPPD_VpdWpdIbR(bxInstruction_c *i) op1.xmm64u(1) = compare64[ib](op1.xmm64u(1), op2.xmm64u(1), &status) ? BX_CONST64(0xFFFFFFFFFFFFFFFF) : 0; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op1); #endif @@ -1045,7 +1057,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD_VsdWsdIbR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); int ib = i->Ib() & 7; if(compare64[ib](op1, op2, &status)) { @@ -1054,7 +1066,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD_VsdWsdIbR(bxInstruction_c *i) op1 = 0; } - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); #endif @@ -1071,12 +1083,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSS_VssWssIbR(bxInstruction_c *i) #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); int ib = i->Ib() & 7; op1 = compare32[ib](op1, op2, &status) ? 0xFFFFFFFF : 0; - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); #endif @@ -1090,7 +1102,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDPS_VpsWpsIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); mxcsr_to_softfloat_status_word_imm_override(status, i->Ib()); op.xmm32u(0) = f32_roundToInt(op.xmm32u(0), &status); @@ -1098,7 +1110,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDPS_VpsWpsIbR(bxInstruction_c *i) op.xmm32u(2) = f32_roundToInt(op.xmm32u(2), &status); op.xmm32u(3) = f32_roundToInt(op.xmm32u(3), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op); BX_NEXT_INSTR(i); @@ -1109,13 +1121,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDPD_VpdWpdIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); mxcsr_to_softfloat_status_word_imm_override(status, i->Ib()); op.xmm64u(0) = f64_roundToInt(op.xmm64u(0), &status); op.xmm64u(1) = f64_roundToInt(op.xmm64u(1), &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op); BX_NEXT_INSTR(i); @@ -1126,12 +1138,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDSS_VssWssIbR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); mxcsr_to_softfloat_status_word_imm_override(status, i->Ib()); op = f32_roundToInt(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op); BX_NEXT_INSTR(i); @@ -1142,12 +1154,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDSD_VsdWsdIbR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); mxcsr_to_softfloat_status_word_imm_override(status, i->Ib()); op = f64_roundToInt(op, &status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op); BX_NEXT_INSTR(i); @@ -1164,28 +1176,28 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::DPPS_VpsWpsIbR(bxInstruction_c *i) BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src()); Bit8u mask = i->Ib(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); // op1: [A, B, C, D] // op2: [E, F, G, H] // after multiplication: op1 = [EA, BF, CG, DH] xmm_mulps_mask(&op1, &op2, status, mask >> 4); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); // shuffle op2 = [BF, AE, DH, CG] xmm_shufps(&op2, &op1, &op1, 0xb1); // op2 = [(BF+AE), (AE+BF), (DH+CG), (CG+DH)] xmm_addps(&op2, &op1, status); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); // shuffle op1 = [(DH+CG), (CG+DH), (BF+AE), (AE+BF)] xmm_shufpd(&op1, &op2, &op2, 0x1); // op2 = [(BF+AE)+(DH+CG), (AE+BF)+(CG+DH), (DH+CG)+(BF+AE), (CG+DH)+(AE+BF)] xmm_addps_mask(&op2, &op1, status, mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REG(i->dst(), op2); @@ -1203,21 +1215,21 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::DPPD_VpdHpdWpdIbR(bxInstruction_c *i) BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); Bit8u mask = i->Ib(); - float_status_t status = mxcsr_to_softfloat_status_word(MXCSR); + softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR); // op1: [A, B] // op2: [C, D] // after multiplication: op1 = [AC, BD] xmm_mulpd_mask(&op1, &op2, status, mask >> 4); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); // shuffle op2 = [BD, AC] xmm_shufpd(&op2, &op1, &op1, 0x1); // op1 = [AC+BD, BD+AC] xmm_addpd_mask(&op1, &op2, status, mask); - check_exceptionsSSE(get_exception_flags(status)); + check_exceptionsSSE(softfloat_getExceptionFlags(&status)); BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); diff --git a/bochs/cpu/sse_rcp.cc b/bochs/cpu/sse_rcp.cc index 43f2b4e5dd..e8a777a0d9 100644 --- a/bochs/cpu/sse_rcp.cc +++ b/bochs/cpu/sse_rcp.cc @@ -28,6 +28,7 @@ #if BX_CPU_LEVEL >= 6 +#include "softfloat3e/include/softfloat.h" #include "fpu/softfloat-specialize.h" static Bit16u rcp_table[2048] = { @@ -296,19 +297,19 @@ float32 approximate_rcp(float32 op) bool sign = f32_sign(op); switch(op_class) { - case float_zero: - case float_denormal: + case softfloat_zero: + case softfloat_denormal: return packFloat32(sign, 0xFF, 0); - case float_negative_inf: - case float_positive_inf: + case softfloat_negative_inf: + case softfloat_positive_inf: return packFloat32(sign, 0, 0); - case float_SNaN: - case float_QNaN: + case softfloat_SNaN: + case softfloat_QNaN: return convert_to_QNaN(op); - case float_normalized: + case softfloat_normalized: break; } @@ -642,21 +643,21 @@ float32 approximate_rsqrt(float32 op) bool sign = f32_sign(op); switch(op_class) { - case float_zero: - case float_denormal: + case softfloat_zero: + case softfloat_denormal: return packFloat32(sign, 0xFF, 0); - case float_positive_inf: + case softfloat_positive_inf: return 0; - case float_negative_inf: + case softfloat_negative_inf: return float32_default_nan; - case float_SNaN: - case float_QNaN: + case softfloat_SNaN: + case softfloat_QNaN: return convert_to_QNaN(op); - case float_normalized: + case softfloat_normalized: break; }; diff --git a/bochs/cpu/uintr.cc b/bochs/cpu/uintr.cc index 9cce84a846..a7646b2d05 100644 --- a/bochs/cpu/uintr.cc +++ b/bochs/cpu/uintr.cc @@ -116,7 +116,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::UIRET(bxInstruction_c *i) BX_CPU_THIS_PTR monitor.reset_monitor(); #endif - BX_CPU_THIS_PTR uintr.UIF = 1; + if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_FLEXIBLE_UIRET)) + BX_CPU_THIS_PTR uintr.UIF = (new_eflags & 0x2) != 0; + else + BX_CPU_THIS_PTR uintr.UIF = 1; uintr_control(); // potentially enable user interrupt delivery BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_UIRET, diff --git a/bochs/cpu/vmcs.cc b/bochs/cpu/vmcs.cc index 5f27a58004..4969b27668 100644 --- a/bochs/cpu/vmcs.cc +++ b/bochs/cpu/vmcs.cc @@ -461,6 +461,12 @@ bool BX_CPU_C::vmcs_field_supported(Bit32u encoding) return is_cpu_extension_supported(BX_ISA_PKS); #endif +#if BX_SUPPORT_VMX >= 2 + case VMCS_64BIT_GUEST_IA32_SPEC_CTRL: + case VMCS_64BIT_GUEST_IA32_SPEC_CTRL_HI: + return BX_SUPPORT_VMX_EXTENSION(BX_VMX_SPEC_CTRL_VIRTUALIZATION); +#endif + #if BX_SUPPORT_VMX >= 2 /* VMCS 64-bit host state fields */ /* binary 0010_11xx_xxxx_xxx0 */ @@ -483,6 +489,12 @@ bool BX_CPU_C::vmcs_field_supported(Bit32u encoding) return is_cpu_extension_supported(BX_ISA_PKS); #endif +#if BX_SUPPORT_VMX >= 2 + case VMCS_64BIT_HOST_IA32_SPEC_CTRL: + case VMCS_64BIT_HOST_IA32_SPEC_CTRL_HI: + return BX_SUPPORT_VMX_EXTENSION(BX_VMX_SPEC_CTRL_VIRTUALIZATION); +#endif + /* VMCS natural width control fields */ /* binary 0110_00xx_xxxx_xxx0 */ case VMCS_CONTROL_CR0_GUEST_HOST_MASK: @@ -894,8 +906,11 @@ void BX_CPU_C::init_secondary_vmexit_ctrls(void) // secondary vmexit controls // ----------------------------------------------------------- - // [02] Prematurely busy shadow stack control + // [02] load host MSR_IA32_SPEC_CTRL control + // [03] Prematurely busy shadow stack control + if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_SPEC_CTRL_VIRTUALIZATION)) + cap->vmx_vmexit_ctrl2_supported_bits |= VMX_VMEXIT_CTRL2_LOAD_HOST_IA32_SPEC_CTRL; #if BX_SUPPORT_CET if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CET)) cap->vmx_vmexit_ctrl2_supported_bits |= VMX_VMEXIT_CTRL2_SHADOW_STACK_BUSY_CTRL; @@ -987,6 +1002,7 @@ void BX_CPU_C::init_vmentry_ctrls(void) // [17] Load guest CET state // [19] Load guest UINV state // [22] Load guest MSR_IA32_PKRS value + // [24] Load guest MSR_IA32_SPEC_CTRL value cap->vmx_vmentry_ctrl_supported_bits = VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS | VMX_VMENTRY_CTRL1_SMM_ENTER | @@ -1016,6 +1032,8 @@ void BX_CPU_C::init_vmentry_ctrls(void) if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_PKS)) cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS; #endif + if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_SPEC_CTRL_VIRTUALIZATION)) + cap->vmx_vmexit_ctrl2_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_GUEST_IA32_SPEC_CTRL; } #endif // BX_SUPPORT_VMX diff --git a/bochs/cpu/vmx.cc b/bochs/cpu/vmx.cc index 8c76985011..fdf583632c 100644 --- a/bochs/cpu/vmx.cc +++ b/bochs/cpu/vmx.cc @@ -40,6 +40,7 @@ extern VMCS_Mapping vmcs_map; #if BX_SUPPORT_VMX >= 2 extern bool isValidMSR_PAT(Bit64u pat_msr); +extern bool isValidMSR_IA32_SPEC_CTRL(Bit64u val_64); #endif #if BX_SUPPORT_CET @@ -1234,6 +1235,14 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckHostState(void) return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } } + + if (vm->vmexit_ctrls2.LOAD_HOST_IA32_SPEC_CTRL()) { + host_state->ia32_spec_ctrl_msr = VMread64(VMCS_64BIT_HOST_IA32_SPEC_CTRL); + if (! isValidMSR_IA32_SPEC_CTRL(host_state->ia32_spec_ctrl_msr)) { + BX_ERROR(("VMFAIL: invalid value in host IA32_SPEC_CTRL_MSR")); + return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; + } + } #endif host_state->rsp = (bx_address) VMread_natural(VMCS_HOST_RSP); @@ -1843,6 +1852,14 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification) return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } + + if (vm->vmentry_ctrls.LOAD_GUEST_IA32_SPEC_CTRL()) { + guest.ia32_spec_ctrl_msr = VMread64(VMCS_64BIT_GUEST_IA32_SPEC_CTRL); + if (! isValidMSR_IA32_SPEC_CTRL(guest.ia32_spec_ctrl_msr)) { + BX_ERROR(("VMFAIL: invalid value in guest MSR_IA32_SPEC_CTRL")); + return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; + } + } #endif guest.rip = VMread_natural(VMCS_GUEST_RIP); @@ -2158,6 +2175,10 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification) if (vm->vmentry_ctrls.LOAD_PAT_MSR()) { BX_CPU_THIS_PTR msr.pat = guest.pat_msr; } + + if (vm->vmentry_ctrls.LOAD_GUEST_IA32_SPEC_CTRL()) { + BX_CPU_THIS_PTR msr.ia32_spec_ctrl = guest.ia32_spec_ctrl_msr; + } #endif #if BX_SUPPORT_VMX >= 2 @@ -2671,6 +2692,9 @@ void BX_CPU_C::VMexitLoadHostState(void) if (vm->vmexit_ctrls1.LOAD_PAT_MSR()) { BX_CPU_THIS_PTR msr.pat = host_state->pat_msr; } + if (vm->vmexit_ctrls2.LOAD_HOST_IA32_SPEC_CTRL()) { + BX_CPU_THIS_PTR msr.ia32_spec_ctrl = host_state->ia32_spec_ctrl_msr; + } #endif // CS selector loaded from VMCS @@ -4248,6 +4272,7 @@ void BX_CPU_C::register_vmx_state(bx_param_c *parent) #if BX_SUPPORT_X86_64 BXRS_HEX_PARAM_FIELD(host, efer_msr, vm->host_state.efer_msr); #endif + BXRS_HEX_PARAM_FIELD(host, ia32_spec_ctrl_msr, vm->host_state.ia32_spec_ctrl_msr); #endif #if BX_SUPPORT_CET BXRS_HEX_PARAM_FIELD(host, ia32_s_cet_msr, vm->host_state.msr_ia32_s_cet); diff --git a/bochs/cpu/vmx.h b/bochs/cpu/vmx.h index 2f6d3a32aa..32f4334736 100644 --- a/bochs/cpu/vmx.h +++ b/bochs/cpu/vmx.h @@ -208,6 +208,7 @@ const Bit64u VMX_VMFUNC_EPTP_SWITCHING_MASK = (BX_CONST64(1) << VMX_VMFUNC_EPTP_ #define VMCS_16BIT_CONTROL_EPTP_INDEX 0x00000004 /* #VE Exception */ #define VMCS_16BIT_CONTROL_HLAT_PREFIX 0x00000006 /* HLAT */ #define VMCS_16BIT_CONTROL_LAST_PID_POINTER_INDEX 0x00000008 /* IPI Virtualization */ +#define VMCS_16BIT_CONTROL_VIRTUAL_TIMER_VECTOR 0x0000000A /* APIC timer virtualization (not implemented) */ /* VMCS 16-bit guest-state fields */ /* binary 0000_10xx_xxxx_xxx0 */ @@ -309,6 +310,9 @@ const Bit64u VMX_VMFUNC_EPTP_SWITCHING_MASK = (BX_CONST64(1) << VMX_VMFUNC_EPTP_ #define VMCS_64BIT_CONTROL_IA32_SPEC_CTRL_MASK_HI 0x0000204B #define VMCS_64BIT_CONTROL_IA32_SPEC_CTRL_SHADOW 0x0000204C #define VMCS_64BIT_CONTROL_IA32_SPEC_CTRL_SHADOW_HI 0x0000204D +#define VMCS_64BIT_CONTROL_GUEST_DEADLINE_SHADOW 0x0000204E /* APIC timer virtualization (not implemented) */ +#define VMCS_64BIT_CONTROL_GUEST_DEADLINE_SHADOW_HI 0x0000204F + /* VMCS 64-bit read only data fields */ /* binary 0010_01xx_xxxx_xxx0 */ @@ -343,6 +347,10 @@ const Bit64u VMX_VMFUNC_EPTP_SWITCHING_MASK = (BX_CONST64(1) << VMX_VMFUNC_EPTP_ #define VMCS_64BIT_GUEST_IA32_RTIT_CTL_HI 0x00002815 #define VMCS_64BIT_GUEST_IA32_PKRS 0x00002818 /* Supervisor-Mode Protection Keys */ #define VMCS_64BIT_GUEST_IA32_PKRS_HI 0x00002819 +#define VMCS_64BIT_GUEST_IA32_SPEC_CTRL 0x0000282E /* MSR_IA32_SPEC_CTRL virtualization */ +#define VMCS_64BIT_GUEST_IA32_SPEC_CTRL_HI 0x0000282F +#define VMCS_64BIT_GUEST_DEADLINE 0x00002830 /* APIC timer virtualization (not implemented) */ +#define VMCS_64BIT_GUEST_DEADLINE_HI 0x00002831 /* VMCS 64-bit host state fields */ /* binary 0010_11xx_xxxx_xxx0 */ @@ -354,6 +362,8 @@ const Bit64u VMX_VMFUNC_EPTP_SWITCHING_MASK = (BX_CONST64(1) << VMX_VMFUNC_EPTP_ #define VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL_HI 0x00002C05 #define VMCS_64BIT_HOST_IA32_PKRS 0x00002C06 /* Supervisor-Mode Protection Keys */ #define VMCS_64BIT_HOST_IA32_PKRS_HI 0x00002C07 +#define VMCS_64BIT_HOST_IA32_SPEC_CTRL 0x00002C1A /* MSR_IA32_SPEC_CTRL virtualization */ +#define VMCS_64BIT_HOST_IA32_SPEC_CTRL_HI 0x00002C1B /* VMCS 32_bit control fields */ /* binary 0100_00xx_xxxx_xxx0 */ @@ -642,6 +652,8 @@ typedef struct bx_VMCS_GUEST_STATE Bit64u pdptr[4]; #endif + Bit64u ia32_spec_ctrl_msr; + #if BX_SUPPORT_CET Bit64u msr_ia32_s_cet; bx_address ssp; @@ -686,6 +698,7 @@ typedef struct bx_VMCS_HOST_STATE Bit64u efer_msr; #endif Bit64u pat_msr; + Bit64u ia32_spec_ctrl_msr; #endif #if BX_SUPPORT_CET diff --git a/bochs/cpu/vmx_ctrls.h b/bochs/cpu/vmx_ctrls.h index 18a1a04bd5..96037a089b 100644 --- a/bochs/cpu/vmx_ctrls.h +++ b/bochs/cpu/vmx_ctrls.h @@ -239,6 +239,7 @@ class VmxVmentryControls { #define VMX_VMENTRY_CTRL1_LOAD_GUEST_CET_STATE (1 << 20) /* CET */ #define VMX_VMENTRY_CTRL1_LOAD_GUEST_LBR_CTRL (1 << 21) // not implemented #define VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS (1 << 22) /* Supervisor-Mode Protection Keys */ +#define VMX_VMENTRY_CTRL1_LOAD_GUEST_IA32_SPEC_CTRL (1 << 24) bool LOAD_DBG_CTRLS() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS; } bool X86_64_GUEST() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_X86_64_GUEST; } @@ -254,6 +255,7 @@ class VmxVmentryControls { bool LOAD_GUEST_CET_STATE() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_GUEST_CET_STATE; } bool LOAD_GUEST_LBR() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_GUEST_LBR_CTRL; } bool LOAD_GUEST_PKRS() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS; } + bool LOAD_GUEST_IA32_SPEC_CTRL() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_GUEST_IA32_SPEC_CTRL; } bool query_any(Bit32u mask) const { return (vmentry_ctrls & mask) != 0; } bool query_all(Bit32u mask) const { return (vmentry_ctrls & mask) == mask; } @@ -326,8 +328,10 @@ class BxVmexit2Controls { public: BxVmexit2Controls(Bit64u ctrls = 0): vmexit2_ctrls(ctrls) {} -#define VMX_VMEXIT_CTRL2_SHADOW_STACK_BUSY_CTRL (1 << 2) /* Shadow stack prematurely busy */ +#define VMX_VMEXIT_CTRL2_LOAD_HOST_IA32_SPEC_CTRL (1 << 2) +#define VMX_VMEXIT_CTRL2_SHADOW_STACK_BUSY_CTRL (1 << 3) /* Shadow stack prematurely busy */ + bool LOAD_HOST_IA32_SPEC_CTRL() const { return vmexit2_ctrls & VMX_VMEXIT_CTRL2_LOAD_HOST_IA32_SPEC_CTRL; } bool SHADOW_STACK_PREMATURELY_BUSY_CTRL() const { return vmexit2_ctrls & VMX_VMEXIT_CTRL2_SHADOW_STACK_BUSY_CTRL; } bool query_any(Bit64u mask) const { return (vmexit2_ctrls & mask) != 0; } diff --git a/bochs/cpu/xmm.h b/bochs/cpu/xmm.h index fce1f8983c..a27d28b2d6 100644 --- a/bochs/cpu/xmm.h +++ b/bochs/cpu/xmm.h @@ -389,19 +389,12 @@ BX_CPP_INLINE int is_clear(const BxPackedXmmRegister *r) return (r->xmm64u(0) | r->xmm64u(1)) == 0; } -#if BX_SUPPORT_EVEX -// implement SAE and EVEX encoded rounding control -BX_CPP_INLINE void softfloat_status_word_rc_override(float_status_t &status, bxInstruction_c *i) -{ - /* must be VL512 otherwise EVEX.LL encodes vector length */ - if (i->modC0() && i->getEvexb()) { - status.float_rounding_mode = i->getRC(); - status.float_suppress_exception = float_all_exceptions_mask; - status.float_exception_masks = float_all_exceptions_mask; - } -} +struct softfloat_status_t; + +#if BX_SUPPORT_EVEX == 0 +#define softfloat_status_word_rc_override(status, i) #else - #define softfloat_status_word_rc_override(status, i) +extern void softfloat_status_word_rc_override(softfloat_status_t &status, bxInstruction_c *i); #endif #if BX_SUPPORT_FPU diff --git a/bochs/cpu/xsave.cc b/bochs/cpu/xsave.cc index 5b9790ea61..08d4b51310 100644 --- a/bochs/cpu/xsave.cc +++ b/bochs/cpu/xsave.cc @@ -203,7 +203,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::XSAVEC(bxInstruction_c *i) if ((xstate_bv & BX_XCR0_SSE_MASK) != 0) { - xsave_sse_state(i, eaddr); + xsave_sse_state(i, eaddr+XSAVE_SSE_STATE_OFFSET); } Bit32u offset = XSAVE_YMM_STATE_OFFSET; @@ -360,12 +360,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::XRSTOR(bxInstruction_c *i) // Legacy form of XRSTOR loads the MXCSR register from memory whenever the // RFBM[1](SSE) or RFBM[2](AVX) is set, regardless of the values of XSTATE_BV[1] and XSTATE_BV[2] if (((requested_feature_bitmap & (BX_XCR0_SSE_MASK|BX_XCR0_YMM_MASK)) != 0 && ! compaction) || - ((requested_feature_bitmap & restore_mask & BX_XCR0_SSE_MASK) != 0)) + ((requested_feature_bitmap & restore_mask & BX_XCR0_SSE_MASK) != 0 && compaction)) { // read cannot cause any boundary cross because XSAVE image is 64-byte aligned Bit32u new_mxcsr = read_virtual_dword(i->seg(), eaddr + 24); - if(new_mxcsr & ~MXCSR_MASK) + if(new_mxcsr & ~MXCSR_MASK) { + BX_ERROR(("%s: corrupted MXCSR state restored new_mxcsr=0x%08x", i->getIaOpcodeNameShort(), new_mxcsr)); exception(BX_GP_EXCEPTION, 0); + } BX_MXCSR_REGISTER = new_mxcsr; } @@ -513,9 +515,9 @@ void BX_CPU_C::xsave_x87_state(bxInstruction_c *i, bx_address offset) { const floatx80 &fp = BX_READ_FPU_REG(index); - xmm.xmm64u(0) = fp.fraction; + xmm.xmm64u(0) = fp.signif; xmm.xmm64u(1) = 0; - xmm.xmm16u(4) = fp.exp; + xmm.xmm16u(4) = fp.signExp; write_virtual_xmmword(i->seg(), (offset+index*16+32) & asize_mask, &xmm); } @@ -523,35 +525,35 @@ void BX_CPU_C::xsave_x87_state(bxInstruction_c *i, bx_address offset) void BX_CPU_C::xrstor_x87_state(bxInstruction_c *i, bx_address offset) { + i387_t restore_i387; BxPackedXmmRegister xmm; bx_address asize_mask = i->asize_mask(); // load FPU state from XSAVE area read_virtual_xmmword(i->seg(), offset, &xmm); - BX_CPU_THIS_PTR the_i387.cwd = xmm.xmm16u(0); - BX_CPU_THIS_PTR the_i387.swd = xmm.xmm16u(1); - BX_CPU_THIS_PTR the_i387.tos = (xmm.xmm16u(1) >> 11) & 0x07; + restore_i387.cwd = xmm.xmm16u(0); + restore_i387.swd = xmm.xmm16u(1); + restore_i387.tos = (xmm.xmm16u(1) >> 11) & 0x07; /* always set bit 6 as '1 */ - BX_CPU_THIS_PTR the_i387.cwd = - (BX_CPU_THIS_PTR the_i387.cwd & ~FPU_CW_Reserved_Bits) | 0x0040; + restore_i387.cwd = (restore_i387.cwd & ~FPU_CW_Reserved_Bits) | 0x0040; /* Restore x87 FPU Opcode */ /* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */ - BX_CPU_THIS_PTR the_i387.foo = xmm.xmm16u(3) & 0x7FF; + restore_i387.foo = xmm.xmm16u(3) & 0x7FF; /* Restore x87 FPU IP */ #if BX_SUPPORT_X86_64 if (i->os64L()) { - BX_CPU_THIS_PTR the_i387.fip = xmm.xmm64u(1); - BX_CPU_THIS_PTR the_i387.fcs = 0; + restore_i387.fip = xmm.xmm64u(1); + restore_i387.fcs = 0; } else #endif { - BX_CPU_THIS_PTR the_i387.fip = xmm.xmm32u(2); - BX_CPU_THIS_PTR the_i387.fcs = xmm.xmm16u(6); + restore_i387.fip = xmm.xmm32u(2); + restore_i387.fcs = xmm.xmm16u(6); } Bit32u tag_byte = xmm.xmmubyte(4); @@ -561,30 +563,32 @@ void BX_CPU_C::xrstor_x87_state(bxInstruction_c *i, bx_address offset) #if BX_SUPPORT_X86_64 if (i->os64L()) { - BX_CPU_THIS_PTR the_i387.fdp = xmm.xmm64u(0); - BX_CPU_THIS_PTR the_i387.fds = 0; + restore_i387.fdp = xmm.xmm64u(0); + restore_i387.fds = 0; } else #endif { - BX_CPU_THIS_PTR the_i387.fdp = xmm.xmm32u(0); - BX_CPU_THIS_PTR the_i387.fds = xmm.xmm16u(2); + restore_i387.fdp = xmm.xmm32u(0); + restore_i387.fds = xmm.xmm16u(2); } /* load i387 register file */ for(unsigned index=0; index < 8; index++) { floatx80 reg; - reg.fraction = read_virtual_qword(i->seg(), (offset+index*16+32) & asize_mask); - reg.exp = read_virtual_word (i->seg(), (offset+index*16+40) & asize_mask); + reg.signif = read_virtual_qword(i->seg(), (offset+index*16+32) & asize_mask); + reg.signExp = read_virtual_word (i->seg(), (offset+index*16+40) & asize_mask); // update tag only if it is not empty - BX_WRITE_FPU_REGISTER_AND_TAG(reg, + restore_i387.FPU_save_regi(reg, IS_TAG_EMPTY(index) ? FPU_Tag_Empty : FPU_tagof(reg), index); } /* Restore floating point tag word - see desription for FXRSTOR instruction */ - BX_CPU_THIS_PTR the_i387.twd = unpack_FPU_TW(tag_byte); + restore_i387.twd = unpack_FPU_TW(&restore_i387, tag_byte); + + BX_CPU_THIS_PTR the_i387 = restore_i387; /* check for unmasked exceptions */ if (FPU_PARTIAL_STATUS & ~FPU_CONTROL_WORD & FPU_CW_Exceptions_Mask) { @@ -619,7 +623,7 @@ bool BX_CPU_C::xsave_x87_state_xinuse(void) for (unsigned index=0;index<8;index++) { floatx80 reg = BX_FPU_REG(index); - if (reg.exp != 0 || reg.fraction != 0) return true; + if (reg.signExp != 0 || reg.signif != 0) return true; } return false; diff --git a/bochs/doc/docbook/development/development.dbk b/bochs/doc/docbook/development/development.dbk index 737d19f38d..1b3d146bde 100644 --- a/bochs/doc/docbook/development/development.dbk +++ b/bochs/doc/docbook/development/development.dbk @@ -3394,11 +3394,26 @@ number for the Windows build. -Check date, update/sumup info in CHANGES. Run autoconf to regenerate configure and check them in. -Create an GIT tag that contains all files of the revision that was used in the release. +Check date, update/sumup info in CHANGES. Run autoconf to regenerate configure and +check them in. The next step is to create a GIT tag that contains all files of the +revision that was used in the release. Go to the main page of the Bochs repository +on GitHub. To the right +of the list of files, click on the Releases link. These are +the next steps: + +Click on Draft a new release +Click on Choose a tag and create a new one called +REL_2_8_FINAL +Fill in the release title Bochs 2.8 +Use the top of the CHANGES file (brief summary of changes) as the description + +Select Set as latest release +Finally click on Publish release + -&FIXME; This section needs an update because of the transition to GitHub +Source packages are automatically created (see below). After building the binary packages +you can edit the release and add them with drag&drop. @@ -3429,7 +3444,7 @@ root directory if it is not already present there. ./build/redhat/make-rpm | tee ../build.txt -This produces two rpm files in the current directory. Test and upload. +This produces two rpm files in the current directory. Test and upload (see below). @@ -3452,7 +3467,7 @@ if necessary. Open up Visual C++ and load the workspace file Bochs.sln. Check the Build:Set Active Project Configuration is set the way you want it. -For releases I use "Win64 Release". +For releases I use "x64 Release". To create "bochsdbg.exe" with Bochs debugger support, manually change these @@ -3488,12 +3503,12 @@ Bochs website, copies all the files into ./build/win32/nsis/bochs-2.8< and then creates a binary ZIP file in the NSIS folder. -Now make the NSIS installer package (the current script is known to work with NSIS 3.04) +Now make the NSIS installer package (the current script is known to work with NSIS 3.09) cd build/win32/nsis make -That gives an installer called Bochs-2.8.exe. Test and upload it. +That gives an installer called Bochs-win64-2.8.exe. Test and upload it. @@ -3524,9 +3539,8 @@ News" section on SF. The Bochs project webspace is stored under the SF directory /home/project-web/bochs. It can be accessed from the SF shell using SSH or with the commands sftp, scp and rsync. Some parts of the directory -structure must be updated from the local CVS repository, others from Bochs SVN -(directories bochs and sfsite). -The online documentation, disk images and screenshots must be uploaded manually. +structure must be updated from the local CVS repository, others from Bochs-sfsite +GIT repository. The online documentation, disk images and screenshots must be uploaded manually. Directory structure @@ -3539,17 +3553,16 @@ The online documentation, disk images and screenshots must be uploaded manually. cgi-binCGI scripts for the websitehtdocsroot directory of the website +htdocs/awardsTODOhtdocs/doc/docbookBochs online documentationhtdocs/docs-htmlold Bochs documentationhtdocs/guestosdisk images directly stored on the Bochs website +htdocs/imagesimages for Bochs website +htdocs/includesinclude files for Bochs websitehtdocs/screenshotscreenshots of Bochs running several guest operating systems -htdocs/svn-snapshotlink to current snapshothtdocs/techspectechnical specifications of several hardware components -lxrBochs source browser -sfsite-cvsrootlocal CVS repositorysitebinshell scripts (e.g. for snapshot generation)sitemanwebsite manual pages -snapshotSVN snapshot storage areatmptemp directory for shell scripts diff --git a/bochs/doc/docbook/include/defs.sgm b/bochs/doc/docbook/include/defs.sgm index 688b28a8c8..629498c195 100644 --- a/bochs/doc/docbook/include/defs.sgm +++ b/bochs/doc/docbook/include/defs.sgm @@ -1,7 +1,6 @@ In March 2001, Kevin helped a few developers to move all Bochs activities from -bochs.com to a new site at . Since then the Bochs project -has settled into its new home, and around release times has even hit #1 most -active project of the week at SourceForge. +bochs.com to a new site at . +Since then the Bochs project has settled into its new home, and around release +times has even hit #1 most active project of the week at SourceForge. @@ -141,7 +141,8 @@ active project of the week at SourceForge. regular basis, but a few statistics give an indication. The &devlist;, which is the primary source of news on bugs and releases, has over 400 subscribers. The latest version has been downloaded over 150,000 times -from SourceForge, not counting any mirror website or SVN users. +from SourceForge, not counting any mirror website or +GitHub users. @@ -894,13 +895,11 @@ code that displays the Bochs VGA screen and handles keyboard and mouse events. The change log is stored in the Bochs source code in a file called -CHANGES. Click here +CHANGES. Click here to see the latest version of the CHANGES file. -The link above is provided by Source Forge and might change one day. If it -stops working, you can download the current source code with SVN and read -the CHANGES file there. +You can also download the current source code from GitHub and read the CHANGES file there. @@ -918,8 +917,11 @@ You can download Bochs from our web site at &bochs-sf-net;. First, you need to choose what version to get: a recent release or a development version. If you trying to get things working for the first time, a release version is recommended since it has been tested the most. The development -versions (sometimes called SVN snapshots) may have some newer bug fixes and -new features, but have not been tested as much as the releases. +versions may have some newer bug fixes and new features, but have not been +tested as much as the releases. A snapshot of the current state of the source +tree in ZIP format is available on +GitHub when you press +the Code button. @@ -938,8 +940,8 @@ linkend="install-binary">Installing a Binary for more information. If you are going to compile Bochs yourself, you need the gzipped tarball containing the source code, called bochs-version.tar.gz. For -Windows and Mac, the prebuilt Makefiles are separate, so also get -the Makefiles for your platform. To unpack a compressed TAR file +Windows a ZIP package with sources and prebuilt Makefiles is available. +To unpack a compressed TAR file A TAR file is a single file that contains many files packed inside. Bochs TAR files are compressed with a program called gzip, and another program @@ -962,71 +964,60 @@ Bochs are in the section, Compiling Bochs. -Alternatively, you can also obtain the sources for any Bochs version using SVN. -See the SVN instructions for details. +Alternatively, you can also obtain the sources for any Bochs version using GIT. +See the GIT instructions for details. -
Tracking the source code with SVN +
Tracking the source code with GIT -SVN (Subversion) is a tool used by many software developers to manage changes -within their source code tree. SVN provides the means to store not only the -current version of a piece of source code, but a record of all changes (and who -made those changes) that have occurred to that source code. Use of SVN is -particularly common on projects with multiple developers, since SVN ensures -changes made by one developer are not accidentally removed when another -developer posts their changes to the source tree. The Bochs source code and -documentation is available using SVN +GIT is a free and open source version control system designed to handle small +to very large project efficiently. Git is used to tracking changes in the source +code, enabling multiple developers to work together on non-linear development. +The Bochs source code and documentation is available using GIT -You can download SVN software and documentation from -subversion.apache.org. +You can download GIT software and documentation from +git-scm.com. -. + hostet on GitHub.
Checking out Bochs -When you have SVN installed, the first step is to do a checkout. The initial -checkout command is long and ugly, but usually you only have to do it -once. The example below shows the SVN checkout process of the Bochs trunk in Unix. -On the Windows platform, you can download a SVN client from -subversion.apache.org, -or use SVN within Cygwin +When you have a GIT client installed, the first step is to do a checkout. +The initial checkout command is long and ugly, but usually you only have to do it +once. The example below shows the GIT checkout process of the Bochs master branch in Unix. +On the Windows platform, you can download a GIT client from +git-scm.com, +or use GIT within Cygwin Cygwin is an open source Unix-like environment for Windows platforms, -available at www.cygwin.com. +available at www.cygwin.com. . -
Checking out Bochs in SVN - - user$ svn co http://svn.code.sf.net/p/bochs/code/trunk/bochs bochs - A bochs/ltdl.c - A bochs/Makefile.in - A bochs/bochs.h - . - . (This might take a few minutes, depending on your network connection.) - . - A bochs/install.sh - U bochs - Checkout, Revision 10754. - user$ cd bochs +
Checking out Bochs in GIT + + user$ git clone https://github.com/bochs-emu/Bochs.git + Cloning into 'Bochs'... + remote: Enumerating objects: 107946, done. + remote: Counting objects: 100% (2708/2708), done. + remote: Compressing objects: 100% (869/869), done. + remote: Total 107946 (delta 2095), reused 2118 (delta 1817), pack-reused 105238 + Receiving objects: 100% (107946/107946), 39.53 MiB | 2.86 MiB/s, done. + Resolving deltas: 100% (85554/85554), done. + (This might take a few minutes, depending on your network connection.) + user$ cd Bochs/bochs user$ ls - aclocal.m4 cpu logio.cc pc_system.cc - bios cpudb.h ltdl.c pc_system.h - bochs.h crc.cc ltdlconf.h.in plugin.cc - build disasm ltdl.h plugin.h - bx_debug doc ltmain.sh README - bxversion.h.in docs-html main.cc README-plugins - bxversion.rc.in extplugin.h Makefile.in README.rfb - CHANGES fpu memory README-wxWindows - config.cc gdbstub.cc misc TESTFORM.txt - config.guess gui msrs.def TODO - config.h.in host osdep.cc win32_enh_dbg.rc - config.sub install-sh osdep.h win32res.rc - configure instrument param_names.h wxbochs.rc - configure.in iodev PARAM_TREE.txt - COPYING load32bitOShack.cc patches + CHANGES aclocal.m4 bxversion.rc.in crc.cc iodev osdep.h win32res.rc + COPYING bios config.cc doc logio.cc param_names.h win32usbres.rc + LICENSE bochs.h config.guess docs-html logio.h patches wxbochs.rc + Makefile.in build config.h.in extplugin.h ltmain.sh pc_system.cc + PARAM_TREE.txt bx_debug config.sub gdbstub.cc main.cc pc_system.h + README bxdisasm.cc configure gui memory plugin.cc + README-wxWidgets bxthread.cc configure.ac host misc plugin.h + TESTFORM.txt bxthread.h cpu install-sh msrs.def qemu-queue.h + TODO bxversion.h.in cpudb.h instrument osdep.cc win32_enh_dbg.rc user$ _
@@ -1040,114 +1031,47 @@ available at www.cygwin.com. -If you have write access to the Bochs SVN tree, see the Developers Guide - - -See the Developers Guide -and/or look at -SourceForge's Subversion documentation, +If you have write access to the Bochs GIT tree, see the +Developers Guide for instructions. - for details. - -The SVN checkout process (above) gives you a directory called bochs +The GIT checkout process (above) gives you a directory called Bochs that contains the very latest source code. I will refer to this directory -as &bochsdir;. In this directory there's also a subdirectory called ".svn" -which tells the SVN software where the code was checked out, what version +as &bochsdir;. In this directory there's also a subdirectory called ".git" +which tells the GIT software where the code was checked out, what version you have, and where to go for future updates.
Getting the Latest Version -Most developers use SVN to always give them the latest source code. The minute +Most developers use GIT to always give them the latest source code. The minute that any developer checks in a change, they are available to everyone else -through SVN. You just have to type svn update in the -&bochsdir; directory, and SVN will retrieve any files and directories that have +through GIT. You just have to type git pull in the +&bochsdir; directory, and GIT will retrieve any files and directories that have been changed since you did a checkout. If you update regularly, each update takes a short time because it downloads only the files that changed. -See also Getting a release version. +See also Getting a release version. + -The svn update command tells you if any new files have +The git pull command tells you if any new files have been downloaded from the server, and it also tells you if you have modified any -of the SVN-controlled files. As it checks through the source directories, it -will list files that have changed, with a single letter before the name that -tells the status of that file. The most common status letters are listed -below. - -
-Status letters in a SVN update - - - - Letter - Meaning - Description - - - - - ? - unknown - - This file is in your Bochs directory, but SVN does not know anything - about it. For example, when you compile Bochs, any files created - during the build process appear as ?. - - - - U - update - - SVN downloaded a new version of this file because it changed on the - server, usually because someone else did a checkin. - - - - A - added - - SVN downloaded a newly added file from the server. - - - - D - deleted - - This file has been deleted on the server and SVN removed it from your - local copy. - - - - C - conflict - - You have changed this file on your disk, but this change conflicts with - a change that was checked in. Conflicts occur when two people change - the same line of code in different ways. You need to edit the - conflicting file(s) and clean it up by hand. Or, sometimes it's - easiest to discard your own edits and download a fresh copy, by - deleting the conflicting file and running svn update again. - - - - -
+of the GIT-controlled files. As it checks through the source directories, it +will list files that have changed. - -
Getting a Release Version +
Getting a Release Version -You can also use the SVN checkout command to get the Bochs source code for +You can also use the GIT checkout command to get the Bochs source code for any release since March 2000. The command is - user$ svn co http://svn.code.sf.net/p/bochs/code/tags/tagname/bochs bochs + user$ git clone --branch tagname https://github.com/bochs-emu/Bochs.git The tagname tells which release you want, and it can be one of the following: @@ -1157,210 +1081,215 @@ The tagname tells which release you want, and it can Bochs version - Release tag for SVN - SVN revision + Release tag for GIT + Release date + + 2.8 + REL_2_8_FINAL + March 10, 2024 + 2.7 REL_2_7_FINAL - 14332 + August 1, 2021 2.6.11 (bugfix) REL_2_6_11_FINAL - 13774 + January 5, 2020 2.6.10 (intermediate) REL_2_6_10_FINAL - 13629 + December 1, 2019 2.6.9 (intermediate) REL_2_6_9_FINAL - 13181 + April 9, 2017 2.6.8 (intermediate) REL_2_6_8_FINAL - 12740 + May 3, 2015 2.6.7 (intermediate) REL_2_6_7_FINAL - 12531 + November 2, 2014 2.6.6 (bugfix) REL_2_6_6_FINAL - 12375 + June 15, 2014 2.6.5 (intermediate) REL_2_6_5_FINAL - 12349 + June 1, 2014 2.6.2 (bugfix) REL_2_6_2_FINAL - 11694 + May 26, 2013 2.6.1 (intermediate) REL_2_6_1_FINAL - 11667 + April 7, 2013 2.6 REL_2_6_FINAL - 11395 + September 2, 2012 2.5.1 (bugfix) REL_2_5_1_FINAL - 10946 + January 6, 2012 2.5 REL_2_5_FINAL - 10801 + November 27, 2011 2.4.6 REL_2_4_6_FINAL - 10202 + February 22, 2011 2.4.5 REL_2_4_5_FINAL - 9914 + April 25, 2010 2.4.2 REL_2_4_2_FINAL - 9568 + November 12, 2009 2.4.1 REL_2_4_1_FINAL - 9368 + June 7, 2009 2.4 REL_2_4_FINAL - 9289 + May 3, 2009 2.3.7 REL_2_3_7_FINAL - 8537 + June 3, 2008 2.3.6 REL_2_3_6_FINAL - 8111 + December 24, 2007 2.3.5 REL_2_3_5_FINAL - 7840 + September 16, 2007 2.3 REL_2_3_FINAL - 7538 + August 27, 2006 2.2.6 (intermediate2) REL_2_2_6_FINAL - 7060 + January 29, 2005 2.2.5 (intermediate1) REL_2_2_5_FINAL - 6942 + December 30, 2005 2.2.1 (bugfix1) REL_2_2_1_FINAL - 6624 + July 8, 2005 2.2 REL_2_2_FINAL - 6476 + May 28, 2005 2.1.1 (bugfix1) REL_2_1_1_FINAL - 5560 + February 8, 2004 2.1 REL_2_1_FINAL - 5441 + January 9, 2004 2.0.2 (bugfix2) REL_2_0_2_FINAL - 4592 + January 21, 2003 2.0.1 (bugfix1) REL_2_0_1_FINAL - 4491 + January 4, 2003 2.0 REL_2_0_FINAL - 4409 + December 21, 2002 1.4.1 (bugfix1) REL_1_4_1_FINAL - 2513 + June 22, 2002 1.4 REL_1_4_FINAL - 2235 + March 27, 2002 1.3 REL_1_3_FINAL - 1705 + December 10, 2001 1.2.1 (bugfix1) REL_1_2_1_FINAL - 912 + June 12, 2001 1.2 REL_1_2_FINAL - 797 + June 3, 2001 1.1.2 (bugfix3) REL_1_1_2_BASE - 510 + May 16, 2001 1.1.1 (bugfix2) REL_1_1_1_BASE - 57 + April 9, 2001 1.1 (bugfix1) REL_1_1_BASE - 51 + April 6, 2001 1.0 (bochs-2000_0325a) REL-bochs-2000-03-25 - 7 + March 25, 2000 @@ -1370,25 +1299,16 @@ The tagname tells which release you want, and it can
-
More about SVN +
More about GIT and GitHub -Entire books have been written on SVN, so there's no sense in duplicating -it all here in the Bochs documentation. Some sources of additional -information is listed below. +The official GIT documentation can be found at +and the official GitHub docs are located at . - -The subversion.apache.org -site has tons of SVN FAQs and documentation. - -A German SVN FAQ -is available at University of Muenster. - -
-
+
Installing a Binary @@ -1403,8 +1323,9 @@ is different on different platforms. The Bochs binaries for Windows are distributed in an EXE installer package. The Bochs installer can be started like any other Windows program and it brings up the installation wizard. Here you can select the destination folder and the -installation options. The wizard installs the files and creates the registry -keys, start menu and desktop links. +installation options. If an older Bochs version is installed, you'll be asked +to uninstall it before installing the new version. The wizard installs the files +and creates the registry keys, start menu and desktop links. Previous releases of Bochs were distributed as ZIP packages, too. These packages @@ -1457,11 +1378,12 @@ DLX Linux screenshot. vgabios-cirrus.bin-1.13.0 SeaVGABIOS ROM image (for Cirrus adapter) VGABIOS-elpin-2.40 VGA BIOS image for Bochs VGABIOS-elpin-LICENSE.txt license for VGA BIOS -VGABIOS-lgpl-latest LGPL'd VGA BIOS image for Bochs -VGABIOS-lgpl-latest-debug LGPL'd VGA BIOS image for Bochs with debug output to the logfile -VGABIOS-lgpl-latest-cirrus LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled -VGABIOS-lgpl-latest-cirrus-debug LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled and debug output to the logfile -VGABIOS-lgpl-latest-banshee LGPL'd VGA BIOS image for Bochs with the Voodoo Banshee extension enabled +VGABIOS-lgpl-latest-bin LGPL'd VGA BIOS image for Bochs +VGABIOS-lgpl-latest-debug.bin LGPL'd VGA BIOS image for Bochs with debug output to the logfile +VGABIOS-lgpl-latest-cirrus.bin LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled +VGABIOS-lgpl-latest-cirrus-debug.bin LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled and debug output to the logfile +VGABIOS-lgpl-latest-banshee.bin LGPL'd VGA BIOS image for Bochs with the Voodoo Banshee extension enabled +VGABIOS-lgpl-latest-banshee-debug.bin LGPL'd VGA BIOS image for Bochs with the Voodoo Banshee extension enabled and debug output to the logfile VGABIOS-lgpl-README.txt readme for the LGPL'd VGA BIOS dlxlinux\ directory containing DLX linux sample disk image and configuration files dlxlinux\bochsrc.bxrc Bochs configuration file for DLX @@ -1471,7 +1393,7 @@ DLX Linux screenshot. dlxlinux\testform.txt Form for reporting success or failure doc\index.html - a local copy of all Bochs documentation (online copy) + a local copy of all Bochs documentation (online copy) keymaps\*.map keymap tables (on Windows used for the paste feature only) @@ -1532,8 +1454,8 @@ anyway, but if it is missing important pieces, it may not run properly. -The Bochs RPM installs five new commands and associated manual pages: bochs, -bochs-dlx and bximage. First, let's try out the +The Bochs RPM installs four new commands and associated manual pages: bochs, +bochs-dlx, bxhub and bximage. First, let's try out the DLX Linux demo by typing bochs-dlx. @@ -1634,7 +1556,7 @@ description of each one. /usr/share/doc/bochs/LICENSE Bochs license information /usr/share/doc/bochs/README the read-me file from the source distribution. /usr/share/doc/bochs/TODO the TODO file from the source distribution. -/usr/share/doc/bochs/index.html a local copy of all Bochs documentation ( Online copy ) +/usr/share/doc/bochs/index.html a local copy of all Bochs documentation ( Online copy ) /usr/share/doc/bochs/slirp.conf sample config file for the advanced 'slirp' network configuration /usr/share/doc/bochs/vnet.conf sample config file for the advanced 'vnet' network configuration /usr/share/bochs/BIOS-bochs-latest default ROM BIOS image for Bochs @@ -1643,11 +1565,12 @@ description of each one. /usr/share/bochs/SeaVGABIOS-README README for SeaVGABIOS ROM image /usr/share/bochs/VGABIOS-elpin-2.40 VGA BIOS image for Bochs /usr/share/bochs/VGABIOS-elpin-LICENSE license for VGA BIOS -/usr/share/bochs/VGABIOS-lgpl-latest LGPL'd VGA BIOS image for Bochs -/usr/share/bochs/VGABIOS-lgpl-latest-debug LGPL'd VGA BIOS image for Bochs with debug output to the logfile -/usr/share/bochs/VGABIOS-lgpl-latest-cirrus LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled -/usr/share/bochs/VGABIOS-lgpl-latest-cirrus-debug LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled and debug output to the logfile -/usr/share/bochs/VGABIOS-lgpl-latest-banshee LGPL'd VGA BIOS image for Bochs with the Voodoo Banshee extension enabled +/usr/share/bochs/VGABIOS-lgpl-latest.bin LGPL'd VGA BIOS image for Bochs +/usr/share/bochs/VGABIOS-lgpl-latest-debug.bin LGPL'd VGA BIOS image for Bochs with debug output to the logfile +/usr/share/bochs/VGABIOS-lgpl-latest-cirrus.bin LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled +/usr/share/bochs/VGABIOS-lgpl-latest-cirrus-debug.bin LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled and debug output to the logfile +/usr/share/bochs/VGABIOS-lgpl-latest-banshee.bin LGPL'd VGA BIOS image for Bochs with the Voodoo Banshee extension enabled +/usr/share/bochs/VGABIOS-lgpl-latest-banshee-debug.bin LGPL'd VGA BIOS image for Bochs with the Voodoo Banshee extension enabled and debug output to the logfile /usr/share/bochs/VGABIOS-lgpl-README readme for the LGPL'd VGA BIOS /usr/share/bochs/bios.bin-1.13.0 SeaBIOS ROM image /usr/share/bochs/dlxlinux/ directory containing DLX linux sample disk image and configuration files @@ -1742,7 +1665,7 @@ descriptions or tool-tips). Bochs is written in C++, so you need a C++ compiler on your system. Most platforms have been tested with GNU gcc/g++, but other compilers are known to work too. By now, you should have unpacked your source TAR file or checked -out Bochs from SVN. If not, you can return to Downloading Bochs for details. The top level directory of the source code will be referred to as &bochsdir;. (&bochsdir; contains the files bochs.h and @@ -2522,7 +2445,7 @@ SMP, x86_64 support) and the devices options (e.g. PCI, USB, Cirrus graphics). features of the debugger. You only want this option if you are developing guest OS code for use in Bochs. In other words, most people don't. Also, it should only be used with . - See the + See the developer documentation for details. @@ -3066,7 +2989,7 @@ called from make are causing the failure (e.g. compiler / lin In some cases it might be useful to rebuild Bochs completely by calling make dist-clean and running the configure script once again. These steps are recommended if the development sources from -SVN are used and one of the build system files (e.g. Makefile +GitHub are used and one of the build system files (e.g. Makefile or config.h.in) has been changed. @@ -3113,7 +3036,7 @@ the BIOS image (usually called BIOS-bochs-latest) -the VGA BIOS image (e.g. VGABIOS-lgpl-latest or VGABIOS-elpin-2.40) +the VGA BIOS image (e.g. VGABIOS-lgpl-latest.bin or VGABIOS-elpin-2.40) @@ -3167,7 +3090,7 @@ instructions given in . A collection of disk images of different operating systems can be found at -. Some disk +. Some disk images are the size of a floppy disk (1 meg compressed) and others are gigantic (160 meg compressed). If you want to create a disk image yourself, please see . @@ -3191,11 +3114,12 @@ system BIOS and VGA BIOS images. BIOS-bochs-legacy ROM BIOS image without 32-bit init code (for i386 and ISA graphics card emulation) bios.bin-1.13.0 SeaBIOS ROM image VGABIOS-elpin-2.40 legacy VGA BIOS image for Bochs -VGABIOS-lgpl-latest LGPL'd VGA BIOS image for Bochs -VGABIOS-lgpl-latest-debug LGPL'd VGA BIOS image for Bochs with debug output to the logfile -VGABIOS-lgpl-latest-cirrus LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled -VGABIOS-lgpl-latest-cirrus-debug LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled and debug output to the logfile -VGABIOS-lgpl-latest-banshee LGPL'd VGA BIOS image for Bochs with the Voodoo Banshee extension enabled +VGABIOS-lgpl-latest.bin LGPL'd VGA BIOS image for Bochs +VGABIOS-lgpl-latest-debug.bin LGPL'd VGA BIOS image for Bochs with debug output to the logfile +VGABIOS-lgpl-latest-cirrus.bin LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled +VGABIOS-lgpl-latest-cirrus-debug.bin LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled and debug output to the logfile +VGABIOS-lgpl-latest-banshee.bin LGPL'd VGA BIOS image for Bochs with the Voodoo Banshee extension enabled +VGABIOS-lgpl-latest-banshee-debug.bin LGPL'd VGA BIOS image for Bochs with the Voodoo Banshee extension enabled and debug output to the logfile vgabios-cirrus.bin-1.13.0 SeaVGABIOS ROM image (for Cirrus adapter) @@ -3206,7 +3130,7 @@ system BIOS and VGA BIOS images. Bochs must be set up to use system and VGA BIOS like this: romimage: file=BIOS-bochs-latest, address=0xfffe0000 - vgaromimage: file=VGABIOS-lgpl-latest + vgaromimage: file=VGABIOS-lgpl-latest.bin We recommend to use the ROM images distributed with Bochs or one of the latest SeaBIOS images. BIOS images designed @@ -3832,8 +3756,8 @@ this feature yet. Examples: vgaromimage: file=bios/VGABIOS-elpin-2.40 - vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest - vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest-cirrus + vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest.bin + vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest-cirrus.bin This tells Bochs what VGA ROM BIOS to load (at 0xC0000). @@ -3885,11 +3809,11 @@ This defines parameters related to the VGA display The 'extension' option can be used to specify the VGA display extension. With the value 'none' you can use standard VGA with no extension. Other supported -values are 'vbe' for Bochs VBE (needs VGABIOS-lgpl-latest as +values are 'vbe' for Bochs VBE (needs VGABIOS-lgpl-latest.bin as VGA BIOS, see vgaromimage option), -'cirrus' for Cirrus SVGA support (needs VGABIOS-lgpl-latest-cirrus +'cirrus' for Cirrus SVGA support (needs VGABIOS-lgpl-latest-cirrus.bin as VGA BIOS) and 'voodoo' for Voodoo Graphics support (needs -VGABIOS-lgpl-latest-banshee as VGA BIOS / see +VGABIOS-lgpl-latest-banshee.bin as VGA BIOS / see for more information). @@ -6883,7 +6807,7 @@ The USB emulation has been tested on numerous Guests. You can find these results - usb_debug: type=none|uhci|ohci|ehci|xhci, reset, enable, start_frame, doorbell, event, non_exist + usb_debug: type=none|uhci|ohci|ehci|xhci, reset=1, enable=1, start_frame=1, doorbell=1, event=1, non_exist=1 @@ -7097,7 +7021,7 @@ bit will be clear, so the next TD will be processed anyway. If you are using a program written for DOS which seems to use the text-mode but doesn't display the text properly, you can try the other VGA BIOS, either - VGABIOS-lgpl-latest or VGABIOS-elpin-2.40, + VGABIOS-lgpl-latest.bin or VGABIOS-elpin-2.40, see the vgaromimage option. @@ -7150,7 +7074,7 @@ When reporting errors while building Bochs to the &devlist; or the SF bug tracker for the Bochs project, this information is required to fix the issue: host platorm / build environment - Bochs release version or SVN revision + Bochs release version or GIT SHA revision code configure options used full error message config.log output if configure failure @@ -7169,7 +7093,7 @@ or submit the patch in SF patch tracker for Bochs. If Bochs does not work properly (e.g. panic, segfault, malfunction of emulated device) we need some information to find out what's going on: - Bochs version used (version number if binary release / SVN revision + Bochs version used (version number if binary release / GIT revision if self-compiled) host platorm / build environment (if self-compiled) bochsrc options used @@ -7183,7 +7107,7 @@ we need some information to find out what's going on: Patches for Bochs should be provided in the "unified diff" format. In addition to the patch file and a detailed description this information is required: - patch applies to Bochs release version / SVN revision + patch applies to Bochs release version / GIT revision test case (if required) @@ -7268,8 +7192,9 @@ will get 2 copies of every announcement.
bochs-cvs mailing list -This is the svn commit mailinglist (a unified diff email will be sent -whenever someone does a checkin in the bochs SVN repository). +This is the SVN commit mailinglist (an email had been sent whenever someone did +a checkin in the Bochs SVN repository). After transitioning to GitHub there is +no activity anymore. The mail archive is still present. @@ -8640,7 +8565,7 @@ The partition size reported by fdisk is okay, but mformat reports only 504 MB Mtools is a set of programs that can read, write, and format DOS disk images. There are links to the Mtools main page and a Win32 port of Mtools on the -Bochs Links page, +Bochs Links page, under Resources. @@ -9503,8 +9428,8 @@ Hitting ^C works. Example: This section describes what is possible to do with Bochs serial port emulation. These examples use dlxlinux disk image (downloaded from - - http://bochs.sourceforge.net/guestos/dlxlinux3.tar.gz + + https://bochs.sourceforge.io/guestos/dlxlinux4.tar.gz ) running as guest, on a debian x86 linux 2.4.19 host. @@ -9647,7 +9572,7 @@ A bootable CD-ROM has a special layout that is detected by the BIOS boot loader code, and executed if it conforms the specifications. This layout is called "El Torito Bootable CD-ROM Format Specification" and has been published by Phoenix and IBM. A copy of this spec is on -Bochs tech specs page. +Bochs tech specs page. El Torito specifies 3 ways to have a bootable CD: @@ -10054,7 +9979,7 @@ Bochs VBE Display Drivers for Windows NT/2000 # Enable CL-GD5446 PCI vga: extension=cirrus - vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest-cirrus + vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest-cirrus.bin pci: enabled=1, chipset=i440fx, slot1=cirrus @@ -10084,7 +10009,7 @@ Bochs VBE Display Drivers for Windows NT/2000 Banshee compatible device with its VGA interface disabled is not implemented yet. For both Banshee and Voodoo3 there is now a specific version of the LGPL'd VGABIOS with Voodoo Banshee specific code called - VGABIOS-lgpl-latest-banshee. The binary file is compiled + VGABIOS-lgpl-latest-banshee.bin. The binary file is compiled for the Banshee PCI model, but Bochs modifies the VGABIOS data after loading to support the Voodoo3 and AGP models properly. @@ -10092,7 +10017,7 @@ Bochs VBE Display Drivers for Windows NT/2000 These bochsrc settings should be used for Voodoo Banshee PCI: vga: extension=voodoo - vgaromimage: file=VGABIOS-lgpl-latest-banshee + vgaromimage: file=VGABIOS-lgpl-latest-banshee.bin voodoo: model=banshee @@ -11391,7 +11316,7 @@ cpu: count=1, ips=50000000, reset_on_triple_fault=1, ignore_bad_msrs=1 cpu: cpuid_limit_winnt=0 clock: sync=realtime, time0=local memory: guest=512, host=512 -vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus +vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus.bin vga: extension=cirrus, update_freq=5 pci: enabled=1, chipset=i440fx, slot1=cirrus @@ -11412,7 +11337,7 @@ cpu: count=1, ips=55000000, reset_on_triple_fault=1, ignore_bad_msrs=1 cpu: cpuid_limit_winnt=0 clock: sync=realtime, time0=local memory: guest=512, host=512 -vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus +vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus.bin vga: extension=cirrus, update_freq=5 pci: enabled=1, chipset=i440fx, slot1=cirrus @@ -11483,7 +11408,7 @@ cpu: count=1, ips=75000000, reset_on_triple_fault=1, ignore_bad_msrs=1 cpu: cpuid_limit_winnt=0 clock: sync=realtime, time0=local memory: guest=512, host=512 -vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus +vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus.bin vga: extension=cirrus, update_freq=5 pci: enabled=1, chipset=i440fx, slot1=cirrus @@ -11516,7 +11441,7 @@ cpu: count=1, ips=100000000, reset_on_triple_fault=1, ignore_bad_msrs=1 cpu: cpuid_limit_winnt=0 clock: sync=realtime, time0=local memory: guest=1024, host=1024 -vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus +vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus.bin vga: extension=cirrus, update_freq=5 pci: enabled=1, chipset=i440fx, slot1=cirrus @@ -11541,7 +11466,7 @@ cpu: count=1, ips=150000000, reset_on_triple_fault=1, ignore_bad_msrs=1 cpu: cpuid_limit_winnt=0 clock: sync=realtime, time0=local memory: guest=2048, host=2048 -vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus +vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus.bin vga: extension=cirrus, update_freq=5 pci: enabled=1, chipset=i440fx, slot1=cirrus @@ -11571,7 +11496,7 @@ cpu: count=1, ips=325000000, reset_on_triple_fault=1, ignore_bad_msrs=1 cpu: cpuid_limit_winnt=0 clock: sync=realtime, time0=local memory: guest=2048, host=2048 -vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus +vgaromimage: file=D:/path/to/your/bios/VGABIOS-lgpl-latest-cirrus.bin vga: extension=cirrus, update_freq=5 pci: enabled=1, chipset=i440fx, slot1=cirrus @@ -11683,7 +11608,7 @@ ata1: enabled=0 ata2: enabled=0 ata3: enabled=0 romimage: file=bios/BIOS-bochs-latest -vgaromimage: file=bios/VGABIOS-lgpl-latest +vgaromimage: file=bios/VGABIOS-lgpl-latest.bin megs: 64 parport1: enabled=1, file="lp.pipe" com1: enabled=0 diff --git a/bochs/doc/man/bochs-dlx.1 b/bochs/doc/man/bochs-dlx.1 index aab9216605..04d68d1e37 100644 --- a/bochs/doc/man/bochs-dlx.1 +++ b/bochs/doc/man/bochs-dlx.1 @@ -1,5 +1,5 @@ .\"Document Author: Timothy R. Butler - tbutler@uninetsolutions.com" -.TH bochs-dlx 1 "19 Jun 2014" "bochs-dlx" "The Bochs Project" +.TH bochs-dlx 1 "26 Mar 2024" "bochs-dlx" "The Bochs Project" .\"SKIP_SECTION" .SH NAME bochs-dlx \- Runs DLX-Linux under the Bochs x86 Emulator @@ -29,22 +29,22 @@ the lack of warranty. .\"SKIP_SECTION" .SH AVAILABILITY The latest version of this program can be found at: - http://bochs.sourceforge.net/getcurrent.html + https://bochs.sourceforge.io/getcurrent.html .\"SKIP_SECTION" .SH SEE ALSO bochs(1), bochsrc(5), bximage(1) .PP .nf The Bochs IA-32 Emulator site on the World Wide Web: - http://bochs.sourceforge.net + https://bochs.sourceforge.io Online Bochs Documentation - http://bochs.sourceforge.net/doc/docbook + https://bochs.sourceforge.io/doc/docbook .fi .\"SKIP_SECTION" .SH BUGS Please report all bugs to the bug tracker on our web -site. Just go to http://bochs.sourceforge.net, and click +site. Just go to https://bochs.sourceforge.io, and click "Bug Reports" on the sidebar under "Features." .PP Provide a detailed description of the bug, the version of diff --git a/bochs/doc/man/bochs.1 b/bochs/doc/man/bochs.1 index d5dc4c1505..a5d8aa8488 100644 --- a/bochs/doc/man/bochs.1 +++ b/bochs/doc/man/bochs.1 @@ -1,5 +1,5 @@ .\"Document Author: Timothy R. Butler - tbutler@uninetsolutions.com" -.TH bochs 1 "4 Apr 2020" "bochs @version@" "The Bochs Project" +.TH bochs 1 "26 Mar 2024" "bochs @version@" "The Bochs Project" .\"SKIP_SECTION" .SH NAME bochs \- Portable x86 Emulator. @@ -84,17 +84,17 @@ the lack of warranty. .\"SKIP_SECTION" .SH AVAILABILITY The latest version of this program can be found at: - http://bochs.sourceforge.net/getcurrent.html + https://bochs.sourceforge.io/getcurrent.html .\"SKIP_SECTION" .SH SEE ALSO bochsrc(5), bochs-dlx(1), bximage(1) .PP .nf The Bochs IA-32 Emulator site on the World Wide Web: - http://bochs.sourceforge.net + https://bochs.sourceforge.io Online Bochs Documentation - http://bochs.sourceforge.net/doc/docbook + https://bochs.sourceforge.io/doc/docbook .fi .\"SKIP_SECTION" .SH AUTHORS @@ -103,11 +103,11 @@ The Bochs emulator was created by Kevin Lawton by the members of the Bochs x86 Emulator Project. You can see a current roster of members at: - http://bochs.sourceforge.net/getinvolved.html + https://bochs.sourceforge.io/getinvolved.html .\"SKIP_SECTION" .SH BUGS Please report all bugs to the bug tracker on our web -site. Just go to http://bochs.sourceforge.net, and click +site. Just go to https://bochs.sourceforge.io, and click "Bug Reports" on the sidebar under "Feedback". .PP Provide a detailed description of the bug, the version of diff --git a/bochs/doc/man/bochsrc.5 b/bochs/doc/man/bochsrc.5 index 534695941f..87db44ad26 100644 --- a/bochs/doc/man/bochsrc.5 +++ b/bochs/doc/man/bochsrc.5 @@ -1,5 +1,5 @@ .\"Document Author: Timothy R. Butler - tbutler@uninetsolutions.com" -.TH bochsrc 5 "20 Jan 2024" "bochsrc" "The Bochs Project" +.TH bochsrc 5 "10 Jun 2024" "bochsrc" "The Bochs Project" .\"SKIP_SECTION" .SH NAME bochsrc \- Configuration file for Bochs. @@ -461,8 +461,8 @@ You also need to load a VGA ROM BIOS into 0xC0000. Examples: vgaromimage: file=bios/VGABIOS-elpin-2.40 - vgaromimage: file=bios/VGABIOS-lgpl-latest - vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest + vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest.bin + vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest-cirrus.bin .TP .I "optromimage1: \fP, \fIoptromimage2: \fP, \fIoptromimage3: \fPor \fIoptromimage4:" @@ -1382,17 +1382,17 @@ the lack of warranty. .\"SKIP_SECTION" .SH AVAILABILITY The latest version of this program can be found at: - http://bochs.sourceforge.net/getcurrent.html + https://bochs.sourceforge.io/getcurrent.html .\"SKIP_SECTION" .SH SEE ALSO bochs(1), bochs-dlx(1), bximage(1) .PP .nf The Bochs IA-32 Emulator site on the World Wide Web: - http://bochs.sourceforge.net + https://bochs.sourceforge.io Online Bochs Documentation - http://bochs.sourceforge.net/doc/docbook + https://bochs.sourceforge.io/doc/docbook .fi .\"SKIP_SECTION" .SH AUTHORS @@ -1400,11 +1400,11 @@ The Bochs emulator was created by Kevin Lawton (kevin@mandrakesoft.com), and is currently maintained by the members of the Bochs x86 Emulator Project. You can see a current roster of members at: - http://bochs.sourceforge.net/getinvolved.html + https://bochs.sourceforge.io/getinvolved.html .\"SKIP_SECTION" .SH BUGS Please report all bugs to the bug tracker on our web -site. Just go to http://bochs.sourceforge.net, and click +site. Just go to https://bochs.sourceforge.io, and click "Bug Reports" on the sidebar under "Feedback". .PP Provide a detailed description of the bug, the version of diff --git a/bochs/doc/man/bximage.1 b/bochs/doc/man/bximage.1 index e0256bdd6d..6cc714863f 100644 --- a/bochs/doc/man/bximage.1 +++ b/bochs/doc/man/bximage.1 @@ -1,5 +1,5 @@ .\"Document Author: Timothy R. Butler - tbutler@uninetsolutions.com" -.TH bximage 1 "10 Dec 2023" "bximage" "The Bochs Project" +.TH bximage 1 "26 Mar 2024" "bximage" "The Bochs Project" .\"SKIP_SECTION" .SH NAME bximage \- Interactive Disk Image Creation, Conversion, Resize and @@ -81,17 +81,17 @@ the lack of warranty. .\"SKIP_SECTION" .SH AVAILABILITY The latest version of this program can be found at: - http://bochs.sourceforge.net/getcurrent.html + https://bochs.sourceforge.io/getcurrent.html .\"SKIP_SECTION" .SH SEE ALSO bochs(1), bochsrc(5), bochs-dlx(1) .PP .nf The Bochs IA-32 Emulator site on the World Wide Web: - http://bochs.sourceforge.net + https://bochs.sourceforge.io Online Bochs Documentation - http://bochs.sourceforge.net/doc/docbook + https://bochs.sourceforge.io/doc/docbook .fi .\"SKIP_SECTION" .SH AUTHORS @@ -102,7 +102,7 @@ by Volker Ruppert. .\"SKIP_SECTION" .SH BUGS Please report all bugs to the bug tracker on our web -site. Just go to http://bochs.sourceforge.net, and click +site. Just go to https://bochs.sourceforge.io, and click "Bug Reports" on the sidebar under "Feedback." .PP Provide a detailed description of the bug, the version of diff --git a/bochs/extplugin.h b/bochs/extplugin.h index 9acc1ee1ab..834f02d1d5 100644 --- a/bochs/extplugin.h +++ b/bochs/extplugin.h @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2021 The Bochs Project +// Copyright (C) 2002-2024 The Bochs Project // // extplugin.h // @@ -23,7 +23,7 @@ #if BX_HAVE_LTDL #include #else -#include "ltdl-bochs.h" +#error Plugin support requires libltdl installed on your system #endif #endif diff --git a/bochs/gui/Makefile.in b/bochs/gui/Makefile.in index 335553d9c1..f03cdd61c1 100644 --- a/bochs/gui/Makefile.in +++ b/bochs/gui/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2001-2023 The Bochs Project +# Copyright (C) 2001-2024 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -242,7 +242,7 @@ gui.o: gui.@CPP_SUFFIX@ ../iodev/iodev.h ../bochs.h ../config.h ../osdep.h \ ../gui/bitmaps/floppyb.h ../gui/bitmaps/mouse.h ../gui/bitmaps/reset.h \ ../gui/bitmaps/power.h ../gui/bitmaps/snapshot.h ../gui/bitmaps/copy.h \ ../gui/bitmaps/paste.h ../gui/bitmaps/configbutton.h \ - ../gui/bitmaps/cdromd.h ../gui/bitmaps/userbutton.h \ + ../gui/bitmaps/cdrom1.h ../gui/bitmaps/userbutton.h \ ../gui/bitmaps/saverestore.h sdl.h keymap.o: keymap.@CPP_SUFFIX@ ../param_names.h ../bochs.h ../config.h ../osdep.h \ ../gui/paramtree.h ../logio.h \ @@ -336,7 +336,7 @@ wxdialog.o: wxdialog.@CPP_SUFFIX@ ../config.h ../param_names.h ../osdep.h \ ../gui/paramtree.h ../gui/siminterface.h ../logio.h wxdialog.h wxmain.h wxmain.o: wxmain.@CPP_SUFFIX@ ../config.h ../param_names.h ../osdep.h \ ../gui/paramtree.h ../gui/siminterface.h ../bxversion.h wxdialog.h \ - wxmain.h ../extplugin.h bitmaps/cdromd.xpm bitmaps/copy.xpm \ + wxmain.h ../extplugin.h bitmaps/cdrom1.xpm bitmaps/copy.xpm \ bitmaps/floppya.xpm bitmaps/floppyb.xpm bitmaps/paste.xpm \ bitmaps/power.xpm bitmaps/reset.xpm bitmaps/snapshot.xpm \ bitmaps/mouse.xpm bitmaps/userbutton.xpm bitmaps/saverestore.xpm @@ -371,7 +371,7 @@ gui.lo: gui.@CPP_SUFFIX@ ../iodev/iodev.h ../bochs.h ../config.h ../osdep.h \ ../gui/bitmaps/floppyb.h ../gui/bitmaps/mouse.h ../gui/bitmaps/reset.h \ ../gui/bitmaps/power.h ../gui/bitmaps/snapshot.h ../gui/bitmaps/copy.h \ ../gui/bitmaps/paste.h ../gui/bitmaps/configbutton.h \ - ../gui/bitmaps/cdromd.h ../gui/bitmaps/userbutton.h \ + ../gui/bitmaps/cdrom1.h ../gui/bitmaps/userbutton.h \ ../gui/bitmaps/saverestore.h sdl.h keymap.lo: keymap.@CPP_SUFFIX@ ../param_names.h ../bochs.h ../config.h ../osdep.h \ ../gui/paramtree.h ../logio.h \ @@ -465,7 +465,7 @@ wxdialog.lo: wxdialog.@CPP_SUFFIX@ ../config.h ../param_names.h ../osdep.h \ ../gui/paramtree.h ../gui/siminterface.h ../logio.h wxdialog.h wxmain.h wxmain.lo: wxmain.@CPP_SUFFIX@ ../config.h ../param_names.h ../osdep.h \ ../gui/paramtree.h ../gui/siminterface.h ../bxversion.h wxdialog.h \ - wxmain.h ../extplugin.h bitmaps/cdromd.xpm bitmaps/copy.xpm \ + wxmain.h ../extplugin.h bitmaps/cdrom1.xpm bitmaps/copy.xpm \ bitmaps/floppya.xpm bitmaps/floppyb.xpm bitmaps/paste.xpm \ bitmaps/power.xpm bitmaps/reset.xpm bitmaps/snapshot.xpm \ bitmaps/mouse.xpm bitmaps/userbutton.xpm bitmaps/saverestore.xpm diff --git a/bochs/gui/bitmaps/cdromd.h b/bochs/gui/bitmaps/cdrom1.h similarity index 90% rename from bochs/gui/bitmaps/cdromd.h rename to bochs/gui/bitmaps/cdrom1.h index 45e8382e3b..e811fd4d35 100644 --- a/bochs/gui/bitmaps/cdromd.h +++ b/bochs/gui/bitmaps/cdrom1.h @@ -2,10 +2,10 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// -#define BX_CDROMD_BMAP_X 32 -#define BX_CDROMD_BMAP_Y 32 +#define BX_CDROM1_BMAP_X 32 +#define BX_CDROM1_BMAP_Y 32 -static const unsigned char bx_cdromd_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/8] = { +static const unsigned char bx_cdrom1_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0e, 0x00, 0x00, 0x10, 0x12, 0x00, 0x00, 0x10, 0x12, 0x00, 0x00, 0x10, 0x12, 0x00, 0x00, 0x60, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x0c, 0x30, 0x00, @@ -19,7 +19,7 @@ static const unsigned char bx_cdromd_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/ 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static const unsigned char bx_cdromd_eject_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/8] = { +static const unsigned char bx_cdrom1_eject_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/8] = { 0x01, 0x00, 0x00, 0x80, 0x02, 0x60, 0x0e, 0x40, 0x04, 0x10, 0x12, 0x20, 0x08, 0x10, 0x12, 0x10, 0x10, 0x10, 0x12, 0x08, 0x20, 0x60, 0x0e, 0x04, 0x40, 0x00, 0x00, 0x02, 0x80, 0xf0, 0x0f, 0x01, 0x00, 0x0d, 0xb0, 0x00, diff --git a/bochs/gui/bitmaps/cdromd.xpm b/bochs/gui/bitmaps/cdrom1.xpm similarity index 97% rename from bochs/gui/bitmaps/cdromd.xpm rename to bochs/gui/bitmaps/cdrom1.xpm index a9f9d97903..d694391885 100644 --- a/bochs/gui/bitmaps/cdromd.xpm +++ b/bochs/gui/bitmaps/cdrom1.xpm @@ -1,5 +1,5 @@ /* XPM */ -static const char *cdromd_xpm[] = { +static const char *cdrom1_xpm[] = { /* width height num_colors chars_per_pixel */ " 32 32 2 1", /* colors */ diff --git a/bochs/gui/bitmaps/cdrom1_eject.xpm b/bochs/gui/bitmaps/cdrom1_eject.xpm new file mode 100644 index 0000000000..c345032035 --- /dev/null +++ b/bochs/gui/bitmaps/cdrom1_eject.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static const char *cdrom1_eject_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 2 1 ", +" c None", +". c black", +/* pixels */ +". .", +" . .. ... . ", +" . . . . . ", +" . . . . . ", +" . . . . . ", +" . .. ... . ", +" . . ", +" . ........ . ", +" . .. .. . ", +" . ...... . ", +" . ... ... . ", +" . ... ...... ... . ", +" . . .. .. . . ", +" . . . ...... . . . ", +" . . . . . . . . . . ", +" . . . . .... . . . . ", +" . . . . . .. . . . . . ", +" . . . . . . . . . . . . ", +" . . . . .. .. . . . . ", +" . . . . . . . . . . ", +" . . . ... ... . . . ", +" . . . . . . . . . . ", +" . . . . .... . . . . ", +" . ... . . ... . ", +" . .. . ...... . .. . ", +" . . .. .. . . ", +" . . .. ...... .. . . ", +" . . .. .. . . ", +" . . ...... . . ", +" . .. .. . ", +" . ........ . ", +". ." +}; diff --git a/bochs/gui/bitmaps/floppya_eject.xpm b/bochs/gui/bitmaps/floppya_eject.xpm new file mode 100644 index 0000000000..f3f9a22d65 --- /dev/null +++ b/bochs/gui/bitmaps/floppya_eject.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static const char *floppya_eject_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 2 1 ", +" c None", +". c black", +/* pixels */ +". . .", +" . . . . ", +" . . . . . ", +" . ... . ", +" . .. .. . . ", +" . .. .. . ", +" . . ", +" ...................... ", +" .... .... ", +" . ................ . ", +" . . . . . . ", +" .... ............ .... ", +" .... . . .... ", +" .... ............ .... ", +" .... . . .... ", +" .... ............ .... ", +" .... .. .... ", +" .... ............ .... ", +" .... . . .... ", +" .... ............ .... ", +" .... . . .... ", +" ...................... ", +" ...................... ", +" ...................... ", +" ...................... ", +" ....... . . . . ...... ", +" ...... ..... . . ..... ", +" ........ ... . . ....... ", +" . ...... ..... . . ..... . ", +" . ...... ... . . ...... . ", +" . .... . . . . . ..... . ", +". .... . . . . ...... ." +}; diff --git a/bochs/gui/bitmaps/floppyb_eject.xpm b/bochs/gui/bitmaps/floppyb_eject.xpm new file mode 100644 index 0000000000..d9ce898e53 --- /dev/null +++ b/bochs/gui/bitmaps/floppyb_eject.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static const char *floppyb_eject_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 2 1 ", +" c None", +". c black", +/* pixels */ +". ... .", +" . . . . ", +" . ... . . ", +" . . . . ", +" . . . . . ", +" . ... . ", +" . . ", +" ...................... ", +" .... .... ", +" . ................ . ", +" . . . . . . ", +" .... ............ .... ", +" .... . . .... ", +" .... ............ .... ", +" .... . . .... ", +" .... ............ .... ", +" .... .. .... ", +" .... ............ .... ", +" .... . . .... ", +" .... ............ .... ", +" .... . . .... ", +" ...................... ", +" ...................... ", +" ...................... ", +" ...................... ", +" ....... . . . . ...... ", +" ...... ..... . . ..... ", +" ........ ... . . ....... ", +" . ...... ..... . . ..... . ", +" . ...... ... . . ...... . ", +" . .... . . . . . ..... . ", +". .... . . . . ...... ." +}; diff --git a/bochs/gui/bitmaps/mouse_dis.xpm b/bochs/gui/bitmaps/mouse_dis.xpm new file mode 100644 index 0000000000..6a41a7015d --- /dev/null +++ b/bochs/gui/bitmaps/mouse_dis.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static const char *mouse_dis_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 2 1 ", +" c None", +". c black", +/* pixels */ +". .", +" . ...... . ", +" . .......... . ", +" . .. .. . ", +" . .. .. . ", +" . .. . . ", +" ............. .. . ", +" .. . .. ... ", +" . . .. . . .. ", +" . ... ... ... . .. ", +" . ... ... ... . . .. ", +" . ... ....... . . .. ", +" . ... ... ... . . . ", +" . ... ... ... . . .. ", +" . ... ... ... .. .. ", +" . . . . .. .. ", +" .. .. ... ", +" . . .. ", +" .. . .. . ", +" . . . . ", +" .. . .. . ", +" . . . . ", +" .. . .. . ", +" . . . . ", +" .. . .. . ", +" . . . . . . ", +" .. . . .. . ", +" . . . . . . . . . ", +" .. . . . . . .. . ", +" .............. . ", +" . . ", +". ." +}; diff --git a/bochs/gui/bitmaps/usb.h b/bochs/gui/bitmaps/usb.h index 5fb6538e2f..eee8460b29 100644 --- a/bochs/gui/bitmaps/usb.h +++ b/bochs/gui/bitmaps/usb.h @@ -5,7 +5,7 @@ #define BX_USB_BMAP_X 32 #define BX_USB_BMAP_Y 32 -static const unsigned char bx_usb_bmap[(BX_USB_BMAP_X * BX_USB_BMAP_Y)/8] = { +static const unsigned char bx_usbdbg_bmap[(BX_USB_BMAP_X * BX_USB_BMAP_Y)/8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0x07, 0xF0, 0x01, 0x80, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x01, 0x80, 0x0F, 0xF0, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0x0F, @@ -19,7 +19,7 @@ static const unsigned char bx_usb_bmap[(BX_USB_BMAP_X * BX_USB_BMAP_Y)/8] = { 0xC0, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0x01 }; -static const unsigned char bx_usb_eject_bmap[(BX_USB_BMAP_X * BX_USB_BMAP_Y)/8] = { +static const unsigned char bx_usbdbg_dis_bmap[(BX_USB_BMAP_X * BX_USB_BMAP_Y)/8] = { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0xC4, 0xFF, 0xFF, 0x23, 0xE8, 0xFF, 0xFF, 0x17, 0xE0, 0x01, 0x80, 0x07, 0xD0, 0x00, 0x00, 0x0B, 0xB0, 0x01, 0x80, 0x0D, 0x70, 0xFF, 0xFF, 0x0E, 0xF0, 0xFE, 0x7F, 0x0F, @@ -33,7 +33,7 @@ static const unsigned char bx_usb_eject_bmap[(BX_USB_BMAP_X * BX_USB_BMAP_Y)/8] 0xC2, 0xFF, 0xFF, 0x43, 0x80, 0xFF, 0xFF, 0x01 }; -static const unsigned char bx_usb_trigger_bmap[(BX_USB_BMAP_X * BX_USB_BMAP_Y)/8] = { +static const unsigned char bx_usbdbg_trigger_bmap[(BX_USB_BMAP_X * BX_USB_BMAP_Y)/8] = { 0x08, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x40, 0xC2, 0xFF, 0xFF, 0x23, 0xE4, 0xFF, 0xFF, 0x47, 0xF8, 0x01, 0x80, 0x8F, 0xF4, 0x00, 0x00, 0x4F, 0xF2, 0x01, 0x80, 0x2F, 0xF4, 0xFF, 0xFF, 0x4F, 0xF8, 0xFF, 0xFF, 0x8F, diff --git a/bochs/gui/bitmaps/usb.xpm b/bochs/gui/bitmaps/usbdbg.xpm similarity index 97% rename from bochs/gui/bitmaps/usb.xpm rename to bochs/gui/bitmaps/usbdbg.xpm index 247c6ffb6f..d1efb1b9e1 100644 --- a/bochs/gui/bitmaps/usb.xpm +++ b/bochs/gui/bitmaps/usbdbg.xpm @@ -1,5 +1,5 @@ /* XPM */ -static const char *usb_xpm[] = { +static const char *usbdbg_xpm[] = { /* width height num_colors chars_per_pixel */ " 32 32 2 1", /* colors */ diff --git a/bochs/gui/bitmaps/usbdbg_trigger.xpm b/bochs/gui/bitmaps/usbdbg_trigger.xpm new file mode 100644 index 0000000000..17c6b769d9 --- /dev/null +++ b/bochs/gui/bitmaps/usbdbg_trigger.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static const char *usbdbg_trigger_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 2 1 ", +". c None", +"# c black", +/* pixels */ +"...#...........................#", +"..#...........................#.", +".#....####################...#..", +"..#..######################...#.", +"...######..............#####...#", +"..#.####................####..#.", +".#..#####..............#####.#..", +"..#.########################..#.", +"...#########################...#", +"..#.########################..#.", +".#..########################.#..", +"..#.########################..#.", +"...#########################...#", +"..#.########################..#.", +".#..########################.#..", +"..#.########################..#.", +"...#########################...#", +"..#.########################..#.", +".#..########################.#..", +"..#.########################..#.", +"...#########################...#", +"..#.########################..#.", +".#...######################..#..", +"..#...##................##....#.", +"...#..##................##.....#", +"..#...##..##........##..##....#.", +".#....##..##........##..##...#..", +"..#...##..##........##..##....#.", +"...#..##..##........##..##.....#", +"..#...##................##....#.", +".#....####################...#..", +"..#....##################.....#." +}; diff --git a/bochs/gui/enh_dbg.cc b/bochs/gui/enh_dbg.cc index 4cf869cc30..2b6c34738f 100644 --- a/bochs/gui/enh_dbg.cc +++ b/bochs/gui/enh_dbg.cc @@ -8,7 +8,7 @@ // // Modified by Bruce Ewing // -// Copyright (C) 2008-2021 The Bochs Project +// Copyright (C) 2008-2024 The Bochs Project #include "config.h" @@ -237,6 +237,8 @@ unsigned short RWPSnapCount; bx_phy_address WWP_Snapshot[16]; bx_phy_address RWP_Snapshot[16]; +bool global_ini; +char ini_path[BX_PATHNAME_LEN]; char *debug_cmd; bool debug_cmd_ready; bool vgaw_refresh; @@ -1230,7 +1232,7 @@ void InitRegObjects() while (--i >= 0) RegObject[cpu][i] = (bx_param_num_c *) NULL; - char pname[16]; + char pname[20]; sprintf (pname,"bochs.cpu%d", cpu); // set the "cpu number" for cpu_list cpu_list = (bx_list_c *) SIM->get_param(pname, root_param); @@ -1360,14 +1362,24 @@ void InitRegObjects() void doUpdate() { + Bit8u tmpbuffer[4096]; + void FillStack(); + void RefreshDataDump(Bit8u *buffer); + if (doSimuInit != FALSE) SpecialInit(); // begin an autoupdate of Register and Asm windows LoadRegList(); // build and show ListView ParseBkpt(); // get the linear breakpoint list - if (DViewMode == VIEW_STACK) // in stack view mode, keep the stack updated + if (DViewMode == VIEW_STACK) { // in stack view mode, keep the stack updated FillStack(); + } else if ((DViewMode == VIEW_MEMDUMP) && DumpInitted) { + RefreshDataDump(tmpbuffer); + if (memcmp(DataDump, tmpbuffer, 4096)) { + doDumpRefresh = TRUE; + } + } CurrentAsmLA = BX_CPU(CurrentCPU)->get_laddr(BX_SEG_REG_CS, (bx_address) rV[RIP_Rnum]); if (CurrentAsmLA < BottomAsmLA || CurrentAsmLA > TopAsmLA) { @@ -1994,7 +2006,7 @@ void FillBrkp() } // performs endian byteswapping the hard way, for a Data dump -void FillDataX(char* t, char C, bool doHex) +void FillDataX(char* t, unsigned char C, bool doHex) { char tmpbuf[40]; char *d = tmpbuf; @@ -2007,8 +2019,8 @@ void FillDataX(char* t, char C, bool doHex) if (doHex != FALSE) { - *d = AsciiHex[2* (unsigned char)C]; - d[1] = AsciiHex[2* (unsigned char)C + 1]; + *d = AsciiHex[2*C]; + d[1] = AsciiHex[2*C + 1]; d[2] = 0; if (isLittleEndian) // little endian => reverse hex digits { @@ -2018,6 +2030,26 @@ void FillDataX(char* t, char C, bool doHex) } } +void RefreshDataDump(Bit8u *buffer) +{ + bool retval = TRUE; + + // re-load 4k DataDump array from bochs emulated linear or physical memory + if (LinearDump) { + // cannot read linear mem across a 4K boundary -- so break the read in two + // -- calculate location of 4K boundary (h): + unsigned len = (int) DumpStart & 0xfff; + unsigned i = 4096 - len; + Bit64u h = DumpStart + i; + retval = ReadBxLMem(DumpStart, i, buffer); + if (retval != FALSE && len != 0) + retval = ReadBxLMem(h, len, buffer + i); + } else { + retval = bx_mem.dbg_fetch_mem(BX_CPU(CurrentCPU), + (bx_phy_address)DumpStart, 4096, buffer); + } +} + // do the ShowData display work asynchronously, as a thread void ShowData() { @@ -2027,6 +2059,9 @@ void ShowData() char mdtxt[200]; char tmphex[40]; + if (doDumpRefresh) { + RefreshDataDump((Bit8u*)DataDump); + } *mdtxt = 0; cols[0]= mdtxt + 1; // the amount of storage needed for each column is complicated cols[1]= mdtxt + 20; @@ -2542,7 +2577,7 @@ void doFind() // Try ascii for additional matches and selected lines Select = TRUE; // this loop, only add selected lines to the display - by = strlen(tmpcb); + by = (int)strlen(tmpcb); for(i = 0, L = 0; i < 4096; i += 16, L++) { if (by != 0 && FindHex((unsigned char *)DataDump + i,16,(unsigned char *)tmpcb,by)) @@ -3456,17 +3491,43 @@ static size_t strip_whitespace(char *s) return ptr; } +static void get_bxshare_path(char *path) +{ + const char *varptr = NULL; + +#if BX_HAVE_GETENV + varptr = getenv("BXSHARE"); +#endif + if (varptr != NULL) { + sprintf(path, "%s", varptr); + } else { + varptr = get_builtin_variable("BXSHARE"); + if (varptr != NULL) { + sprintf(path, "%s", varptr); + } else { + strcpy(path, "."); + } + } +} + void ReadSettings() { FILE *fd = NULL; - char line[512]; + char line[512], path[BX_PATHNAME_LEN]; char *ret, *param, *val; bool format_checked = 0; size_t len1 = 0, len2; int i; - fd = fopen("bx_enh_dbg.ini", "r"); - if (fd == NULL) return; + if (global_ini) { + get_bxshare_path(path); + sprintf(ini_path, "%s/bx_enh_dbg.ini", path); + fd = fopen(ini_path, "r"); + } + if (fd == NULL) { + fd = fopen("bx_enh_dbg.ini", "r"); + if (fd == NULL) return; + } do { ret = fgets(line, sizeof(line)-1, fd); line[sizeof(line) - 1] = '\0'; @@ -3529,7 +3590,7 @@ void ReadSettings() DumpAlign = (1 << DumpWSIndex); PrevDAD = 0; } else if (!strcmp(param, "DockOrder")) { - DockOrder = strtoul(val, NULL, 16); + DockOrder = (short)strtoul(val, NULL, 16); } else if ((len1 == 15) && !strncmp(param, "ListWidthPix[", 13) && (param[14] == ']')) { if ((param[13] < '0') || (param[13] > '2')) { fprintf(stderr, "bx_enh_dbg.ini: invalid index for option SeeReg[x]\n"); @@ -3551,7 +3612,11 @@ void WriteSettings() FILE *fd = NULL; int i; - fd = fopen("bx_enh_dbg.ini", "w"); + if (global_ini) { + fd = fopen(ini_path, "w"); + } else { + fd = fopen("bx_enh_dbg.ini", "w"); + } if (fd == NULL) return; fprintf(fd, "# bx_enh_dbg_ini\n"); for (i = 0; i < 8; i++) { @@ -3576,12 +3641,13 @@ void WriteSettings() fclose(fd); } -void InitDebugDialog() +void InitDebugDialog(bool GlobalIni) { // redirect notify callback to the debugger specific code SIM->get_notify_callback(&old_callback, &old_callback_arg); assert (old_callback != NULL); SIM->set_notify_callback(enh_dbg_notify_callback, NULL); + global_ini = GlobalIni; ReadSettings(); DoAllInit(); // non-os-specific init stuff OSInit(); diff --git a/bochs/gui/enh_dbg.h b/bochs/gui/enh_dbg.h index aead6aca1e..158fd2fe30 100644 --- a/bochs/gui/enh_dbg.h +++ b/bochs/gui/enh_dbg.h @@ -186,11 +186,7 @@ extern short DockOrder; // set the default List "docking" (Reg, ASM, Dump // END of User Customizable settings #if !defined(_MSC_VER) -#if SIZEOF_UNSIGNED_LONG == 8 -#define FMT_LLCAPX "%016lX" -#else -#define FMT_LLCAPX "%016llX" -#endif +#define FMT_LLCAPX FMT_LL"X" #else #define FMT_LLCAPX "%016I64X" #endif diff --git a/bochs/gui/gtk_enh_dbg_osdep.cc b/bochs/gui/gtk_enh_dbg_osdep.cc index b3dc70ca20..e346c42100 100644 --- a/bochs/gui/gtk_enh_dbg_osdep.cc +++ b/bochs/gui/gtk_enh_dbg_osdep.cc @@ -8,7 +8,7 @@ // // Modified by Bruce Ewing // -// Copyright (C) 2008-2021 The Bochs Project +// Copyright (C) 2008-2024 The Bochs Project #include "bochs.h" #include "bx_debug/debug.h" @@ -17,6 +17,10 @@ #if BX_DEBUGGER && BX_DEBUGGER_GUI +#if BX_HAVE_GTK_VERSION == 2 +#define GTK_DISABLE_DEPRECATED +#endif + #include #include #include @@ -168,7 +172,7 @@ GtkWidget *LV[3]; // Register, ASM, MemDump / ListViews (TreeViews) // GTK-specific settings gint win_x = -1, win_y = -1, win_w, win_h; bool window_init = 0; -char fontname[80]; +char fontname[81]; bool font_init = 0; // HIHI put all these colors in an array, and use #defines for them @@ -227,8 +231,13 @@ bool ShowAskDialog() if (dialog == NULL) { dialog = gtk_dialog_new (); +#if BX_HAVE_GTK_VERSION == 2 gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); +#else + gtk_dialog_add_button (GTK_DIALOG (dialog), g_dgettext("gtk30", "_Cancel"), GTK_RESPONSE_CANCEL); + gtk_dialog_add_button (GTK_DIALOG (dialog), g_dgettext("gtk30", "_OK"), GTK_RESPONSE_OK); +#endif gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); } // HIHI should the "transient" line be INSIDE the dialog creation "if"? -- when I tried it, it crashed? @@ -582,7 +591,11 @@ int GetASMTopIdx() // Database = (GtkListStore *) gtk_tree_view_get_model( GTK_TREE_VIEW(LV[ASM_WND]) ); AsmPgSize = 0; - va = gtk_tree_view_get_vadjustment ( GTK_TREE_VIEW(LV[ASM_WND]) ); +#if BX_HAVE_GTK_VERSION == 2 + va = gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(LV[ASM_WND])); +#else + va = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(LV[ASM_WND])); +#endif // calculate the number of vertical "pixels" in one row (as a fraction of the scroll range) if (AsmLineCount == 0) return 0; @@ -597,7 +610,11 @@ int GetASMTopIdx() // -- it does not technically have to really be a pixel count void ScrollASM(int pixels) { - GtkAdjustment *va = gtk_tree_view_get_vadjustment ( GTK_TREE_VIEW(LV[ASM_WND]) ); +#if BX_HAVE_GTK_VERSION == 2 + GtkAdjustment *va = gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(LV[ASM_WND])); +#else + GtkAdjustment *va = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(LV[ASM_WND])); +#endif gtk_adjustment_set_value(GTK_ADJUSTMENT(va), gtk_adjustment_get_value(va) + pixels); } @@ -687,7 +704,9 @@ void VSizeChange() if (ShowIOWindows == FALSE) { gtk_widget_hide(IOVbox); +//#if BX_HAVE_GTK_VERSION == 2 gtk_table_resize(GTK_TABLE(TreeTbl), 3, 1); // IO windows do not exist, so total table rows = 3 +//#endif } else { @@ -697,7 +716,9 @@ void VSizeChange() gcp = gtk_entry_get_text(GTK_ENTRY(IEntry)); strcpy (tmpcb, gcp); gtk_entry_set_text(GTK_ENTRY(IEntry),""); +//#if BX_HAVE_GTK_VERSION == 2 gtk_table_resize(GTK_TABLE(TreeTbl), 4, 1); // IO windows exist, so total table rows = 4 +//#endif gtk_widget_show(IOVbox); gtk_widget_grab_focus(IEntry); // Input window loses focus while it is hidden gtk_entry_set_text(GTK_ENTRY(IEntry),tmpcb); @@ -828,7 +849,11 @@ void StartListUpdate(int listnum) static int PrevDV = -1; // type of previous Dump window that was displayed GtkListStore *Database; // set the scroll position back to the very top - GtkAdjustment *va = gtk_tree_view_get_vadjustment ( GTK_TREE_VIEW(LV[listnum]) ); +#if BX_HAVE_GTK_VERSION == 2 + GtkAdjustment *va = gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(LV[listnum])); +#else + GtkAdjustment *va = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(LV[listnum])); +#endif gtk_adjustment_set_value (GTK_ADJUSTMENT(va), 0); // then clear the database for the list that is updating Database = (GtkListStore *) gtk_tree_view_get_model( GTK_TREE_VIEW(LV[listnum]) ); @@ -1108,16 +1133,37 @@ bool NewFont() return FALSE; // need to know the current font, to highlight it g_object_get(G_OBJECT(LV_Rend[0]), "font", &ofn, NULL); +#if BX_HAVE_GTK_VERSION == 2 GtkWidget *widget = gtk_font_selection_dialog_new("Choose primary font"); gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(widget), ofn); - if (gtk_dialog_run(GTK_DIALOG (widget)) == GTK_RESPONSE_OK) { + if (gtk_dialog_run(GTK_DIALOG(widget)) == GTK_RESPONSE_OK) { char *nfn = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(widget)); strncpy(fontname, nfn, 80); g_free(nfn); update_font(); } - g_free(ofn); gtk_widget_destroy(widget); +#else + GtkWidget *dialog = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(dialog), "Select Font"); + gtk_dialog_add_button(GTK_DIALOG(dialog), g_dgettext("gtk30", "_OK"), GTK_RESPONSE_OK); + gtk_dialog_add_button(GTK_DIALOG(dialog), g_dgettext("gtk30", "_Cancel"), GTK_RESPONSE_CANCEL); + gtk_dialog_set_default_response(GTK_DIALOG (dialog), GTK_RESPONSE_OK); + GtkWidget *widget = gtk_font_chooser_widget_new(); + gtk_widget_show(widget); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), widget, TRUE, TRUE, 0); + gtk_font_chooser_set_font(GTK_FONT_CHOOSER(widget), ofn); + gtk_widget_show(dialog); + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { + char *nfn = gtk_font_chooser_get_font(GTK_FONT_CHOOSER(widget)); + strncpy(fontname, nfn, 80); + g_free(nfn); + update_font(); + } + gtk_widget_destroy(widget); + gtk_widget_destroy(dialog); +#endif + g_free(ofn); return TRUE; } @@ -1373,8 +1419,13 @@ void Close_cb(GtkWidget *widget, gpointer data) gtk_widget_destroy(PTree); g_object_unref(PTree); g_object_unref(LV[2]); +#if BX_HAVE_GTK_VERSION == 2 gdk_cursor_unref(SizeCurs); gdk_cursor_unref(DockCurs); +#else + g_object_unref(SizeCurs); + g_object_unref(DockCurs); +#endif if (!SIM->is_wx_selected()) { gtk_main_quit(); @@ -1670,7 +1721,14 @@ gboolean LEB_MouseUp(GtkWidget *widget, GdkEventButton *event, gpointer data) else // complete a Docking operation { // get "local" x mouse coordinate value (main window relative) +#if BX_HAVE_GTK_VERSION == 2 gdk_window_get_pointer(gtk_widget_get_window(LVEvtBox), &x, &zip, NULL); +#else + GdkDisplay* display = gdk_display_get_default(); + GdkSeat* seat = gdk_display_get_default_seat(display); + GdkDevice* pointer = gdk_seat_get_pointer(seat); + gdk_window_get_device_position(gtk_widget_get_window(LVEvtBox), pointer, &x, &zip, NULL); +#endif // verify that mouseup was within a LV window if (x >= 0 && cy >= 0 && x < totwidth && cy < heightLV) { @@ -1818,7 +1876,13 @@ static gboolean VGAWrefreshTick(GtkWidget *widget) gint y; // enter pre-dock mode int i, j; --SizingDelay; - gdk_display_get_pointer (display, NULL, &x, &y, NULL); // absolute x and y mouse coords +#if BX_HAVE_GTK_VERSION == 2 + gdk_display_get_pointer(display, NULL, &x, &y, NULL); // absolute x and y mouse coords +#else + GdkSeat* seat = gdk_display_get_default_seat(display); + GdkDevice* pointer = gdk_seat_get_pointer(seat); + gdk_device_get_position(pointer, NULL, &x, &y); +#endif i = x - xClick; j = y - yClick; // calculate the pixel delta from the mousedown event to now if (i < 0) i= -i; @@ -2180,7 +2244,11 @@ bool OSInit() gtk_window_move(GTK_WINDOW(window), win_x, win_y); } +#if BX_HAVE_GTK_VERSION == 2 MainVbox = gtk_vbox_new(FALSE, 0); // vbox that contains EVERYTHING +#else + MainVbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); +#endif gtk_container_add(GTK_CONTAINER(window), MainVbox); @@ -2188,7 +2256,11 @@ bool OSInit() InitMenus(); // build the StatusBar +#if BX_HAVE_GTK_VERSION == 2 StatHbox = gtk_hbox_new(FALSE, 3); +#else + StatHbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3); +#endif Stat[0] = gtk_label_new("Break"); gtk_label_set_width_chars (GTK_LABEL(Stat[0]), 7); Stat[1] = gtk_label_new("CPU:"); @@ -2196,9 +2268,15 @@ bool OSInit() Stat[2] = gtk_label_new("t=0"); gtk_label_set_width_chars (GTK_LABEL(Stat[2]), 19); Stat[3] = gtk_label_new("IOPL"); +#if BX_HAVE_GTK_VERSION == 2 StatVSep1 = gtk_vseparator_new(); StatVSep2 = gtk_vseparator_new(); StatVSep3 = gtk_vseparator_new(); +#else + StatVSep1 = gtk_separator_new(GTK_ORIENTATION_VERTICAL); + StatVSep2 = gtk_separator_new(GTK_ORIENTATION_VERTICAL); + StatVSep3 = gtk_separator_new(GTK_ORIENTATION_VERTICAL); +#endif gtk_box_pack_start(GTK_BOX(StatHbox), Stat[0], FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(StatHbox), StatVSep1, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(StatHbox), Stat[1], FALSE, FALSE, 0); @@ -2207,25 +2285,46 @@ bool OSInit() gtk_box_pack_start(GTK_BOX(StatHbox), StatVSep3, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(StatHbox), Stat[3], TRUE, TRUE, 0); // set LEFT, instead of the default centered "justification" of status text +#if BX_HAVE_GTK_VERSION == 2 gtk_misc_set_alignment(GTK_MISC(Stat[0]), (gfloat) 0., (gfloat) 0.5); gtk_misc_set_alignment(GTK_MISC(Stat[1]), (gfloat) 0., (gfloat) 0.5); gtk_misc_set_alignment(GTK_MISC(Stat[2]), (gfloat) 0., (gfloat) 0.5); gtk_misc_set_alignment(GTK_MISC(Stat[3]), (gfloat) 0., (gfloat) 0.5); +#else + gtk_widget_set_halign(GTK_WIDGET(Stat[0]), GTK_ALIGN_START); + gtk_widget_set_valign(GTK_WIDGET(Stat[0]), GTK_ALIGN_CENTER); + gtk_widget_set_halign(GTK_WIDGET(Stat[1]), GTK_ALIGN_START); + gtk_widget_set_valign(GTK_WIDGET(Stat[1]), GTK_ALIGN_CENTER); + gtk_widget_set_halign(GTK_WIDGET(Stat[2]), GTK_ALIGN_START); + gtk_widget_set_valign(GTK_WIDGET(Stat[2]), GTK_ALIGN_CENTER); + gtk_widget_set_halign(GTK_WIDGET(Stat[3]), GTK_ALIGN_START); + gtk_widget_set_valign(GTK_WIDGET(Stat[3]), GTK_ALIGN_CENTER); +#endif gtk_box_pack_start(GTK_BOX(MainVbox), menubar, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(MainVbox), StatHbox, FALSE, FALSE, 0); // build the table that holds the TreeView/Input&Output windows TreeTbl = gtk_table_new(4, 1, TRUE); // proportion the remaining space in quarters, vertically +#if BX_HAVE_GTK_VERSION == 2 sep8 = gtk_vseparator_new(); // vertical separators between the ListViews sep9 = gtk_vseparator_new(); +#else +// TreeTbl = gtk_grid_new(); // TODO + sep8 = gtk_separator_new(GTK_ORIENTATION_VERTICAL); + sep9 = gtk_separator_new(GTK_ORIENTATION_VERTICAL); +#endif VSepEvtBox1 = gtk_event_box_new(); // seps need event boxes to catch "Enter" events VSepEvtBox2 = gtk_event_box_new(); gtk_container_add (GTK_CONTAINER(VSepEvtBox1), sep8); gtk_container_add (GTK_CONTAINER(VSepEvtBox2), sep9); gtk_widget_add_events(VSepEvtBox1, GDK_ENTER_NOTIFY_MASK); // masks must be set immediately after creation gtk_widget_add_events(VSepEvtBox2, GDK_ENTER_NOTIFY_MASK); +#if BX_HAVE_GTK_VERSION == 2 IOVbox = gtk_vbox_new(FALSE, 0); // stack the Input Entry and Output TextView vertically +#else + IOVbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); +#endif // create Input window IEntry = gtk_entry_new(); @@ -2248,13 +2347,21 @@ bool OSInit() gtk_box_pack_start(GTK_BOX(IOVbox), ScrlWinOut, TRUE, TRUE, 0); gtk_box_pack_end(GTK_BOX(IOVbox), IEntry, FALSE, FALSE, 0); +#if BX_HAVE_GTK_VERSION == 2 LVHbox = gtk_hbox_new(FALSE, 0); // to hold the ListView windows +#else + LVHbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); +#endif LVEvtBox = gtk_event_box_new(); // need to catch "leave" and "move" events for ListViews gtk_container_add (GTK_CONTAINER(LVEvtBox), LVHbox); gtk_widget_add_events(LVEvtBox, GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK); // make Command and CPU Button rows +#if BX_HAVE_GTK_VERSION == 2 CmdBHbox = gtk_hbox_new(TRUE, 0); +#else + CmdBHbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); +#endif for (i=0 ; i < 5 ; i++) { @@ -2270,7 +2377,11 @@ bool OSInit() // CPU button row does not exist for only 1 cpu if (BX_SMP_PROCESSORS > 1) { +#if BX_HAVE_GTK_VERSION == 2 CpuBHbox = gtk_hbox_new(TRUE, 0); +#else + CpuBHbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); +#endif gtk_box_pack_start(GTK_BOX(MainVbox), CpuBHbox, FALSE, FALSE, 0); i = 0; strcpy (bigbuf, "CPU0"); // Handle CPU0 specially -- it is "selected" @@ -2289,8 +2400,13 @@ bool OSInit() gtk_box_pack_end(GTK_BOX(MainVbox), TreeTbl, TRUE, TRUE, 0); +//#if BX_HAVE_GTK_VERSION == 2 gtk_table_attach_defaults(GTK_TABLE(TreeTbl), LVEvtBox, 0, 1, 0, 3); // order = LRTB gtk_table_attach_defaults(GTK_TABLE(TreeTbl), IOVbox, 0, 1, 3, 4); +//#else +// gtk_grid_attach(GTK_GRID(TreeTbl), LVEvtBox, 0, 0, 3, 3); // order = LTWH +// gtk_grid_attach(GTK_GRID(TreeTbl), IOVbox, 0, 3, 3, 1); +//#endif VSizeChange(); // build the 3 ListView windows @@ -2343,10 +2459,17 @@ bool OSInit() gtk_event_box_set_visible_window (GTK_EVENT_BOX(VSepEvtBox2), FALSE); gtk_event_box_set_above_child (GTK_EVENT_BOX(VSepEvtBox2), TRUE); // build the sizing/docking cursors - SizeCurs = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW); - DockCurs = gdk_cursor_new (GDK_CROSSHAIR); +#if BX_HAVE_GTK_VERSION == 2 + SizeCurs = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW); + DockCurs = gdk_cursor_new(GDK_CROSSHAIR); gdk_cursor_ref(SizeCurs); gdk_cursor_ref(DockCurs); +#else + SizeCurs = gdk_cursor_new_for_display(gdk_display_get_default(), GDK_SB_H_DOUBLE_ARROW); + DockCurs = gdk_cursor_new_for_display(gdk_display_get_default(), GDK_CROSSHAIR); + g_object_ref(SizeCurs); + g_object_ref(DockCurs); +#endif if (!font_init) { char *fn; diff --git a/bochs/gui/gtk_usb_debug.cc b/bochs/gui/gtk_usb_debug.cc new file mode 100644 index 0000000000..2d17642ac7 --- /dev/null +++ b/bochs/gui/gtk_usb_debug.cc @@ -0,0 +1,865 @@ +///////////////////////////////////////////////////////////////////////// +// $Id$ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 Benjamin David Lunt +// Copyright (C) 2003-2024 The Bochs Project +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#include "bochs.h" +#include "siminterface.h" +#include "param_names.h" + +#if BX_USB_DEBUGGER + +#include "usb_debug.h" +// hacks for iodev / USB internals +#include "iodev.h" +#include "iodev/usb/usb_common.h" + +#include +#include + +typedef struct { + const char *name; + GtkWidget *entry; + Bit8u fmt_size; + const struct S_ATTRIBUTES *attr; +} usb_reg_t; + +const char *chkTxt[6] = {"Reset", "Enable", "Event", "Doorbell", "Start of Frame", "Non-Exist"}; +const char *chkBXPN[6] = {BXPN_USB_DEBUG_RESET, BXPN_USB_DEBUG_ENABLE, BXPN_USB_DEBUG_EVENT, + BXPN_USB_DEBUG_DOORBELL, BXPN_USB_DEBUG_START_FRAME, BXPN_USB_DEBUG_NON_EXIST}; + +GtkWidget *main_dialog; +GtkWidget *uhci_entry[UHCI_REG_COUNT]; +GtkWidget *DFframe, *DFvbox, *checkbox[6]; +GtkWidget *apply_button; + +// multithreading using pure posix threads -- not glib threads +static void * EventLp(void *data) +{ + gtk_main(); + return NULL; +} + +static void MakeGTKthreads() +{ + pthread_t hThread; + pthread_create(&hThread, NULL, EventLp, NULL); +} + +GtkWidget* usbdlg_create_label(GtkWidget *box, const char *text, bool expand = true) +{ + GtkWidget *label = gtk_label_new(text); + gtk_box_pack_start(GTK_BOX(box), label, expand, expand, 2); + return label; +} + +GtkWidget* usbdlg_create_entry_with_label(GtkWidget **box, const char *text, + bool expand = true) +{ + gtk_box_pack_start(GTK_BOX(box[0]), gtk_label_new(text), expand, expand, 2); + GtkWidget *entry = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(box[1]), entry, expand, expand, 2); + return entry; +} + +GtkWidget* usbdlg_create_ro_entry(GtkWidget *box, bool expand = true) +{ + GtkWidget *entry = gtk_entry_new(); + gtk_widget_set_sensitive(entry, 0); + gtk_box_pack_start(GTK_BOX(box), entry, expand, expand, 2); + return entry; +} + +GtkWidget* usbdlg_create_ro_entry_with_label(GtkWidget **box, const char *text, + bool expand = true) +{ + gtk_box_pack_start(GTK_BOX(box[0]), gtk_label_new(text), expand, expand, 2); + GtkWidget *entry = gtk_entry_new(); + gtk_widget_set_sensitive(entry, 0); + gtk_box_pack_start(GTK_BOX(box[1]), entry, expand, expand, 2); + return entry; +} + +void usbdlg_create_debug_flags(GtkWidget *vbox) +{ + DFframe = gtk_frame_new("Debug Flags"); + gtk_box_pack_start(GTK_BOX(vbox), DFframe, FALSE, FALSE, 2); + DFvbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_container_add(GTK_CONTAINER(DFframe), DFvbox); + for (int i = 0; i < 6; i++) { + checkbox[i] = gtk_check_button_new_with_label(chkTxt[i]); + if (SIM->get_param_num(chkBXPN[i])->get() > 0) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox[i]), TRUE); + } + gtk_box_pack_start(GTK_BOX(DFvbox), checkbox[i], FALSE, FALSE, 2); + } +} + +void usbdlg_set_debug_flags() +{ + for (int i = 0; i < 6; i++) { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox[i]))) { + SIM->get_param_num(chkBXPN[i])->set(1); + } else { + SIM->get_param_num(chkBXPN[i])->set(0); + } + } +} + +static void usb_regview_dialog(GtkWidget *widget, gpointer data) +{ + int i, ret; + char buffer[32], format[10]; + Bit32u oldval, value; + + usb_reg_t *usb_reg_def = (usb_reg_t*)data; + GtkWidget *dialog = + gtk_dialog_new_with_buttons(usb_reg_def->name, GTK_WINDOW(main_dialog), GTK_DIALOG_MODAL, + g_dgettext("gtk30", "_OK"), GTK_RESPONSE_OK, + g_dgettext("gtk30", "_Cancel"), GTK_RESPONSE_CANCEL, + NULL); + gtk_window_set_default_size(GTK_WINDOW(dialog), 250, 250); + GtkWidget *listbox = gtk_list_box_new(); + gtk_list_box_set_selection_mode(GTK_LIST_BOX(listbox), GTK_SELECTION_MULTIPLE); + gtk_list_box_set_activate_on_single_click(GTK_LIST_BOX(listbox), 1); + i = 0; + while (usb_reg_def->attr[i].index > -1) { + gtk_list_box_insert(GTK_LIST_BOX(listbox), gtk_label_new(usb_reg_def->attr[i].str), -1); + i++; + } + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), listbox, TRUE, TRUE, 2); + // Show dialog + gtk_widget_show_all(dialog); + oldval = strtoul(gtk_entry_get_text(GTK_ENTRY(usb_reg_def->entry)), NULL, 16); + i = 0; + while (usb_reg_def->attr[i].index > -1) { + if ((oldval & usb_reg_def->attr[i].mask) != 0) { + gtk_list_box_select_row(GTK_LIST_BOX(listbox), + gtk_list_box_get_row_at_index(GTK_LIST_BOX(listbox), i)); + } else { + gtk_list_box_unselect_row(GTK_LIST_BOX(listbox), + gtk_list_box_get_row_at_index(GTK_LIST_BOX(listbox), i)); + } + i++; + } + ret = gtk_dialog_run(GTK_DIALOG(dialog)); + if (ret == GTK_RESPONSE_OK) { + value = 0; + i = 0; + while (usb_reg_def->attr[i].index > -1) { + if (gtk_list_box_row_is_selected(gtk_list_box_get_row_at_index(GTK_LIST_BOX(listbox), i))) { + value |= usb_reg_def->attr[i].mask; + } + i++; + } + if (value != oldval) { + sprintf(format, "0x%%0%iX", usb_reg_def->fmt_size); + sprintf(buffer, format, value); + gtk_entry_set_text(GTK_ENTRY(usb_reg_def->entry), buffer); + } + } + gtk_widget_destroy(dialog); +} + +// Save UHCI state to controller + +int hc_uhci_save() +{ + char buffer[COMMON_STR_SIZE]; + + if (u_changed[UHCI_REG_COMMAND]) { + strcpy(buffer, gtk_entry_get_text(GTK_ENTRY(uhci_entry[UHCI_REG_COMMAND]))); + usb_io_write(pci_bar_address + 0, strtol(buffer, NULL, 0), 2); + } + if (u_changed[UHCI_REG_STATUS]) { + strcpy(buffer, gtk_entry_get_text(GTK_ENTRY(uhci_entry[UHCI_REG_STATUS]))); + usb_io_write(pci_bar_address + 2, strtol(buffer, NULL, 0), 2); + } + if (u_changed[UHCI_REG_INTERRUPT]) { + strcpy(buffer, gtk_entry_get_text(GTK_ENTRY(uhci_entry[UHCI_REG_INTERRUPT]))); + usb_io_write(pci_bar_address + 4, strtol(buffer, NULL, 0), 2); + } + if (u_changed[UHCI_REG_FRAME_NUM]) { + strcpy(buffer, gtk_entry_get_text(GTK_ENTRY(uhci_entry[UHCI_REG_FRAME_NUM]))); + usb_io_write(pci_bar_address + 6, strtol(buffer, NULL, 0), 2); + } + if (u_changed[UHCI_REG_FRAME_ADDR]) { + strcpy(buffer, gtk_entry_get_text(GTK_ENTRY(uhci_entry[UHCI_REG_FRAME_ADDR]))); + usb_io_write(pci_bar_address + 8, strtol(buffer, NULL, 0), 4); + } + if (u_changed[UHCI_REG_SOF]) { + strcpy(buffer, gtk_entry_get_text(GTK_ENTRY(uhci_entry[UHCI_REG_SOF]))); + usb_io_write(pci_bar_address + 12, strtol(buffer, NULL, 0), 1); + } + if (u_changed[UHCI_REG_PORT0]) { + strcpy(buffer, gtk_entry_get_text(GTK_ENTRY(uhci_entry[UHCI_REG_PORT0]))); + usb_io_write(pci_bar_address + 16, strtol(buffer, NULL, 0), 2); + } + if (u_changed[UHCI_REG_PORT1]) { + strcpy(buffer, gtk_entry_get_text(GTK_ENTRY(uhci_entry[UHCI_REG_PORT1]))); + usb_io_write(pci_bar_address + 18, strtol(buffer, NULL, 0), 2); + } + + memset(u_changed, 0, sizeof(u_changed)); + gtk_widget_set_sensitive(apply_button, 0); + + return 0; +} + +// Apply button support + +static void on_entry_changed(GtkWidget *widget, gpointer data) +{ + *((bool*)data) = 1; + gtk_widget_set_sensitive(apply_button, 1); +} + +static void apply_changes(GtkWidget *widget, gpointer data) +{ + if (usb_debug_type == USB_DEBUG_UHCI) { + hc_uhci_save(); + } else { + GtkWidget* error = gtk_message_dialog_new( + GTK_WINDOW(main_dialog), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, + "Saving changes to controller not implemented yet"); + gtk_window_set_title(GTK_WINDOW(error), "WARNING"); + gtk_dialog_run(GTK_DIALOG(error)); + gtk_widget_destroy(error); + } +} + +void usbdlg_create_apply_button(GtkWidget *vbox) +{ + GtkWidget *apply_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(vbox), apply_hbox, FALSE, FALSE, 2); + apply_button = gtk_button_new_with_label(g_dgettext("gtk30", "_Apply")); + gtk_widget_set_sensitive(apply_button, 0); + g_signal_connect(apply_button, "clicked", G_CALLBACK(apply_changes), NULL); + gtk_box_pack_start(GTK_BOX(apply_hbox), apply_button, FALSE, FALSE, 2); +} + +int tree_items = 0; + +void hc_uhci_do_item(GtkWidget *treeview, Bit32u FrameAddr, Bit32u FrameNum) +{ + struct USB_UHCI_QUEUE_STACK queue_stack; + Bit32u item, queue_addr = 0; + struct QUEUE queue; + struct TD td; + char str[COMMON_STR_SIZE]; + Bit32u state; + GtkTreeViewColumn *treecol; + GtkCellRenderer *renderer; + GtkTreeStore *treestore; + + // get the frame pointer + DEV_MEM_READ_PHYSICAL(FrameAddr, sizeof(Bit32u), (Bit8u *) &item); + sprintf(str, "Frame Pointer(%i): 0x%08X", FrameNum, item); + + treecol = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(treecol, str); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), treecol); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(treecol, renderer, TRUE); + gtk_tree_view_column_add_attribute(treecol, renderer, "text", 0); // pull display text from treestore col 0 + gtk_widget_set_can_focus(treeview, FALSE); + treestore = gtk_tree_store_new(1, G_TYPE_STRING); + gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(treestore)); + + queue_stack.queue_cnt = 0; + + // A catch to make sure we don't do too many + while (tree_items < 50) { + if (!USB_UHCI_IS_LINK_VALID(item)) // the the T bit is set, we are done + break; + + // is it a queue? + if (USB_UHCI_IS_LINK_QUEUE(item)) { + // add it to our current list of queues + if (uhci_add_queue(&queue_stack, item & ~0xF)) { + // if this queue has been added before, stop. + break; + } + + // read in the queue + DEV_MEM_READ_PHYSICAL(item & ~0xF, sizeof(struct QUEUE), (Bit8u *) &queue); + sprintf(str, "0x%08X: Queue Head: (0x%08X 0x%08X)", item & ~0xF, queue.horz, queue.vert); +// Next = TreeViewInsert(TreeView, Next, TVI_LAST, str, (LPARAM) ((item & ~0xF) | 1), 0); + + // if the vert pointer is valid, there are td's in it to process + // else only the head pointer may be valid + if (!USB_UHCI_IS_LINK_VALID(queue.vert)) { + // no vertical elements to process + // (clear queue_addr to indicate we are not processing + // elements of the vertical part of a queue) + queue_addr = 0; + item = queue.horz; + } else { + // there are vertical elements to process + // (save the address of the horz pointer in queue_addr + // so that we may update the queue's vertical pointer + // member with the successfully processed TD's link pointer) + queue_addr = item; + item = queue.vert; + } + continue; + } + + // we processed another td within this queue line + state = 0; // clear the state + DEV_MEM_READ_PHYSICAL(item & ~0xF, sizeof(struct TD), (Bit8u *) &td); + const bool depthbreadth = (td.dword0 & 0x0004) ? true : false; // 1 = depth first, 0 = breadth first + sprintf(str, "0x%08X: TD: (0x%08X)", item & ~0xF, td.dword0); +// if ((item & ~0xF) == (Bit32u) g_params.wParam) +// state |= TVIS_BOLD; +// hCur = TreeViewInsert(TreeView, Next, TVI_LAST, str, (LPARAM) ((item & ~0xF) | 0), state); +// if ((item & ~0xF) == (Bit32u) g_params.wParam) +// TreeView_Select(TreeView, hCur, TVGN_CARET); + item = td.dword0; + if (queue_addr != 0) { + // if breadth first or last in the element list, move on to next queue item + if (!depthbreadth || !USB_UHCI_IS_LINK_VALID(item)) { + item = queue.horz; + queue_addr = 0; + } + } + } +} + +// UHCI main dialog + +int uhci_debug_dialog(int type, int param1) +{ + bx_list_c *UHCI_state = NULL; + int i, ret; + Bit32u frame_addr, frame_num; + char buffer[COMMON_STR_SIZE]; + GtkWidget *mainVbox, *BAhbox, *hbox[2], *vbox[3], *ro_entry[4]; + GtkWidget *ORframe, *ORhbox, *ORvbox[3]; + GtkWidget *PRframe, *PRhbox, *PRvbox[3]; + GtkWidget *TVvbox, *FNhbox; + GtkWidget *button[8], *FNlabel, *treeview; + usb_reg_t uhci_reg_def[5] = { + {"Command Register", NULL, 4, attribs_u_command}, + {"Status Register", NULL, 4, attribs_u_status}, + {"Interrupt Enable Register", NULL, 4, attribs_u_interrupt}, + {"Port 0 Register", NULL, 4, attribs_u_ports}, + {"Port 1 Register", NULL, 4, attribs_u_ports} + }; + + UHCI_state = (bx_list_c*)SIM->get_param("usb_uhci", SIM->get_bochs_root()); + if (UHCI_state == NULL) + return -1; + + main_dialog = gtk_dialog_new(); + switch (type) { + case USB_DEBUG_FRAME: + gtk_window_set_title(GTK_WINDOW(main_dialog), "UHCI Debug Dialog: Break Type: Start of Frame"); + break; + case USB_DEBUG_COMMAND: + gtk_window_set_title(GTK_WINDOW(main_dialog), "UHCI Debug Dialog: Break Type: Doorbell"); + break; + case USB_DEBUG_NONEXIST: + gtk_window_set_title(GTK_WINDOW(main_dialog), "UHCI Debug Dialog: Break Type: Non-Existant Port Write"); + break; + case USB_DEBUG_RESET: + sprintf(buffer, "UHCI Debug Dialog: Break Type: Port %d Reset", param1); + gtk_window_set_title(GTK_WINDOW(main_dialog), buffer); + break; + case USB_DEBUG_ENABLE: + sprintf(buffer, "UHCI Debug Dialog: Break Type: Port %d Enable", param1); + gtk_window_set_title(GTK_WINDOW(main_dialog), buffer); + break; + default: + gtk_window_set_title(GTK_WINDOW(main_dialog), "UHCI Debug Dialog"); + } + gtk_window_set_default_size(GTK_WINDOW(main_dialog), 600, 500); + button[0] = gtk_dialog_add_button(GTK_DIALOG(main_dialog), "Continue", GTK_RESPONSE_OK); + button[1] = gtk_dialog_add_button(GTK_DIALOG(main_dialog), "Quit", GTK_RESPONSE_CANCEL); + gtk_dialog_set_default_response(GTK_DIALOG(main_dialog), GTK_RESPONSE_OK); + gtk_window_set_focus(GTK_WINDOW(main_dialog), button[0]); + mainVbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(main_dialog))), mainVbox, TRUE, TRUE, 2); + + BAhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(mainVbox), BAhbox, FALSE, FALSE, 2); + usbdlg_create_label(BAhbox, "UHCI at Base IO address", false); + ro_entry[0] = usbdlg_create_ro_entry(BAhbox, false); + + hbox[0] = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(mainVbox), hbox[0], TRUE, TRUE, 2); + hbox[1] = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(mainVbox), hbox[1], TRUE, TRUE, 2); + for (i = 0; i < 3; i++) { + vbox[i] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(hbox[0]), vbox[i], TRUE, TRUE, 2); + } + + ORframe = gtk_frame_new("Operational Registers"); + gtk_box_pack_start(GTK_BOX(vbox[0]), ORframe, FALSE, FALSE, 2); + ORhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_container_add(GTK_CONTAINER(ORframe), ORhbox); + for (i = 0; i < 3; i++) { + ORvbox[i] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(ORhbox), ORvbox[i], FALSE, FALSE, 2); + } + uhci_entry[UHCI_REG_COMMAND] = usbdlg_create_entry_with_label(ORvbox, "Command"); + button[2] = gtk_button_new_with_label("<>"); + uhci_reg_def[0].entry = uhci_entry[UHCI_REG_COMMAND]; + g_signal_connect(button[2], "clicked", G_CALLBACK(usb_regview_dialog), &uhci_reg_def[0]); + gtk_box_pack_start(GTK_BOX(ORvbox[2]), button[2], FALSE, FALSE, 2); + uhci_entry[UHCI_REG_STATUS] = usbdlg_create_entry_with_label(ORvbox, "Status"); + button[3] = gtk_button_new_with_label("<>"); + uhci_reg_def[1].entry = uhci_entry[UHCI_REG_STATUS]; + g_signal_connect(button[3], "clicked", G_CALLBACK(usb_regview_dialog), &uhci_reg_def[1]); + gtk_box_pack_start(GTK_BOX(ORvbox[2]), button[3], FALSE, FALSE, 2); + uhci_entry[UHCI_REG_INTERRUPT] = usbdlg_create_entry_with_label(ORvbox, "Interrupt Enable"); + button[4] = gtk_button_new_with_label("<>"); + uhci_reg_def[2].entry = uhci_entry[UHCI_REG_INTERRUPT]; + g_signal_connect(button[4], "clicked", G_CALLBACK(usb_regview_dialog), &uhci_reg_def[2]); + gtk_box_pack_start(GTK_BOX(ORvbox[2]), button[4], FALSE, FALSE, 2); + uhci_entry[UHCI_REG_FRAME_NUM] = usbdlg_create_entry_with_label(ORvbox, "Frame Number"); + uhci_entry[UHCI_REG_FRAME_ADDR] = usbdlg_create_entry_with_label(ORvbox, "Frame Address"); + uhci_entry[UHCI_REG_SOF] = usbdlg_create_entry_with_label(ORvbox, "Start of Frame"); + + PRframe = gtk_frame_new("Port Registers"); + gtk_box_pack_start(GTK_BOX(hbox[1]), PRframe, FALSE, FALSE, 2); + PRhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_container_add(GTK_CONTAINER(PRframe), PRhbox); + for (i = 0; i < 3; i++) { + PRvbox[i] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(PRhbox), PRvbox[i], FALSE, FALSE, 2); + } + for (i = 0; i < 2; i++) { + sprintf(buffer, "Port %d", i); + uhci_entry[UHCI_REG_PORT0 + i] = usbdlg_create_entry_with_label(PRvbox, buffer); + ro_entry[i + 1] = usbdlg_create_ro_entry_with_label(PRvbox, "Emulation Type"); + button[i + 5] = gtk_button_new_with_label("<>"); + uhci_reg_def[i + 3].entry = uhci_entry[UHCI_REG_PORT0 + i]; + g_signal_connect(button[i + 5], "clicked", G_CALLBACK(usb_regview_dialog), &uhci_reg_def[i + 3]); + gtk_box_pack_start(GTK_BOX(PRvbox[2]), button[i + 5], FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(PRvbox[2]), gtk_label_new(" "), FALSE, FALSE, 8); // spacer + } + TVvbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(hbox[1]), TVvbox, TRUE, TRUE, 2); + FNhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(TVvbox), FNhbox, FALSE, FALSE, 2); + FNlabel = usbdlg_create_label(FNhbox, "Frame at Address", false); + ro_entry[3] = usbdlg_create_ro_entry(FNhbox, false); + button[7] = gtk_button_new_with_label("View Item"); + gtk_widget_set_sensitive(button[7], 0); + gtk_box_pack_start(GTK_BOX(FNhbox), button[7], FALSE, FALSE, 2); + treeview = gtk_tree_view_new(); + gtk_box_pack_start(GTK_BOX(TVvbox), treeview, TRUE, TRUE, 2); + + usbdlg_create_apply_button(mainVbox); + usbdlg_create_debug_flags(vbox[2]); + // Set values + pci_bar_address = get_pci_bar_addr((bx_shadow_data_c*)SIM->get_param("hub.pci_conf", UHCI_state), 4); + sprintf(buffer, "0x%04X", pci_bar_address); + gtk_entry_set_text(GTK_ENTRY(ro_entry[0]), buffer); + sprintf(buffer, "0x%04X", usb_io_read(pci_bar_address + 0, 2)); + gtk_entry_set_text(GTK_ENTRY(uhci_entry[UHCI_REG_COMMAND]), buffer); + g_signal_connect(GTK_EDITABLE(uhci_entry[UHCI_REG_COMMAND]), "changed", + G_CALLBACK(on_entry_changed), &u_changed[UHCI_REG_COMMAND]); + sprintf(buffer, "0x%04X", usb_io_read(pci_bar_address + 2, 2)); + gtk_entry_set_text(GTK_ENTRY(uhci_entry[UHCI_REG_STATUS]), buffer); + g_signal_connect(GTK_EDITABLE(uhci_entry[UHCI_REG_STATUS]), "changed", + G_CALLBACK(on_entry_changed), &u_changed[UHCI_REG_STATUS]); + sprintf(buffer, "0x%04X", usb_io_read(pci_bar_address + 4, 2)); + gtk_entry_set_text(GTK_ENTRY(uhci_entry[UHCI_REG_INTERRUPT]), buffer); + g_signal_connect(GTK_EDITABLE(uhci_entry[UHCI_REG_INTERRUPT]), "changed", + G_CALLBACK(on_entry_changed), &u_changed[UHCI_REG_INTERRUPT]); + frame_num = usb_io_read(pci_bar_address + 6, 2); + sprintf(buffer, "0x%04X", frame_num); + gtk_entry_set_text(GTK_ENTRY(uhci_entry[UHCI_REG_FRAME_NUM]), buffer); + g_signal_connect(GTK_EDITABLE(uhci_entry[UHCI_REG_FRAME_NUM]), "changed", + G_CALLBACK(on_entry_changed), &u_changed[UHCI_REG_FRAME_NUM]); + frame_addr = usb_io_read(pci_bar_address + 8, 4); + sprintf(buffer, "0x%08X", frame_addr); + gtk_entry_set_text(GTK_ENTRY(uhci_entry[UHCI_REG_FRAME_ADDR]), buffer); + g_signal_connect(GTK_EDITABLE(uhci_entry[UHCI_REG_FRAME_ADDR]), "changed", + G_CALLBACK(on_entry_changed), &u_changed[UHCI_REG_FRAME_ADDR]); + sprintf(buffer, "0x%02X", usb_io_read(pci_bar_address + 12, 1)); + gtk_entry_set_text(GTK_ENTRY(uhci_entry[UHCI_REG_SOF]), buffer); + g_signal_connect(GTK_EDITABLE(uhci_entry[UHCI_REG_SOF]), "changed", + G_CALLBACK(on_entry_changed), &u_changed[UHCI_REG_SOF]); + sprintf(buffer, "0x%04X", usb_io_read(pci_bar_address + 16, 2)); + gtk_entry_set_text(GTK_ENTRY(uhci_entry[UHCI_REG_PORT0]), buffer); + g_signal_connect(GTK_EDITABLE(uhci_entry[UHCI_REG_PORT0]), "changed", + G_CALLBACK(on_entry_changed), &u_changed[UHCI_REG_PORT0]); + SIM->get_param_enum("port1.device", host_param)->dump_param(buffer, COMMON_STR_SIZE, 1); + gtk_entry_set_text(GTK_ENTRY(ro_entry[1]), buffer); + sprintf(buffer, "0x%04X", usb_io_read(pci_bar_address + 18, 2)); + gtk_entry_set_text(GTK_ENTRY(uhci_entry[UHCI_REG_PORT1]), buffer); + g_signal_connect(GTK_EDITABLE(uhci_entry[UHCI_REG_PORT1]), "changed", + G_CALLBACK(on_entry_changed), &u_changed[UHCI_REG_PORT1]); + SIM->get_param_enum("port2.device", host_param)->dump_param(buffer, COMMON_STR_SIZE, 1); + gtk_entry_set_text(GTK_ENTRY(ro_entry[2]), buffer); + + frame_addr += (frame_num * sizeof(Bit32u)); + sprintf(buffer, "0x%08X", frame_addr); + gtk_entry_set_text(GTK_ENTRY(ro_entry[3]), buffer); + + bool valid = 0; + switch (type) { + // The DoTransfer() function was called + case USB_DEBUG_COMMAND: + // The start of a frame timer was triggered + case USB_DEBUG_FRAME: + gtk_label_set_text(GTK_LABEL(FNlabel), "SOF Frame Address"); + if (frame_addr != 0x00000000) { + hc_uhci_do_item(treeview, frame_addr, frame_num); + gtk_widget_set_sensitive(button[7], 1); + valid = 1; + } + break; + + // an event triggered. We ignore these in the uhci + //case USB_DEBUG_EVENT: + // break; + + // first byte (word, dword, qword) of first non-existant port was written to + case USB_DEBUG_NONEXIST: + // port reset (non-root reset) + case USB_DEBUG_RESET: + // enable changed + case USB_DEBUG_ENABLE: + gtk_label_set_text(GTK_LABEL(FNlabel), "None"); + gtk_entry_set_text(GTK_ENTRY(ro_entry[3]), "None"); + break; + } + + if (!valid) { + gtk_widget_set_sensitive(treeview, 0); + usbdlg_create_label(TVvbox, "This trigger does not populate the tree view", false); + } else { + usbdlg_create_label(TVvbox, "Tree view populated", false); + } + // Show dialog + gtk_widget_show_all(main_dialog); + ret = gtk_dialog_run(GTK_DIALOG(main_dialog)); + if (ret == GTK_RESPONSE_OK) { + usbdlg_set_debug_flags(); + } + gtk_widget_destroy(main_dialog); + return ret; +} + +// xHCI main dialog + +int xhci_debug_dialog(int type, int param1) +{ + bx_list_c *xHCI_state = NULL; + int i, n_ports, ret; + Bit32u dword, offset; + Bit64u RingPtr = 0; + char buffer[COMMON_STR_SIZE], tmpbuf[32]; + GtkWidget *mainVbox, *BAhbox, *hbox[2], *vbox[4], *entry[38]; + GtkWidget *CRframe, *CRhbox, *CRvbox[2]; + GtkWidget *ORframe, *ORhbox, *ORvbox[2]; + GtkWidget *RTframe, *RThbox, *RTvbox[2]; + GtkWidget *PRframe, *PRhbox, *PRvbox[3]; + GtkWidget *TVvbox, *FNhbox; + GtkWidget *button[13], *FNlabel, *treeview; + usb_reg_t xhci_reg_def[10] = { + {"Port 0 Register", NULL, 8, attribs_x_ports}, + {"Port 1 Register", NULL, 8, attribs_x_ports}, + {"Port 2 Register", NULL, 8, attribs_x_ports}, + {"Port 3 Register", NULL, 8, attribs_x_ports}, + {"Port 4 Register", NULL, 8, attribs_x_ports}, + {"Port 5 Register", NULL, 8, attribs_x_ports}, + {"Port 6 Register", NULL, 8, attribs_x_ports}, + {"Port 7 Register", NULL, 8, attribs_x_ports}, + {"Port 8 Register", NULL, 8, attribs_x_ports}, + {"Port 9 Register", NULL, 8, attribs_x_ports} + }; + + xHCI_state = (bx_list_c*)SIM->get_param("usb_xhci", SIM->get_bochs_root()); + if (xHCI_state == NULL) + return -1; + + main_dialog = gtk_dialog_new(); + switch (type) { + case USB_DEBUG_COMMAND: + gtk_window_set_title(GTK_WINDOW(main_dialog), "xHCI Debug Dialog: Break Type: Command Ring"); + break; + case USB_DEBUG_EVENT: + gtk_window_set_title(GTK_WINDOW(main_dialog), "xHCI Debug Dialog: Break Type: Event Ring"); + break; + case USB_DEBUG_FRAME: + gtk_window_set_title(GTK_WINDOW(main_dialog), "xHCI Debug Dialog: Break Type: Frame"); + break; + default: + gtk_window_set_title(GTK_WINDOW(main_dialog), "xHCI Debug Dialog"); + } + gtk_window_set_default_size(GTK_WINDOW(main_dialog), 600, 500); + button[0] = gtk_dialog_add_button(GTK_DIALOG(main_dialog), "Continue", GTK_RESPONSE_OK); + button[1] = gtk_dialog_add_button(GTK_DIALOG(main_dialog), "Quit", GTK_RESPONSE_CANCEL); + gtk_dialog_set_default_response(GTK_DIALOG(main_dialog), GTK_RESPONSE_OK); + gtk_window_set_focus(GTK_WINDOW(main_dialog), button[0]); + mainVbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(main_dialog))), mainVbox, TRUE, TRUE, 2); + + BAhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(mainVbox), BAhbox, FALSE, FALSE, 2); + usbdlg_create_label(BAhbox, "xHCI at Base MMIO address", false); + entry[0] = usbdlg_create_ro_entry(BAhbox, false); + + hbox[0] = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(mainVbox), hbox[0], TRUE, TRUE, 2); + hbox[1] = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(mainVbox), hbox[1], TRUE, TRUE, 2); + for (i = 0; i < 4; i++) { + vbox[i] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(hbox[0]), vbox[i], TRUE, TRUE, 2); + } + + CRframe = gtk_frame_new("Capability Registers"); + gtk_box_pack_start(GTK_BOX(vbox[0]), CRframe, FALSE, FALSE, 2); + CRhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_container_add(GTK_CONTAINER(CRframe), CRhbox); + CRvbox[0] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(CRhbox), CRvbox[0], FALSE, FALSE, 2); + CRvbox[1] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(CRhbox), CRvbox[1], FALSE, FALSE, 2); + entry[1] = usbdlg_create_entry_with_label(CRvbox, "Cap Length"); + entry[2] = usbdlg_create_entry_with_label(CRvbox, "HCSParams1"); + entry[3] = usbdlg_create_ro_entry_with_label(CRvbox, "HCSParams2"); + entry[4] = usbdlg_create_entry_with_label(CRvbox, "HCSParams3"); + entry[5] = usbdlg_create_entry_with_label(CRvbox, "HCCParams1"); + entry[6] = usbdlg_create_entry_with_label(CRvbox, "DB Offset"); + entry[7] = usbdlg_create_entry_with_label(CRvbox, "RTS Offset"); + entry[8] = usbdlg_create_entry_with_label(CRvbox, "HCCParams2"); + + ORframe = gtk_frame_new("Operational Registers"); + gtk_box_pack_start(GTK_BOX(vbox[1]), ORframe, FALSE, FALSE, 2); + ORhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_container_add(GTK_CONTAINER(ORframe), ORhbox); + ORvbox[0] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(ORhbox), ORvbox[0], FALSE, FALSE, 2); + ORvbox[1] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(ORhbox), ORvbox[1], FALSE, FALSE, 2); + entry[9] = usbdlg_create_ro_entry_with_label(ORvbox, "Command"); + entry[10] = usbdlg_create_entry_with_label(ORvbox, "Status"); + entry[11] = usbdlg_create_entry_with_label(ORvbox, "Page Size"); + entry[12] = usbdlg_create_entry_with_label(ORvbox, "Device Notification"); + entry[13] = usbdlg_create_entry_with_label(ORvbox, "Command Ring"); + entry[14] = usbdlg_create_entry_with_label(ORvbox, "Device Context Base"); + entry[15] = usbdlg_create_entry_with_label(ORvbox, "Configure"); + + RTframe = gtk_frame_new("Runtime Registers"); + gtk_box_pack_start(GTK_BOX(vbox[2]), RTframe, FALSE, FALSE, 2); + RThbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_container_add(GTK_CONTAINER(RTframe), RThbox); + RTvbox[0] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(RThbox), RTvbox[0], FALSE, FALSE, 2); + RTvbox[1] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(RThbox), RTvbox[1], FALSE, FALSE, 2); + entry[16] = usbdlg_create_entry_with_label(RTvbox, "Microframe Index"); + + PRframe = gtk_frame_new("Port Registers"); + gtk_box_pack_start(GTK_BOX(hbox[1]), PRframe, FALSE, FALSE, 2); + PRhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_container_add(GTK_CONTAINER(PRframe), PRhbox); + for (i = 0; i < 3; i++) { + PRvbox[i] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(PRhbox), PRvbox[i], FALSE, FALSE, 2); + } + n_ports = SIM->get_param_num(BXPN_XHCI_N_PORTS)->get(); + for (i = 0; i < n_ports; i++) { + sprintf(buffer, "Port %d", i); + entry[i * 2 + 17] = usbdlg_create_entry_with_label(PRvbox, buffer); + entry[i * 2 + 18] = usbdlg_create_ro_entry_with_label(PRvbox, "Emulation Type"); + button[i + 2] = gtk_button_new_with_label("<>"); + xhci_reg_def[i].entry = entry[i * 2 + 17]; + g_signal_connect(button[i + 2], "clicked", G_CALLBACK(usb_regview_dialog), &xhci_reg_def[i]); + gtk_box_pack_start(GTK_BOX(PRvbox[2]), button[i + 2], FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(PRvbox[2]), gtk_label_new(" "), FALSE, FALSE, 8); // spacer + } + TVvbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(hbox[1]), TVvbox, TRUE, TRUE, 2); + FNhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(TVvbox), FNhbox, FALSE, FALSE, 2); + FNlabel = usbdlg_create_label(FNhbox, "Ring Address", false); + entry[n_ports * 2 + 17] = usbdlg_create_ro_entry(FNhbox, false); + button[12] = gtk_button_new_with_label("View TRB"); + gtk_widget_set_sensitive(button[12], 0); + gtk_box_pack_start(GTK_BOX(FNhbox), button[12], FALSE, FALSE, 2); + treeview = gtk_tree_view_new(); + gtk_box_pack_start(GTK_BOX(TVvbox), treeview, TRUE, TRUE, 2); + + usbdlg_create_apply_button(mainVbox); + usbdlg_create_debug_flags(vbox[3]); + // Set values + pci_bar_address = get_pci_bar_addr((bx_shadow_data_c*)SIM->get_param("hub.pci_conf", xHCI_state), 0); + sprintf(buffer, "0x%08X", pci_bar_address); + gtk_entry_set_text(GTK_ENTRY(entry[0]), buffer); + for (i = 0; i < 8; i++) { + dword = xhci_read_dword(pci_bar_address + (i * 4)); + sprintf(buffer, "0x%08X", dword); + gtk_entry_set_text(GTK_ENTRY(entry[i + 1]), buffer); + g_signal_connect(GTK_EDITABLE(entry[i + 1]), "changed", G_CALLBACK(on_entry_changed), NULL); + } + offset = xhci_read_dword(pci_bar_address + 0) & 0xFF; + + dword = xhci_read_dword(pci_bar_address + offset + 0x00); + sprintf(buffer, "0x%08X", dword); + gtk_entry_set_text(GTK_ENTRY(entry[9]), buffer); + g_signal_connect(GTK_EDITABLE(entry[9]), "changed", G_CALLBACK(on_entry_changed), NULL); + dword = xhci_read_dword(pci_bar_address + offset + 0x04); + sprintf(buffer, "0x%08X", dword); + gtk_entry_set_text(GTK_ENTRY(entry[10]), buffer); + g_signal_connect(GTK_EDITABLE(entry[10]), "changed", G_CALLBACK(on_entry_changed), NULL); + dword = xhci_read_dword(pci_bar_address + offset + 0x08); + sprintf(buffer, "0x%08X", dword); + gtk_entry_set_text(GTK_ENTRY(entry[11]), buffer); + g_signal_connect(GTK_EDITABLE(entry[11]), "changed", G_CALLBACK(on_entry_changed), NULL); + dword = xhci_read_dword(pci_bar_address + offset + 0x14); + sprintf(buffer, "0x%08X", dword); + gtk_entry_set_text(GTK_ENTRY(entry[12]), buffer); + g_signal_connect(GTK_EDITABLE(entry[12]), "changed", G_CALLBACK(on_entry_changed), NULL); + // we can't read this using DEV_MEM_READ_PHYSICAL since the handler will return zero + sprintf(buffer, "0x" FMT_ADDRX64, SIM->get_param_num("hub.op_regs.HcCrcr.actual", xHCI_state)->get64()); + gtk_entry_set_text(GTK_ENTRY(entry[13]), buffer); + g_signal_connect(GTK_EDITABLE(entry[13]), "changed", G_CALLBACK(on_entry_changed), NULL); + Bit64u qword = xhci_read_dword(pci_bar_address + offset + 0x30) | + ((Bit64u) xhci_read_dword(pci_bar_address + offset + 0x34) << 32); + sprintf(buffer, "0x" FMT_ADDRX64, qword); + gtk_entry_set_text(GTK_ENTRY(entry[14]), buffer); + g_signal_connect(GTK_EDITABLE(entry[14]), "changed", G_CALLBACK(on_entry_changed), NULL); + dword = xhci_read_dword(pci_bar_address + offset + 0x38); + sprintf(buffer, "0x%08X", dword); + gtk_entry_set_text(GTK_ENTRY(entry[15]), buffer); + g_signal_connect(GTK_EDITABLE(entry[15]), "changed", G_CALLBACK(on_entry_changed), NULL); + + offset = xhci_read_dword(pci_bar_address + 0x18); + dword = xhci_read_dword(pci_bar_address + offset + 0); + sprintf(buffer, "0x%08X", dword); + gtk_entry_set_text(GTK_ENTRY(entry[16]), buffer); + g_signal_connect(GTK_EDITABLE(entry[16]), "changed", G_CALLBACK(on_entry_changed), NULL); + // show up to 10 port register sets + for (i = 0; i < n_ports; i++) { + dword = xhci_read_dword(pci_bar_address + XHCI_PORT_SET_OFFSET + (i * 16)); + sprintf(buffer, "0x%08X", dword); + gtk_entry_set_text(GTK_ENTRY(entry[i * 2 + 17]), buffer); + g_signal_connect(GTK_EDITABLE(entry[i * 2 + 17]), "changed", G_CALLBACK(on_entry_changed), NULL); + sprintf(tmpbuf, "port%d.device", i + 1); + SIM->get_param_enum(tmpbuf, host_param)->dump_param(buffer, COMMON_STR_SIZE, 1); + gtk_entry_set_text(GTK_ENTRY(entry[i * 2 + 18]), buffer); + } + + bool valid = 0; + switch (type) { + // a command TRB was placed on the command ring + case USB_DEBUG_COMMAND: + gtk_label_set_text(GTK_LABEL(FNlabel), "Command Ring Address"); + RingPtr = SIM->get_param_num("hub.op_regs.HcCrcr.crc", xHCI_state)->get(); + sprintf(buffer, "0x" FMT_ADDRX64, RingPtr); + gtk_entry_set_text(GTK_ENTRY(entry[n_ports * 2 + 17]), buffer); + if (RingPtr != 0) { + gtk_widget_set_sensitive(button[12], 1); + valid = 1; + } + break; + + // an event TRB was placed on an event ring + case USB_DEBUG_EVENT: + gtk_label_set_text(GTK_LABEL(FNlabel), "Event Ring"); + sprintf(buffer, "Interrupter %i", param1); + gtk_entry_set_text(GTK_ENTRY(entry[n_ports * 2 + 17]), buffer); + gtk_widget_set_sensitive(button[12], 1); + valid = 1; + break; + + case USB_DEBUG_FRAME: + + gtk_label_set_text(GTK_LABEL(FNlabel), "SOF Frame Address"); + + break; + + // first byte (word, dword, qword) of first non-existant port was written to + case USB_DEBUG_NONEXIST: + // port reset (non-root reset) + case USB_DEBUG_RESET: + // enable changed + case USB_DEBUG_ENABLE: + gtk_label_set_text(GTK_LABEL(FNlabel), "None"); + gtk_entry_set_text(GTK_ENTRY(entry[n_ports * 2 + 17]), "None"); + break; + } + + if (!valid) { + gtk_widget_set_sensitive(treeview, 0); + usbdlg_create_label(TVvbox, "This trigger does not populate the tree view", false); + } else { + usbdlg_create_label(TVvbox, "Tree view populated", false); + } + // Show dialog + gtk_widget_show_all(main_dialog); + ret = gtk_dialog_run(GTK_DIALOG(main_dialog)); + if (ret == GTK_RESPONSE_OK) { + usbdlg_set_debug_flags(); + } + gtk_widget_destroy(main_dialog); + return ret; +} + +// USB debug dialog entry point + +int usb_debug_dialog(int type, int param1, int param2) +{ + static bool first_call = true; + int argc = 1, ret; + char *argv[2], **argvp, buffer[COMMON_STR_SIZE]; + + if (first_call) { + if (!SIM->is_wx_selected() && !SIM->has_debug_gui()) { + // you MUST call gtk_init, even with faked arguments, because it inits GDK and Glib + *buffer = 0; // gtk flames out if you pass in a NULL -- sheesh + argv[0] = buffer; // so I really do have to fake up an "argv" list + argv[1] = NULL; + argvp = argv; + if (gtk_init_check(&argc, &argvp) == false) { + fprintf(stderr, "gtk init failed, can not access display?\n"); + return -1; + } + MakeGTKthreads(); + } + first_call = false; + } + host_param = SIM->get_param(hc_param_str[usb_debug_type]); + if (usb_debug_type == USB_DEBUG_UHCI) { + ret = uhci_debug_dialog(type, param1); + return (ret == GTK_RESPONSE_OK) ? 0 : -1; + } else if (usb_debug_type == USB_DEBUG_XHCI) { + ret = xhci_debug_dialog(type, param1); + return (ret == GTK_RESPONSE_OK) ? 0 : -1; + } else { + GtkWidget* error = gtk_message_dialog_new( + NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, + "GTK version of USB debugger dialog not implemented yet"); + gtk_window_set_title(GTK_WINDOW(error), "WARNING"); + ret = gtk_dialog_run(GTK_DIALOG(error)); + gtk_widget_destroy(error); + return (ret == GTK_RESPONSE_OK) ? 0 : -1; + } +} + +#endif diff --git a/bochs/gui/gui.cc b/bochs/gui/gui.cc index eccb89a446..81dd1cb6ed 100644 --- a/bochs/gui/gui.cc +++ b/bochs/gui/gui.cc @@ -32,8 +32,8 @@ #include "gui/bitmaps/copy.h" #include "gui/bitmaps/paste.h" #include "gui/bitmaps/configbutton.h" -#include "gui/bitmaps/cdromd.h" -#if BX_USE_WIN32USBDEBUG +#include "gui/bitmaps/cdrom1.h" +#if BX_USB_DEBUGGER #include "gui/bitmaps/usb.h" #endif #include "gui/bitmaps/userbutton.h" @@ -155,6 +155,7 @@ bx_gui_c::bx_gui_c(void): disp_mode(DISP_MODE_SIM) memset(palette, 0, sizeof(palette)); memset(vga_charmap[0], 0, 0x2000); memset(vga_charmap[1], 0, 0x2000); + memset(&gui_opts, 0, sizeof(gui_opts)); } bx_gui_c::~bx_gui_c() @@ -216,10 +217,10 @@ void bx_gui_c::init(int argc, char **argv, unsigned max_xres, unsigned max_yres, BX_FLOPPYB_BMAP_X, BX_FLOPPYB_BMAP_Y); BX_GUI_THIS floppyB_eject_bmap_id = create_bitmap(bx_floppyb_eject_bmap, BX_FLOPPYB_BMAP_X, BX_FLOPPYB_BMAP_Y); - BX_GUI_THIS cdrom1_bmap_id = create_bitmap(bx_cdromd_bmap, - BX_CDROMD_BMAP_X, BX_CDROMD_BMAP_Y); - BX_GUI_THIS cdrom1_eject_bmap_id = create_bitmap(bx_cdromd_eject_bmap, - BX_CDROMD_BMAP_X, BX_CDROMD_BMAP_Y); + BX_GUI_THIS cdrom1_bmap_id = create_bitmap(bx_cdrom1_bmap, + BX_CDROM1_BMAP_X, BX_CDROM1_BMAP_Y); + BX_GUI_THIS cdrom1_eject_bmap_id = create_bitmap(bx_cdrom1_eject_bmap, + BX_CDROM1_BMAP_X, BX_CDROM1_BMAP_Y); BX_GUI_THIS mouse_bmap_id = create_bitmap(bx_mouse_bmap, BX_MOUSE_BMAP_X, BX_MOUSE_BMAP_Y); BX_GUI_THIS nomouse_bmap_id = create_bitmap(bx_nomouse_bmap, @@ -235,12 +236,12 @@ void bx_gui_c::init(int argc, char **argv, unsigned max_xres, unsigned max_yres, BX_GUI_THIS save_restore_bmap_id = create_bitmap(bx_save_restore_bmap, BX_SAVE_RESTORE_BMAP_X, BX_SAVE_RESTORE_BMAP_Y); -#if BX_USE_WIN32USBDEBUG - BX_GUI_THIS usb_bmap_id = create_bitmap(bx_usb_bmap, +#if BX_USB_DEBUGGER + BX_GUI_THIS usbdbg_bmap_id = create_bitmap(bx_usbdbg_bmap, BX_USB_BMAP_X, BX_USB_BMAP_Y); - BX_GUI_THIS usb_eject_bmap_id = create_bitmap(bx_usb_eject_bmap, + BX_GUI_THIS usbdbg_dis_bmap_id = create_bitmap(bx_usbdbg_dis_bmap, BX_USB_BMAP_X, BX_USB_BMAP_Y); - BX_GUI_THIS usb_trigger_bmap_id = create_bitmap(bx_usb_trigger_bmap, + BX_GUI_THIS usbdbg_trigger_bmap_id = create_bitmap(bx_usbdbg_trigger_bmap, BX_USB_BMAP_X, BX_USB_BMAP_Y); #endif @@ -272,22 +273,12 @@ void bx_gui_c::init(int argc, char **argv, unsigned max_xres, unsigned max_yres, BX_GRAVITY_LEFT, toggle_mouse_enable); BX_GUI_THIS set_tooltip(BX_GUI_THIS mouse_hbar_id, "Enable mouse capture"); -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER // USB button if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_USB) { - if ((SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get() > 0) && ( - SIM->get_param_bool(BXPN_UHCI_ENABLED)->get() || - SIM->get_param_bool(BXPN_OHCI_ENABLED)->get() || - SIM->get_param_bool(BXPN_EHCI_ENABLED)->get() || - SIM->get_param_bool(BXPN_XHCI_ENABLED)->get())) { - BX_GUI_THIS usb_hbar_id = headerbar_bitmap(BX_GUI_THIS usb_bmap_id, - BX_GRAVITY_LEFT, usb_handler); - BX_GUI_THIS set_tooltip(BX_GUI_THIS usb_hbar_id, "Trigger the USB Debugger"); - } else { - BX_GUI_THIS usb_hbar_id = headerbar_bitmap(BX_GUI_THIS usb_eject_bmap_id, - BX_GRAVITY_LEFT, usb_handler); - BX_GUI_THIS set_tooltip(BX_GUI_THIS usb_hbar_id, "USB support not enabled"); - } + BX_GUI_THIS usbdbg_hbar_id = headerbar_bitmap(BX_GUI_THIS usbdbg_dis_bmap_id, + BX_GRAVITY_LEFT, usb_handler); + BX_GUI_THIS set_tooltip(BX_GUI_THIS usbdbg_hbar_id, "USB debugger support not enabled"); } #endif @@ -713,16 +704,21 @@ void bx_gui_c::config_handler(void) } } -#if BX_USE_WIN32USBDEBUG -#include "win32usb.h" +#if BX_USB_DEBUGGER void bx_gui_c::usb_handler(void) { if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_USB) { // Once we set the trigger, don't allow the user to press the button again if (SIM->get_param_num(BXPN_USB_DEBUG_START_FRAME)->get() < BX_USB_DEBUG_SOF_TRIGGER) - SIM->usb_config_interface(USB_DEBUG_FRAME, 0, 0); + SIM->usb_debug_interface(USB_DEBUG_FRAME, 0, 0); } } + +void bx_gui_c::set_usbdbg_bitmap(bool trigger) +{ + set_tooltip(BX_GUI_THIS usbdbg_hbar_id, "Trigger the USB debugger"); + replace_bitmap(usbdbg_hbar_id, trigger ? usbdbg_trigger_bmap_id : usbdbg_bmap_id); +} #endif void bx_gui_c::toggle_mouse_enable(void) @@ -1080,10 +1076,10 @@ Bit8u bx_gui_c::get_mouse_headerbar_id() } #if BX_DEBUGGER && BX_DEBUGGER_GUI -void bx_gui_c::init_debug_dialog() +void bx_gui_c::init_debug_dialog(bool global_ini) { - extern void InitDebugDialog(); - InitDebugDialog(); + extern void InitDebugDialog(bool GlobalIni); + InitDebugDialog(global_ini); } void bx_gui_c::close_debug_dialog() @@ -1260,8 +1256,8 @@ void bx_gui_c::text_update_common(Bit8u *old_text, Bit8u *new_text, if (blink_mode) { if (tm_info->blink_flags & BX_TEXT_BLINK_TOGGLE) forceUpdate = 1; - if (!blink_state) cursor_visible = 0; } + if (!blink_state) cursor_visible = 0; if (BX_GUI_THIS charmap_updated) { BX_GUI_THIS set_font(tm_info->line_graphics); BX_GUI_THIS charmap_updated = 0; @@ -1577,7 +1573,7 @@ int bx_gui_c::bx_printf(const char *s) } console.cursor_addr = console.cursor_y * 160 + console.cursor_x * 2; console_refresh(0); - return strlen(s); + return (int)strlen(s); } char* bx_gui_c::bx_gets(char *s, int size) @@ -1636,3 +1632,47 @@ void bx_gui_c::set_command_mode(bool active) command_mode.active = active; } } + +bool bx_gui_c::parse_common_gui_options(const char *arg, Bit8u flags) +{ + if (!strcmp(arg, "nokeyrepeat") && (flags & BX_GUI_OPT_NOKEYREPEAT)) { + BX_INFO(("disabled host keyboard repeat")); + gui_opts.nokeyrepeat = 1; + return true; + } else if (!strncmp(arg, "gui_debug", 9)) { +#if BX_DEBUGGER && BX_DEBUGGER_GUI + gui_opts.enh_dbg_enabled = 1; + gui_opts.enh_dbg_global_ini = 0; + if ((strlen(arg) > 9) && (arg[9] == ':')) { + if (!strcmp(&arg[10], "globalini")) { + gui_opts.enh_dbg_global_ini = 1; + BX_INFO(("Debugger gui using global config from BXSHARE path")); + } else { + BX_ERROR(("Ignoring unknown setting '%s' for gui debugger", &arg[10])); + } + } else if (strlen(arg) > 9) { + return false; + } +#else + SIM->message_box("ERROR", "Bochs debugger not available - ignoring 'gui_debug' option"); +#endif + return true; +#if BX_SHOW_IPS + } else if (!strcmp(arg, "hideIPS") && (flags & BX_GUI_OPT_HIDE_IPS)) { + BX_INFO(("hide IPS display in status bar")); + gui_opts.hide_ips = 1; + return true; +#endif + } else if (!strcmp(arg, "cmdmode") && (flags & BX_GUI_OPT_CMDMODE)) { + BX_INFO(("enabled command mode support")); + command_mode.present = 1; + return true; +#if BX_USE_GUI_CONSOLE + } else if (!strcmp(arg, "no_gui_console") && (flags & BX_GUI_OPT_NO_GUI_CONSOLE)) { + BX_INFO(("use system console instead of gui console")); + console.present = 0; + return true; +#endif + } + return false; +} diff --git a/bochs/gui/gui.h b/bochs/gui/gui.h index 3c6a85688e..6b13215305 100644 --- a/bochs/gui/gui.h +++ b/bochs/gui/gui.h @@ -26,7 +26,7 @@ // header bar and status bar stuff #define BX_HEADER_BAR_Y 32 -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER #define BX_MAX_PIXMAPS 19 #define BX_MAX_HEADERBAR_ENTRIES 13 #else @@ -47,7 +47,7 @@ #define BX_GUI_DLG_RUNTIME 0x08 #define BX_GUI_DLG_USER 0x10 #define BX_GUI_DLG_SAVE_RESTORE 0x20 -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER #define BX_GUI_DLG_USB 0x40 #define BX_GUI_DLG_ALL 0x7F #else @@ -80,12 +80,11 @@ #define BX_GUI_MT_F12 (BX_MT_KEY_F12) #define BX_GUI_MT_CTRL_ALT (BX_MT_KEY_CTRL | BX_MT_KEY_ALT) -// usb_debug items -#if BX_USE_WIN32USBDEBUG - #define BX_USB_DEBUG_SOF_NONE 0 - #define BX_USB_DEBUG_SOF_SET 1 - #define BX_USB_DEBUG_SOF_TRIGGER 2 -#endif +// display library option flags +#define BX_GUI_OPT_HIDE_IPS 0x01 +#define BX_GUI_OPT_NOKEYREPEAT 0x02 +#define BX_GUI_OPT_CMDMODE 0x04 +#define BX_GUI_OPT_NO_GUI_CONSOLE 0x08 typedef struct { Bit16u start_address; @@ -115,9 +114,9 @@ BOCHSAPI_MSVCONLY Bit8u reverse_bitorder(Bit8u); BOCHSAPI extern class bx_gui_c *bx_gui; #if BX_SUPPORT_X86_64 - #define BOCHS_WINDOW_NAME "Bochs x86-64 emulator, http://bochs.sourceforge.net/" + #define BOCHS_WINDOW_NAME "Bochs x86-64 emulator, https://bochs.sourceforge.io/" #else - #define BOCHS_WINDOW_NAME "Bochs x86 emulator, http://bochs.sourceforge.net/" + #define BOCHS_WINDOW_NAME "Bochs x86 emulator, https://bochs.sourceforge.io/" #endif // The bx_gui_c class provides data and behavior that is common to @@ -217,7 +216,7 @@ class BOCHSAPI bx_gui_c : public logfunctions { Bit8u set_modifier_keys(Bit8u modifier, bool pressed); bool parse_user_shortcut(const char *val); #if BX_DEBUGGER && BX_DEBUGGER_GUI - void init_debug_dialog(void); + void init_debug_dialog(bool global_ini); void close_debug_dialog(void); #endif #if BX_USE_GUI_CONSOLE @@ -239,6 +238,9 @@ class BOCHSAPI bx_gui_c : public logfunctions { void set_fullscreen_mode(bool active) {fullscreen_mode = active;} // marklog handler without button, called in gui command mode static void marklog_handler(void); +#if BX_USB_DEBUGGER + void set_usbdbg_bitmap(bool trigger); +#endif protected: // And these are defined and used privately in gui.cc @@ -252,7 +254,7 @@ class BOCHSAPI bx_gui_c : public logfunctions { static void paste_handler(void); static void snapshot_handler(void); static void config_handler(void); -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER static void usb_handler(void); #endif static void userbutton_handler(void); @@ -271,6 +273,7 @@ class BOCHSAPI bx_gui_c : public logfunctions { #else void console_cleanup(void) {} #endif + bool parse_common_gui_options(const char *arg, Bit8u flags); // header bar buttons bool floppyA_status; @@ -288,11 +291,8 @@ class BOCHSAPI bx_gui_c : public logfunctions { unsigned mouse_bmap_id, nomouse_bmap_id, mouse_hbar_id; unsigned user_bmap_id, user_hbar_id; unsigned save_restore_bmap_id, save_restore_hbar_id; -#if BX_USE_WIN32USBDEBUG - // TODO: this is a lousy hack. we need to keep these protected.... -public: - unsigned usb_bmap_id, usb_eject_bmap_id, usb_trigger_bmap_id, usb_hbar_id; -protected: +#if BX_USB_DEBUGGER + unsigned usbdbg_bmap_id, usbdbg_dis_bmap_id, usbdbg_trigger_bmap_id, usbdbg_hbar_id; #endif // the "classic" Bochs headerbar unsigned bx_headerbar_entries; @@ -393,6 +393,17 @@ class BOCHSAPI bx_gui_c : public logfunctions { } command_mode; bool fullscreen_mode; Bit32u marker_count; + // display library options + struct { +#if BX_SHOW_IPS + bool hide_ips; +#endif + bool nokeyrepeat; +#if BX_DEBUGGER && BX_DEBUGGER_GUI + bool enh_dbg_enabled; + bool enh_dbg_global_ini; +#endif + } gui_opts; }; diff --git a/bochs/gui/sdl.cc b/bochs/gui/sdl.cc index 824b4eaee5..0bd7a0a9c9 100644 --- a/bochs/gui/sdl.cc +++ b/bochs/gui/sdl.cc @@ -110,11 +110,13 @@ static unsigned statusitem_pos[12] = { }; static bool statusitem_active[12]; #if BX_SHOW_IPS -static bool sdl_hide_ips = 0; static bool sdl_ips_update = 0; static char sdl_ips_text[20]; static bool sdl_show_info_msg = 0; #endif +#if defined(WIN32) && BX_DEBUGGER && BX_DEBUGGER_GUI +bool sdl_enh_dbg_global_ini; +#endif static void sdl_set_status_text(int element, const char *text, bool active, bool color = 0) @@ -187,7 +189,13 @@ static Bit32u sdl_sym_to_bx_key(SDLKey sym) case SDLK_BACKSPACE: return BX_KEY_BACKSPACE; case SDLK_TAB: return BX_KEY_TAB; case SDLK_RETURN: return BX_KEY_ENTER; - case SDLK_PAUSE: return BX_KEY_PAUSE; + case SDLK_PAUSE: + if (bx_gui->get_modifier_keys() & BX_MOD_KEY_CTRL) { + return BX_KEY_CTRL_BREAK; + } else { + return BX_KEY_PAUSE; + } + break; case SDLK_ESCAPE: return BX_KEY_ESC; case SDLK_SPACE: return BX_KEY_SPACE; case SDLK_QUOTE: return BX_KEY_SINGLE_QUOTE; @@ -303,7 +311,7 @@ static Bit32u sdl_sym_to_bx_key(SDLKey sym) /* Miscellaneous function keys */ case SDLK_PRINT: return BX_KEY_PRINT; - case SDLK_BREAK: return BX_KEY_PAUSE; + case SDLK_BREAK: return BX_KEY_CTRL_BREAK; case SDLK_MENU: return BX_KEY_MENU; default: @@ -333,14 +341,14 @@ void switch_to_fullscreen(void) { SDL_FreeSurface(sdl_screen); sdl_screen = NULL; -#ifdef ANDROID +#ifdef __ANDROID__ sdl_fullscreen = SDL_SetVideoMode(res_x,res_y,32, SDL_SWSURFACE|SDL_FULLSCREEN); #else sdl_fullscreen = SDL_SetVideoMode(res_x,res_y,32, SDL_HWSURFACE|SDL_FULLSCREEN); #endif DEV_vga_refresh(1); SDL_ShowCursor(0); -#ifndef ANDROID +#ifndef __ANDROID__ if (sdl_grab == 0) { SDL_WM_GrabInput(SDL_GRAB_ON); sdl_grab = 1; @@ -375,7 +383,7 @@ DWORD WINAPI DebugGuiThread(LPVOID) { MSG msg; - bx_gui->init_debug_dialog(); + bx_gui->init_debug_dialog(sdl_enh_dbg_global_ini); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -416,7 +424,7 @@ bx_sdl_gui_c::bx_sdl_gui_c() atexit(SDL_Quit); #endif -#ifdef ANDROID +#ifdef __ANDROID__ modes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_SWSURFACE); #else modes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); @@ -475,46 +483,43 @@ void bx_sdl_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) } // parse sdl specific options + Bit8u flags = BX_GUI_OPT_NOKEYREPEAT | BX_GUI_OPT_HIDE_IPS | BX_GUI_OPT_CMDMODE + | BX_GUI_OPT_NO_GUI_CONSOLE; if (argc > 1) { for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "fullscreen")) { - sdl_fullscreen_toggle = 1; - switch_to_fullscreen(); - } else if (!strcmp(argv[i], "nokeyrepeat")) { - BX_INFO(("disabled host keyboard repeat")); - SDL_EnableKeyRepeat(0, 0); - } else if (!strcmp(argv[i], "gui_debug")) { -#if BX_DEBUGGER && BX_DEBUGGER_GUI - SIM->set_debug_gui(1); -#ifdef WIN32 - if (gui_ci) { - // on Windows the debugger gui must run in a separate thread - DWORD threadID; - CreateThread(NULL, 0, DebugGuiThread, NULL, 0, &threadID); + if (!parse_common_gui_options(argv[i], flags)) { + if (!strcmp(argv[i], "fullscreen")) { + sdl_fullscreen_toggle = 1; + switch_to_fullscreen(); } else { - BX_PANIC(("Config interface 'win32config' is required for gui debugger")); + BX_PANIC(("Unknown sdl option '%s'", argv[i])); } -#else - init_debug_dialog(); -#endif -#else - SIM->message_box("ERROR", "Bochs debugger not available - ignoring 'gui_debug' option"); -#endif -#if BX_SHOW_IPS - } else if (!strcmp(argv[i], "hideIPS")) { - BX_INFO(("hide IPS display in status bar")); - sdl_hide_ips = 1; -#endif - } else if (!strcmp(argv[i], "cmdmode")) { - command_mode.present = 1; - } else if (!strcmp(argv[i], "no_gui_console")) { - console.present = 0; - } else { - BX_PANIC(("Unknown sdl option '%s'", argv[i])); } } } + if (gui_opts.nokeyrepeat) { + SDL_EnableKeyRepeat(0, 0); + } + +#if BX_DEBUGGER && BX_DEBUGGER_GUI + if (gui_opts.enh_dbg_enabled) { + SIM->set_debug_gui(1); +#ifdef WIN32 + if (gui_ci) { + sdl_enh_dbg_global_ini = gui_opts.enh_dbg_global_ini; + // on Windows the debugger gui must run in a separate thread + DWORD threadID; + CreateThread(NULL, 0, DebugGuiThread, NULL, 0, &threadID); + } else { + BX_PANIC(("Config interface 'win32config' is required for gui debugger")); + } +#else + init_debug_dialog(gui_opts.enh_dbg_global_ini); +#endif + } +#endif + new_gfx_api = 1; new_text_api = 1; #if defined(WIN32) && BX_SHOW_IPS @@ -901,10 +906,8 @@ void bx_sdl_gui_c::handle_events(void) mouse_toggle_check(BX_MT_KEY_F12, 0); } - // filter out release of Windows/Fullscreen toggle and unsupported keys - if ((sdl_event.key.keysym.sym != SDLK_SCROLLOCK) - && (sdl_event.key.keysym.sym < SDLK_LAST)) - { + // filter out release of unsupported keys + if (sdl_event.key.keysym.sym < SDLK_LAST) { // convert sym->bochs code if (!SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) { key_event = sdl_sym_to_bx_key(sdl_event.key.keysym.sym); @@ -1007,7 +1010,7 @@ void bx_sdl_gui_c::dimension_update(unsigned x, unsigned y, guest_yres = y; if ((x == res_x) && (y == res_y)) return; -#ifndef ANDROID +#ifndef __ANDROID__ // This is not needed on Android if (((int)x > sdl_maxres.w) || ((int)y > sdl_maxres.h)) { BX_PANIC(("dimension_update(): resolution of out of display bounds")); @@ -1041,7 +1044,7 @@ void bx_sdl_gui_c::dimension_update(unsigned x, unsigned y, BX_HEADERBAR_BG_GREEN, BX_HEADERBAR_BG_BLUE); } else { -#ifdef ANDROID +#ifdef __ANDROID__ sdl_fullscreen = SDL_SetVideoMode(x, y, 32, SDL_SWSURFACE|SDL_FULLSCREEN); #else sdl_fullscreen = SDL_SetVideoMode(x, y, 32, SDL_HWSURFACE|SDL_FULLSCREEN); @@ -1432,7 +1435,7 @@ void bx_sdl_gui_c::set_mouse_mode_absxy(bool mode) #if BX_SHOW_IPS void bx_sdl_gui_c::show_ips(Bit32u ips_count) { - if (!sdl_hide_ips && !sdl_ips_update) { + if (!gui_opts.hide_ips && !sdl_ips_update) { ips_count /= 1000; sprintf(sdl_ips_text, "IPS: %u.%3.3uM", ips_count / 1000, ips_count % 1000); sdl_ips_update = 1; diff --git a/bochs/gui/sdl2.cc b/bochs/gui/sdl2.cc index a2fbcaead9..f9fc100bba 100644 --- a/bochs/gui/sdl2.cc +++ b/bochs/gui/sdl2.cc @@ -105,7 +105,6 @@ int old_mousex=0, new_mousex=0; int old_mousey=0, new_mousey=0; bool just_warped = 0; bool sdl_mouse_mode_absxy = 0; -bool sdl_nokeyrepeat = 0; bitmaps *sdl_bitmaps[MAX_SDL_BITMAPS]; int n_sdl_bitmaps = 0; int statusbar_height = 18; @@ -115,7 +114,6 @@ static unsigned statusitem_pos[12] = { static bool statusitem_active[12]; #if BX_SHOW_IPS SDL_TimerID timer_id; -static bool sdl_hide_ips = 0; static bool sdl_ips_update = 0; static char sdl_ips_text[20]; static bool sdl_show_info_msg = 0; @@ -125,6 +123,9 @@ BxEvent *sdl2_notify_callback(void *unused, BxEvent *event); static bxevent_handler old_callback = NULL; static void *old_callback_arg = NULL; #endif +#if defined(WIN32) && BX_DEBUGGER && BX_DEBUGGER_GUI +bool sdl2_enh_dbg_global_ini; +#endif static void sdl_set_status_text(int element, const char *text, bool active, Bit8u color = 0) @@ -345,7 +346,6 @@ void switch_to_fullscreen(void) bx_gui->toggle_mouse_enable(); } SDL_GetWindowPosition(window, &saved_x, &saved_y); - SDL_SetWindowSize(window, res_x, res_y); SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); sdl_fullscreen = SDL_GetWindowSurface(window); sdl_screen = NULL; @@ -379,7 +379,7 @@ DWORD WINAPI DebugGuiThread(LPVOID) { MSG msg; - bx_gui->init_debug_dialog(); + bx_gui->init_debug_dialog(sdl2_enh_dbg_global_ini); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -472,47 +472,40 @@ void bx_sdl2_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) console.present = 1; } - // parse sdl specific options + // parse sdl2 specific options + Bit8u flags = BX_GUI_OPT_NOKEYREPEAT | BX_GUI_OPT_HIDE_IPS | BX_GUI_OPT_CMDMODE + | BX_GUI_OPT_NO_GUI_CONSOLE; if (argc > 1) { for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "fullscreen")) { - sdl_fullscreen_toggle = 1; - switch_to_fullscreen(); - } else if (!strcmp(argv[i], "nokeyrepeat")) { - BX_INFO(("disabled host keyboard repeat")); - sdl_nokeyrepeat = 1; - } else if (!strcmp(argv[i], "gui_debug")) { -#if BX_DEBUGGER && BX_DEBUGGER_GUI - SIM->set_debug_gui(1); -#ifdef WIN32 - if (gui_ci) { - // on Windows the debugger gui must run in a separate thread - DWORD threadID; - CreateThread(NULL, 0, DebugGuiThread, NULL, 0, &threadID); + if (!parse_common_gui_options(argv[i], flags)) { + if (!strcmp(argv[i], "fullscreen")) { + sdl_fullscreen_toggle = 1; + switch_to_fullscreen(); } else { - BX_PANIC(("Config interface 'win32config' is required for gui debugger")); + BX_PANIC(("Unknown sdl2 option '%s'", argv[i])); } -#else - init_debug_dialog(); -#endif -#else - SIM->message_box("ERROR", "Bochs debugger not available - ignoring 'gui_debug' option"); -#endif -#if BX_SHOW_IPS - } else if (!strcmp(argv[i], "hideIPS")) { - BX_INFO(("hide IPS display in status bar")); - sdl_hide_ips = 1; -#endif - } else if (!strcmp(argv[i], "cmdmode")) { - command_mode.present = 1; - } else if (!strcmp(argv[i], "no_gui_console")) { - console.present = 0; - } else { - BX_PANIC(("Unknown sdl2 option '%s'", argv[i])); } } } +#if BX_DEBUGGER && BX_DEBUGGER_GUI + if (gui_opts.enh_dbg_enabled) { + SIM->set_debug_gui(1); +#ifdef WIN32 + if (gui_ci) { + sdl2_enh_dbg_global_ini = gui_opts.enh_dbg_global_ini; + // on Windows the debugger gui must run in a separate thread + DWORD threadID; + CreateThread(NULL, 0, DebugGuiThread, NULL, 0, &threadID); + } else { + BX_PANIC(("Config interface 'win32config' is required for gui debugger")); + } +#else + init_debug_dialog(gui_opts.enh_dbg_global_ini); +#endif + } +#endif + new_gfx_api = 1; new_text_api = 1; #if defined(WIN32) && BX_SHOW_IPS @@ -520,6 +513,10 @@ void bx_sdl2_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) #endif if (gui_ci) { dialog_caps = BX_GUI_DLG_ALL; +#if BX_USB_DEBUGGER + } else { + dialog_caps |= BX_GUI_DLG_USB; +#endif } sdl_init_done = 1; } @@ -636,8 +633,7 @@ void bx_sdl2_gui_c::handle_events(void) case SDL_WINDOWEVENT: if (sdl_event.window.event == SDL_WINDOWEVENT_EXPOSED) { SDL_UpdateWindowSurface(window); - } - if (sdl_event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) { + } else if (sdl_event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) { DEV_kbd_release_keys(); } break; @@ -849,7 +845,7 @@ void bx_sdl2_gui_c::handle_events(void) break; } - if (sdl_nokeyrepeat && sdl_event.key.repeat) { + if (gui_opts.nokeyrepeat && sdl_event.key.repeat) { break; } // convert sym->bochs code @@ -993,7 +989,7 @@ void bx_sdl2_gui_c::dimension_update(unsigned x, unsigned y, if ((x == res_x) && (y == res_y)) return; -#ifndef ANDROID +#ifndef __ANDROID__ // This is not needed on Android if (((int)x > sdl_maxres.w) || ((int)y > sdl_maxres.h)) { BX_PANIC(("dimension_update(): resolution of out of display bounds")); @@ -1382,7 +1378,7 @@ void bx_sdl2_gui_c::set_mouse_mode_absxy(bool mode) #if BX_SHOW_IPS void bx_sdl2_gui_c::show_ips(Bit32u ips_count) { - if (!sdl_hide_ips && !sdl_ips_update) { + if (!gui_opts.hide_ips && !sdl_ips_update) { ips_count /= 1000; sprintf(sdl_ips_text, "IPS: %u.%3.3uM", ips_count / 1000, ips_count % 1000); sdl_ips_update = 1; diff --git a/bochs/gui/siminterface.cc b/bochs/gui/siminterface.cc index d2b3f1ae9d..5590db1f08 100644 --- a/bochs/gui/siminterface.cc +++ b/bochs/gui/siminterface.cc @@ -28,6 +28,9 @@ #include "iodev.h" #include "bx_debug/debug.h" #include "virt_timer.h" +#if BX_USB_DEBUGGER +#include "gui/usb_debug.h" +#endif bx_simulator_interface_c *SIM = NULL; logfunctions *siminterface_log = NULL; @@ -69,9 +72,6 @@ class bx_real_sim_c : public bx_simulator_interface_c { const char *registered_ci_name; config_interface_callback_t ci_callback; void *ci_callback_data; -#if BX_USE_WIN32USBDEBUG - usb_interface_callback_t usbi_callback; -#endif rt_conf_entry_t *rt_conf_entries; addon_option_t *addon_options; bool init_done; @@ -179,9 +179,10 @@ class bx_real_sim_c : public bx_simulator_interface_c { config_interface_callback_t callback, void *userdata); virtual int configuration_interface(const char* name, ci_command_t command); -#if BX_USE_WIN32USBDEBUG - virtual void register_usb_interface(usb_interface_callback_t callback, void *data); - virtual int usb_config_interface(int type, int wParam, int lParam); +#if BX_USB_DEBUGGER + virtual void register_usb_debug_type(int type); + virtual void usb_debug_trigger(int type, int trigger, int param1, int param2); + virtual int usb_debug_interface(int type, int param1, int param2); #endif virtual int begin_simulation(int argc, char *argv[]); virtual int register_runtime_config_handler(void *dev, rt_conf_handler_t handler); @@ -922,11 +923,11 @@ int bx_real_sim_c::configuration_interface(const char *ignore, ci_command_t comm BX_PANIC(("no configuration interface was loaded")); return -1; } - if (!strcmp(registered_ci_name, "wx")) + if (!strcmp(registered_ci_name, "wx")) { wxsel = 1; - else + } else { wxsel = 0; - bx_debug_gui = wxsel; + } if (command == CI_START) { ci_started = 1; } else if (command == CI_SHUTDOWN) { @@ -939,23 +940,26 @@ int bx_real_sim_c::configuration_interface(const char *ignore, ci_command_t comm return retval; } -#if BX_USE_WIN32USBDEBUG -void bx_real_sim_c::register_usb_interface(usb_interface_callback_t callback, void *data) +#if BX_USB_DEBUGGER +void bx_real_sim_c::register_usb_debug_type(int type) { - usbi_callback = callback; + usb_dbg_register_type(type); } -int bx_real_sim_c::usb_config_interface(int type, int wParam, int lParam) +void bx_real_sim_c::usb_debug_trigger(int type, int trigger, int param1, int param2) { - if (!usbi_callback) { - BX_PANIC(("no usb interface was loaded")); - return -1; + usb_dbg_trigger(type, trigger, param1, param2); +} + +int bx_real_sim_c::usb_debug_interface(int type, int param1, int param2) +{ + int retval = -1; + + if (type != USB_DEBUG_NONE) { + set_display_mode(DISP_MODE_CONFIG); + retval = usb_dbg_interface(type, param1, param2); + set_display_mode(DISP_MODE_SIM); } - - set_display_mode(DISP_MODE_CONFIG); - int retval = (*usbi_callback)(type, wParam, lParam); - set_display_mode(DISP_MODE_SIM); - return retval; } #endif @@ -1222,7 +1226,7 @@ bool bx_real_sim_c::restore_logopts() do { ret = fgets(line, sizeof(line)-1, fp); line[sizeof(line) - 1] = '\0'; - int len = strlen(line); + int len = (int)strlen(line); if ((len>0) && (line[len-1] < ' ')) line[len-1] = '\0'; i = 0; @@ -1273,7 +1277,7 @@ static int bx_restore_getline(FILE *fp, char *line, int maxlen) { char *ret = fgets(line, maxlen - 1, fp); line[maxlen - 1] = '\0'; - int len = strlen(line); + int len = (int)strlen(line); if ((len > 0) && (line[len - 1] < ' ')) line[len - 1] = '\0'; return (ret != NULL) ? len : 0; diff --git a/bochs/gui/siminterface.h b/bochs/gui/siminterface.h index 2e4c426ea3..3177ab8a96 100644 --- a/bochs/gui/siminterface.h +++ b/bochs/gui/siminterface.h @@ -119,7 +119,8 @@ typedef enum { BX_TOOLBAR_SNAPSHOT, BX_TOOLBAR_CONFIG, BX_TOOLBAR_MOUSE_EN, - BX_TOOLBAR_USER + BX_TOOLBAR_USER, + BX_TOOLBAR_USB_DEBUG } bx_toolbar_buttons; // normally all action choices are available for all event types. The exclude @@ -559,6 +560,35 @@ BOCHSAPI extern int floppy_type_n_sectors[]; BOCHSAPI extern const char *media_status_names[]; BOCHSAPI extern const char *bochs_bootdisk_names[]; +// usb_debug items +#if BX_USB_DEBUGGER + +enum { + USB_DEBUG_NONE, + USB_DEBUG_UHCI, + USB_DEBUG_OHCI, + USB_DEBUG_EHCI, + USB_DEBUG_XHCI +}; + +// USB debug break_type +#define USB_DEBUG_FRAME 1 +#define USB_DEBUG_COMMAND 2 +#define USB_DEBUG_EVENT 3 +#define USB_DEBUG_NONEXIST 4 +#define USB_DEBUG_RESET 5 +#define USB_DEBUG_ENABLE 6 + +#define BX_USB_DEBUG_SOF_NONE 0 +#define BX_USB_DEBUG_SOF_SET 1 +#define BX_USB_DEBUG_SOF_TRIGGER 2 + +// lParam flags +#define USB_LPARAM_FLAG_BEFORE 0x00000001 +#define USB_LPARAM_FLAG_AFTER 0x00000002 + +#endif + //////////////////////////////////////////////////////////////////// // base class simulator interface, contains just virtual functions. // I'm not longer sure that having a base class is going to be of any @@ -572,9 +602,6 @@ enum ci_return_t { CI_ERR_NO_TEXT_CONSOLE // err: can't work because there's no text console }; typedef int (*config_interface_callback_t)(void *userdata, ci_command_t command); -#if BX_USE_WIN32USBDEBUG - typedef int (*usb_interface_callback_t)(int type, int wParam, int lParam); -#endif typedef BxEvent* (*bxevent_handler)(void *theclass, BxEvent *event); typedef void (*rt_conf_handler_t)(void *this_ptr); typedef Bit32s (*addon_option_parser_t)(const char *context, int num_params, char *params[]); @@ -715,9 +742,10 @@ class BOCHSAPI bx_simulator_interface_c { config_interface_callback_t callback, void *userdata) {} virtual int configuration_interface(const char* name, ci_command_t command) {return -1; } -#if BX_USE_WIN32USBDEBUG - virtual void register_usb_interface(usb_interface_callback_t callback, void *data) {} - virtual int usb_config_interface(int type, int wParam, int lParam) { return -1; } +#if BX_USB_DEBUGGER + virtual void register_usb_debug_type(int type) {} + virtual void usb_debug_trigger(int type, int trigger, int param1, int param2) {} + virtual int usb_debug_interface(int type, int param1, int param2) { return -1; } #endif virtual int begin_simulation(int argc, char *argv[]) {return -1;} virtual int register_runtime_config_handler(void *dev, rt_conf_handler_t handler) {return 0;} diff --git a/bochs/gui/textconfig.cc b/bochs/gui/textconfig.cc index a2db15e7a6..a9ca046cd1 100644 --- a/bochs/gui/textconfig.cc +++ b/bochs/gui/textconfig.cc @@ -205,7 +205,7 @@ int ask_int(const char *prompt, const char *help, Bit64s min, Bit64s max, Bit64s bx_printf("Your choice must be an integer between " FMT_LL "d and " FMT_LL "d.\n\n", min, max); continue; } - illegal = (1 != sscanf(buffer, "%ld", &n)); + illegal = (1 != sscanf(buffer, FMT_LL "d", &n)); if (illegal || nmax) { bx_printf("Your choice (%s) was not an integer between " FMT_LL "d and " FMT_LL "d.\n\n", clean, min, max); @@ -623,10 +623,10 @@ void bx_log_options(int individual) if (ask_int(log_options_prompt1, "", -1, maxid-1, -1, &id) < 0) return; if (id < 0) return; - bx_printf("Editing log options for the device %s\n", SIM->get_prefix(id)); + bx_printf("Editing log options for the device %s\n", SIM->get_prefix((int)id)); for (level=0; levelget_max_log_level(); level++) { char prompt[1024]; - int default_action = SIM->get_log_action(id, level); + int default_action = SIM->get_log_action((int)id, level); sprintf(prompt, "Enter action for %s event: [%s] ", SIM->get_log_level_name(level), SIM->get_action_name(default_action)); // don't show the no change choice (choices=3) if (ask_menu(prompt, "", log_level_n_choices_normal, log_level_choices, default_action, &action)<0) @@ -634,7 +634,7 @@ void bx_log_options(int individual) // the exclude expression allows some choices not being available if they // don't make any sense. For example, it would be stupid to ignore a panic. if (!BX_LOG_OPTS_EXCLUDE(level, action)) { - SIM->set_log_action(id, level, action); + SIM->set_log_action((int)id, level, action); } else { bx_printf("Event type '%s' does not support log action '%s'.\n", SIM->get_log_level_name(level), log_level_choices[action]); @@ -1068,7 +1068,7 @@ int text_ask(bx_param_c *param) bx_list_c *list = (bx_list_c*)param; bx_param_c *child; const char *my_title = list->get_title(); - int i, imax = strlen(my_title); + int i, imax = (int)strlen(my_title); for (i=0; i + +const char *hc_param_str[] = { + "", + BXPN_USB_UHCI, + BXPN_USB_OHCI, + BXPN_USB_EHCI, + BXPN_USB_XHCI +}; + +/////////////////////////////////////////////////////////////////////////////////////////////// +// UHCI +// +struct S_ATTRIBUTES attribs_u_command[] = { + // | 31 chars + null | <- max + { (1<<7), (1<<7), 7, "Max Packet" , {-1, } }, + { (1<<6), (1<<6), 6, "Configure Flag" , {-1, } }, + { (1<<5), (1<<5), 5, "Software Debug" , {-1, } }, + { (1<<4), (1<<4), 4, "Force Global Resume" , {-1, } }, + { (1<<3), (1<<3), 3, "Enter Global Suspend Mode" , {-1, } }, + { (1<<2), (1<<2), 2, "Global Reset" , {-1, } }, + { (1<<1), (1<<1), 1, "Host Controller Reset" , {-1, } }, + { (1<<0), (1<<0), 0, "Run/Stop" , {-1, } }, + { 0, (Bit32u) -1, -1, "\0" , {-1, } } +}; + +struct S_ATTRIBUTES attribs_u_status[] = { + // | 31 chars + null | <- max + { (1<<5), (1<<5), 5, "HCHalted" , {-1, } }, + { (1<<4), (1<<4), 4, "Host Controller Process Error" , {-1, } }, + { (1<<3), (1<<3), 3, "Host System Error" , {-1, } }, + { (1<<2), (1<<2), 2, "Resume Detect" , {-1, } }, + { (1<<1), (1<<1), 1, "USB Error Interrupt" , {-1, } }, + { (1<<0), (1<<0), 0, "USB Interrupt" , {-1, } }, + { 0, (Bit32u) -1, -1, "\0" , {-1, } } +}; + +struct S_ATTRIBUTES attribs_u_interrupt[] = { + // | 31 chars + null | <- max + { (1<<3), (1<<3), 3, "Short packet Interrupt Enable" , {-1, } }, + { (1<<2), (1<<2), 2, "Interrupt On Complete (IOC)" , {-1, } }, + { (1<<1), (1<<1), 1, "Resume Interrupt Enable" , {-1, } }, + { (1<<0), (1<<0), 0, "Timeout/CRC Interrupt Enable" , {-1, } }, + { 0, (Bit32u) -1, -1, "\0" , {-1, } } +}; + +struct S_ATTRIBUTES attribs_u_ports[] = { + // | 31 chars + null | <- max + { (1<<15), (1<<15), 15, "Zero (bit 15)" , {-1, } }, + { (1<<14), (1<<14), 14, "Zero (bit 14)" , {-1, } }, + { (1<<13), (1<<13), 13, "Zero (bit 13)" , {-1, } }, + { (1<<12), (1<<12), 12, "Suspend" , {-1, } }, + { (1<<11), (1<<11), 11, "Over-current Changed" , {-1, } }, + { (1<<10), (1<<10), 10, "Over-current Status" , {-1, } }, + { (1<< 9), (1<< 9), 9, "Port Reset" , {-1, } }, + { (1<< 8), (1<< 8), 8, "Low Speed Device Attached" , {-1, } }, + { (1<< 7), (1<< 7), 7, "Reserved (must be 1)" , {-1, } }, + { (1<< 6), (1<< 6), 6, "Resume Detect" , {-1, } }, + { (1<< 5), (1<< 5), 5, "Line Status: D-" , {-1, } }, + { (1<< 4), (1<< 4), 4, "Line Status: D+" , {-1, } }, + { (1<< 3), (1<< 3), 3, "Port Enable/Disable Change" , {-1, } }, + { (1<< 2), (1<< 2), 2, "Port Enabled/Disabled" , {-1, } }, + { (1<< 1), (1<< 1), 1, "Current Status Change" , {-1, } }, + { (1<< 0), (1<< 0), 0, "Current Connect Status" , {-1, } }, + { 0, (Bit32u) -1, -1, "\0" , {-1, } } +}; + +/////////////////////////////////////////////////////////////////////////////////////////////// +// XHCI +// +struct S_ATTRIBUTES attribs_x_ports[] = { + // | 31 chars + null | <- max + { (1ULL<<31), (1ULL<<31), 31, "Warm Port Reset" , {-1, } }, + { (1<<30), (1<<30), 30, "Device Removable" , {-1, } }, + { (1<<29), (1<<29), 29, "Reserved (bit 29)" , {-1, } }, + { (1<<28), (1<<28), 28, "Reserved (bit 28)" , {-1, } }, + { (1<<27), (1<<27), 27, "Wake on Over-current Enable" , {-1, } }, + { (1<<26), (1<<26), 26, "Wake on Disconnect Enable" , {-1, } }, + { (1<<25), (1<<25), 25, "Wake on Connect Enable" , {-1, } }, + { (1<<24), (1<<24), 24, "Cold Attach Status" , {-1, } }, + { (1<<23), (1<<23), 23, "Port Config Error Change" , {-1, } }, + { (1<<22), (1<<22), 22, "Port Link State Change" , {-1, } }, + { (1<<21), (1<<21), 21, "Port Reset Change" , {-1, } }, + { (1<<20), (1<<20), 20, "Over-current Change" , {-1, } }, + { (1<<19), (1<<19), 19, "Warm Port Reset Change" , {-1, } }, + { (1<<18), (1<<18), 18, "Port Enable/Disable Change" , {-1, } }, + { (1<<17), (1<<17), 17, "Connect Status Change" , {-1, } }, + { (1<<16), (1<<16), 16, "Port Link State Write Strobe" , {-1, } }, + { (1<<15), (1<<15), 15, "Port Indicator (bit 1)" , {-1, } }, + { (1<<14), (1<<14), 14, "Port Indicator (bit 0)" , {-1, } }, + { (1<<13), (1<<13), 13, "Port Speed (bit 3)" , {-1, } }, + { (1<<12), (1<<12), 12, "Port Speed (bit 2)" , {-1, } }, + { (1<<11), (1<<11), 11, "Port Speed (bit 1)" , {-1, } }, + { (1<<10), (1<<10), 10, "Port Speed (bit 0)" , {-1, } }, + { (1<< 9), (1<< 9), 9, "Port Power" , {-1, } }, + { (1<< 8), (1<< 8), 8, "Port Link State (bit 3)" , {-1, } }, + { (1<< 7), (1<< 7), 7, "Port Link State (bit 2)" , {-1, } }, + { (1<< 6), (1<< 6), 6, "Port Link State (bit 1)" , {-1, } }, + { (1<< 5), (1<< 5), 5, "Port Link State (bit 0)" , {-1, } }, + { (1<< 4), (1<< 4), 4, "Port Reset" , {-1, } }, + { (1<< 3), (1<< 3), 3, "Over-current Status" , {-1, } }, + { (1<< 2), (1<< 2), 2, "Reserved" , {-1, } }, + { (1<< 1), (1<< 1), 1, "Port Enabled/Disabled" , {-1, } }, + { (1<< 0), (1<< 0), 0, "Current Connect Status" , {-1, } }, + { 0, (Bit32u) -1, -1, "\0" , {-1, } } +}; + +int usb_debug_type = USB_DEBUG_NONE; +bx_param_c *host_param = NULL; +Bit32u pci_bar_address; +bool u_changed[UHCI_REG_COUNT]; + +bool uhci_add_queue(struct USB_UHCI_QUEUE_STACK *stack, const Bit32u addr) +{ + // check to see if this queue has been processed before + for (int i=0; iqueue_cnt; i++) { + if (stack->queue_stack[i] == addr) + return true; + } + + // if the stack is full, we return TRUE anyway + if (stack->queue_cnt == USB_UHCI_QUEUE_STACK_SIZE) + return true; + + // add the queue's address + stack->queue_stack[stack->queue_cnt] = addr; + stack->queue_cnt++; + + return false; +} + +void usb_dbg_register_type(int type) +{ + if (type != USB_DEBUG_NONE) { + if ((type != USB_DEBUG_UHCI) && (type != USB_DEBUG_XHCI)) { + BX_PANIC(("USB debugger does not yet support type %d", type)); + } else { + usb_debug_type = type; + bx_gui->set_usbdbg_bitmap(0); + } + } +} + +int usb_dbg_interface(int type, int param1, int param2) +{ + if (SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get() > 0) { + // if "start_frame" is 0, do the debug_window + // if "start_frame" is 1, wait for the trigger from the HC + // (set the value to 2, then return, allowing the trigger to envoke it) + // if "start_frame" is 2, the HC triggered the debug + if (SIM->get_param_num(BXPN_USB_DEBUG_START_FRAME)->get() == BX_USB_DEBUG_SOF_SET) { + SIM->get_param_num(BXPN_USB_DEBUG_START_FRAME)->set(BX_USB_DEBUG_SOF_TRIGGER); + bx_gui->set_usbdbg_bitmap(1); + } else { + bx_gui->set_usbdbg_bitmap(0); + if (usb_debug_dialog(type, param1, param2) < 0) { + bx_user_quit = 1; +#if !BX_DEBUGGER + bx_atexit(); + SIM->quit_sim(1); +#else + bx_dbg_exit(1); +#endif + return -1; + } + } + } + return 0; +} + +// one of the controllers has triggered a debug item. +void usb_dbg_trigger(int type, int trigger, int param1, int param2) +{ + if ((usb_debug_type == USB_DEBUG_NONE) || (type != usb_debug_type)) + return; + + bx_param_bool_c *bool_trigger; + bx_param_num_c *num_trigger; + switch (trigger) { + case USB_DEBUG_FRAME: + num_trigger = SIM->get_param_num(BXPN_USB_DEBUG_START_FRAME); + if (num_trigger && (num_trigger->get() == BX_USB_DEBUG_SOF_TRIGGER)) { + SIM->usb_debug_interface(USB_DEBUG_FRAME, param1, param2); + num_trigger->set(BX_USB_DEBUG_SOF_SET); + } + break; + + case USB_DEBUG_COMMAND: + bool_trigger = SIM->get_param_bool(BXPN_USB_DEBUG_DOORBELL); + if (bool_trigger && bool_trigger->get()) + SIM->usb_debug_interface(USB_DEBUG_COMMAND, param1, param2); + break; + + case USB_DEBUG_EVENT: + bool_trigger = SIM->get_param_bool(BXPN_USB_DEBUG_EVENT); + if (bool_trigger && bool_trigger->get()) + SIM->usb_debug_interface(USB_DEBUG_EVENT, param1, param2); + break; + + case USB_DEBUG_NONEXIST: + bool_trigger = SIM->get_param_bool(BXPN_USB_DEBUG_NON_EXIST); + if (bool_trigger && bool_trigger->get()) + SIM->usb_debug_interface(USB_DEBUG_NONEXIST, param1, param2); + break; + + case USB_DEBUG_RESET: + bool_trigger = SIM->get_param_bool(BXPN_USB_DEBUG_RESET); + if (bool_trigger && bool_trigger->get()) + SIM->usb_debug_interface(USB_DEBUG_RESET, param1, param2); + break; + + case USB_DEBUG_ENABLE: + bool_trigger = SIM->get_param_bool(BXPN_USB_DEBUG_ENABLE); + if (bool_trigger && bool_trigger->get()) + SIM->usb_debug_interface(USB_DEBUG_ENABLE, param1, param2); + break; + } +} + +Bit32u get_pci_bar_addr(bx_shadow_data_c *pci_conf, Bit8u bar_num) +{ + if ((pci_conf != NULL) && (bar_num < 5)) { + Bit8u *data = pci_conf->getptr() + 0x10 + (bar_num << 2); + Bit32u value = ReadHostDWordFromLittleEndian((Bit32u*)data); + if (value & 1) { + return (value & 0xfffc); + } else { + return (value & 0xfffffff0); + } + } else { + return 0; + } +} + +Bit32u usb_io_read(Bit16u addr, unsigned io_len) +{ + return bx_devices.inp(addr, io_len); +} + +void usb_io_write(Bit16u addr, Bit32u value, unsigned io_len) +{ + bx_devices.outp(addr, value, io_len); +} + +Bit32u xhci_read_dword(const Bit32u address) +{ + Bit32u value = 0; + + if (address > 0) { + DEV_MEM_READ_PHYSICAL(address, 4, (Bit8u*)&value); + } + return value; +} + +#endif diff --git a/bochs/gui/usb_debug.h b/bochs/gui/usb_debug.h new file mode 100644 index 0000000000..3bce0ab245 --- /dev/null +++ b/bochs/gui/usb_debug.h @@ -0,0 +1,117 @@ +///////////////////////////////////////////////////////////////////////// +// $Id$ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 Benjamin David Lunt +// Copyright (C) 2003-2024 The Bochs Project +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef BX_USB_DEBUG_H +#define BX_USB_DEBUG_H + +#if BX_USB_DEBUGGER + +#define COMMON_STR_SIZE 128 + +struct S_ATTRIBUTES { + Bit64u attrb; + Bit64u mask; + int index; + char str[32]; + int groups[10]; // up to 10 items can be grouped. Increase if we need more. +}; + +enum { + UHCI_REG_COMMAND, + UHCI_REG_STATUS, + UHCI_REG_INTERRUPT, + UHCI_REG_FRAME_NUM, + UHCI_REG_FRAME_ADDR, + UHCI_REG_SOF, + UHCI_REG_PORT0, + UHCI_REG_PORT1, + UHCI_REG_COUNT +}; + +// copy&paste start +// from uhci_core.h +#define USB_UHCI_QUEUE_STACK_SIZE 256 + +#define USB_UHCI_IS_LINK_VALID(item) ((item & 1) == 0) // return TRUE if valid link address +#define USB_UHCI_IS_LINK_QUEUE(item) ((item & 2) == 2) // return TRUE if link is a queue pointer + +struct USB_UHCI_QUEUE_STACK { + int queue_cnt; + Bit32u queue_stack[USB_UHCI_QUEUE_STACK_SIZE]; +}; + +#pragma pack (push, 1) +struct TD { + Bit32u dword0; + Bit32u dword1; + Bit32u dword2; + Bit32u dword3; +}; + +struct QUEUE { + Bit32u horz; + Bit32u vert; +}; +#pragma pack (pop) + +// from usb_xhci.h +#define OPS_REGS_OFFSET 0x20 +#define XHCI_PORT_SET_OFFSET (0x400 + OPS_REGS_OFFSET) +// copy&paste end + +extern const char *hc_param_str[]; + +extern int usb_debug_type; +extern bx_param_c *host_param; +extern Bit32u pci_bar_address; + +// UHCI +extern struct S_ATTRIBUTES attribs_u_command[]; +extern struct S_ATTRIBUTES attribs_u_status[]; +extern struct S_ATTRIBUTES attribs_u_interrupt[]; +extern struct S_ATTRIBUTES attribs_u_ports[]; + +extern bool u_changed[UHCI_REG_COUNT]; + +bool uhci_add_queue(struct USB_UHCI_QUEUE_STACK *stack, const Bit32u addr); + +// xHCI +extern struct S_ATTRIBUTES attribs_x_ports[]; + +// USB debug API +void usb_dbg_register_type(int type); + +int usb_dbg_interface(int type, int param1, int param2); + +void usb_dbg_trigger(int type, int trigger, int param1, int param2); + +int usb_debug_dialog(int break_type, int param1, int param2); + +Bit32u get_pci_bar_addr(bx_shadow_data_c *pci_conf, Bit8u bar_num); + +Bit32u usb_io_read(Bit16u addr, unsigned io_len); + +void usb_io_write(Bit16u addr, Bit32u value, unsigned io_len); + +Bit32u xhci_read_dword(const Bit32u address); + +#endif // BX_USB_DEBUGGER +#endif // BX_USB_DEBUG_H diff --git a/bochs/gui/vncsrv.cc b/bochs/gui/vncsrv.cc index 6c4d464322..dd09a09474 100644 --- a/bochs/gui/vncsrv.cc +++ b/bochs/gui/vncsrv.cc @@ -7,7 +7,7 @@ // Donald Becker // http://www.psyon.org // -// Copyright (C) 2001-2023 The Bochs Project +// Copyright (C) 2001-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -44,6 +44,10 @@ // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE +#ifdef __CYGWIN__ +#define __USE_W32_SOCKETS +#endif + #include "param_names.h" #include "iodev.h" #include "keymap.h" diff --git a/bochs/gui/win32.cc b/bochs/gui/win32.cc index 6ab45a9dac..0f85d716d7 100644 --- a/bochs/gui/win32.cc +++ b/bochs/gui/win32.cc @@ -176,6 +176,7 @@ static unsigned stretch_factor; static BOOL fix_size = FALSE; #if BX_DEBUGGER && BX_DEBUGGER_GUI static BOOL gui_debug = FALSE; +static BOOL win32_enh_dbg_global_ini = FALSE; #endif static HWND hotKeyReceiver = NULL; static HWND saveParent = NULL; @@ -658,41 +659,36 @@ void bx_win32_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) mouseToggleReq = FALSE; // parse win32 specific options + Bit8u flags = BX_GUI_OPT_NOKEYREPEAT | BX_GUI_OPT_HIDE_IPS | BX_GUI_OPT_CMDMODE; if (argc > 1) { for (i = 1; i < argc; i++) { - BX_INFO(("option %d: %s", i, argv[i])); - if (!strcmp(argv[i], "nokeyrepeat")) { - BX_INFO(("disabled host keyboard repeat")); - win32_nokeyrepeat = 1; - } else if (!strcmp(argv[i], "traphotkeys")) { - BX_INFO(("trap system hotkeys for Bochs window")); - win32_traphotkeys = 1; - } else if (!strcmp(argv[i], "gui_debug")) { -#if BX_DEBUGGER && BX_DEBUGGER_GUI - if (gui_ci) { - gui_debug = TRUE; - SIM->set_debug_gui(1); + if (!parse_common_gui_options(argv[i], flags)) { + if (!strcmp(argv[i], "traphotkeys")) { + BX_INFO(("trap system hotkeys for Bochs window")); + win32_traphotkeys = 1; + } else if (!strcmp(argv[i], "autoscale")) { + win32_autoscale = 1; } else { - BX_PANIC(("Config interface 'win32config' is required for gui debugger")); + BX_PANIC(("Unknown win32 option '%s'", argv[i])); } -#else - SIM->message_box("ERROR", "Bochs debugger not available - ignoring 'gui_debug' option"); -#endif -#if BX_SHOW_IPS - } else if (!strcmp(argv[i], "hideIPS")) { - BX_INFO(("hide IPS display in status bar")); - hideIPS = TRUE; -#endif - } else if (!strcmp(argv[i], "cmdmode")) { - command_mode.present = 1; - } else if (!strcmp(argv[i], "autoscale")) { - win32_autoscale = 1; - } else { - BX_PANIC(("Unknown win32 option '%s'", argv[i])); } } } + win32_nokeyrepeat = gui_opts.nokeyrepeat; + hideIPS = gui_opts.hide_ips; +#if BX_DEBUGGER && BX_DEBUGGER_GUI + if (gui_opts.enh_dbg_enabled) { + if (gui_ci) { + gui_debug = TRUE; + SIM->set_debug_gui(1); + win32_enh_dbg_global_ini = gui_opts.enh_dbg_global_ini; + } else { + BX_PANIC(("Config interface 'win32config' is required for gui debugger")); + } + } +#endif + mouse_buttons = GetSystemMetrics(SM_CMOUSEBUTTONS); BX_INFO(("Number of Mouse Buttons = %d", mouse_buttons)); if ((SIM->get_param_enum(BXPN_MOUSE_TOGGLE)->get() == BX_MOUSE_TOGGLE_CTRL_MB) && @@ -967,8 +963,9 @@ DWORD WINAPI UIThread(LPVOID) SendMessage(hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0); SendMessage(hwndTB, TB_SETBITMAPSIZE, 0, (LPARAM)MAKELONG(32, 32)); - hwndSB = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", - stInfo.mainWnd, 0x7712); + hwndSB = CreateWindowEx(0, STATUSCLASSNAME, (PCTSTR)NULL, + WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, stInfo.mainWnd, + (HMENU) 0x7712, stInfo.hInstance, NULL); if (hwndSB) { unsigned elements; SB_Edges[0] = SIZE_OF_SB_MOUSE_MESSAGE + SIZE_OF_SB_ELEMENT; @@ -1031,7 +1028,7 @@ DWORD WINAPI UIThread(LPVOID) ShowWindow(stInfo.mainWnd, SW_SHOW); #if BX_DEBUGGER && BX_DEBUGGER_GUI if (gui_debug) { - bx_gui->init_debug_dialog(); + bx_gui->init_debug_dialog(win32_enh_dbg_global_ini); } #endif #if BX_SHOW_IPS @@ -1772,7 +1769,7 @@ void bx_win32_gui_c::draw_char(Bit8u ch, Bit8u fc, Bit8u bc, Bit16u xc, Bit16u y if ((ce - cs + 1) < fh) { fh = ce - cs + 1; } - DrawBitmap(hdc, vgafont[map][ch], xc, yc, fw, fh, fx, fy, bc, fc); + DrawBitmap(hdc, vgafont[map][ch], xc, yc, fw, fh, fx, cs, bc, fc); } ReleaseDC(stInfo.simWnd, hdc); LeaveCriticalSection(&stInfo.drawCS); @@ -1843,18 +1840,22 @@ void bx_win32_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0) { HDC hdc; HGDIOBJ oldObj; + unsigned yt = y_tilesize; + if ((y0 + y_tilesize) > dimension_y) { + yt = dimension_y - y0; + } EnterCriticalSection(&stInfo.drawCS); hdc = GetDC(stInfo.simWnd); oldObj = SelectObject(MemoryDC, MemoryBitmap); - StretchDIBits(MemoryDC, x0, y0, x_tilesize, y_tilesize, 0, 0, - x_tilesize, y_tilesize, tile, bitmap_info, DIB_RGB_COLORS, SRCCOPY); + StretchDIBits(MemoryDC, x0, y0, x_tilesize, yt, 0, 0, + x_tilesize, yt, tile, bitmap_info, DIB_RGB_COLORS, SRCCOPY); SelectObject(MemoryDC, oldObj); - updateUpdated(x0, y0, x0 + x_tilesize - 1, y0 + y_tilesize - 1); + updateUpdated(x0, y0, x0 + x_tilesize - 1, y0 + yt - 1); ReleaseDC(stInfo.simWnd, hdc); LeaveCriticalSection(&stInfo.drawCS); @@ -1876,6 +1877,10 @@ void bx_win32_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, if ((x == dimension_x) && (y == dimension_y) && (bpp == current_bpp)) return; + if (fullscreenMode) { + clear_screen(); + flush(); + } dimension_x = x; dimension_y = y; @@ -1890,8 +1895,12 @@ void bx_win32_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, } } - bitmap_info->bmiHeader.biBitCount = bpp; if (bpp != current_bpp) { + if (bpp == 15) { + bitmap_info->bmiHeader.biBitCount = 16; + } else { + bitmap_info->bmiHeader.biBitCount = bpp; + } if (bpp == 16) { bitmap_info->bmiHeader.biCompression = BI_BITFIELDS; static RGBQUAD red_mask = {0x00, 0xF8, 0x00, 0x00}; @@ -1910,9 +1919,6 @@ void bx_win32_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, bitmap_info->bmiColors[2] = bitmap_info->bmiColors[258]; } bitmap_info->bmiHeader.biCompression = BI_RGB; - if (bpp == 15) { - bitmap_info->bmiHeader.biBitCount = 16; - } } } current_bpp = guest_bpp = bpp; diff --git a/bochs/gui/win32config.cc b/bochs/gui/win32config.cc index 428356b740..981dc8e49f 100644 --- a/bochs/gui/win32config.cc +++ b/bochs/gui/win32config.cc @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2003-2023 The Bochs Project +// Copyright (C) 2003-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -31,10 +31,6 @@ #include "win32res.h" #include "win32paramdlg.h" #include "plugin.h" -#if BX_USE_WIN32USBDEBUG - #include "win32usb.h" - static int win32_usbi_callback(int type, int wParam, int lParam); -#endif #if BX_USE_WIN32CONFIG @@ -45,9 +41,6 @@ PLUGIN_ENTRY_FOR_MODULE(win32config) { if (mode == PLUGIN_INIT) { SIM->register_configuration_interface("win32config", win32_ci_callback, NULL); -#if BX_USE_WIN32USBDEBUG - SIM->register_usb_interface(win32_usbi_callback, NULL); -#endif SIM->set_notify_callback(win32_notify_callback, NULL); } else if (mode == PLUGIN_PROBE) { return (int)PLUGTYPE_CI; @@ -805,34 +798,4 @@ static int win32_ci_callback(void *userdata, ci_command_t command) return 0; } -#if BX_USE_WIN32USBDEBUG -static int win32_usbi_callback(int type, int wParam, int lParam) { - if (!bx_gui->has_gui_console()) { - if (SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get() > 0) { - // if "start_frame" is 0, do the debug_window - // if "start_frame" is 1, wait for the trigger from the HC - // (set the value to 2, then return, allowing the trigger to envoke it) - // if "start_frame" is 2, the HC triggered the debug - if (SIM->get_param_num(BXPN_USB_DEBUG_START_FRAME)->get() == BX_USB_DEBUG_SOF_SET) { - SIM->get_param_num(BXPN_USB_DEBUG_START_FRAME)->set(BX_USB_DEBUG_SOF_TRIGGER); - bx_gui->replace_bitmap(bx_gui->usb_hbar_id, bx_gui->usb_trigger_bmap_id); - } else { - bx_gui->replace_bitmap(bx_gui->usb_hbar_id, bx_gui->usb_bmap_id); - if (win32_usb_start(GetBochsWindow(), type, wParam, lParam) < 0) { - bx_user_quit = 1; - #if !BX_DEBUGGER - bx_atexit(); - SIM->quit_sim(1); - #else - bx_dbg_exit(1); - #endif - return -1; - } - } - } - } - return 0; -} -#endif - #endif // BX_USE_WIN32CONFIG diff --git a/bochs/gui/win32dialog.h b/bochs/gui/win32dialog.h index dd80022e98..0fd21f9b7e 100644 --- a/bochs/gui/win32dialog.h +++ b/bochs/gui/win32dialog.h @@ -24,12 +24,11 @@ #include "config.h" // Compilation for WIN64 native require minimum 0x0500 -#ifndef _WIN32_IE -#define _WIN32_IE 0x0500 /* Force a minimum "OS level" for commctrl.h */ -#endif #if _WIN32_IE < 0x0500 #undef _WIN32_IE -#define _WIN32_IE 0x0500 +#endif +#ifndef _WIN32_IE +#define _WIN32_IE 0x0500 /* Force a minimum "OS level" for commctrl.h */ #endif extern "C" { diff --git a/bochs/gui/win32usb.cc b/bochs/gui/win32usb.cc index 96664756f8..47512590f7 100644 --- a/bochs/gui/win32usb.cc +++ b/bochs/gui/win32usb.cc @@ -19,14 +19,9 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - #include "bochs.h" -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER #include "windowsx.h" @@ -35,6 +30,7 @@ #include "iodev.h" #include "param_names.h" +#include "usb_debug.h" #include "win32usbres.h" #include "win32usb.h" @@ -48,15 +44,6 @@ static const int dlg_resource[5] = { USB_DEBUG_XHCI_DLG }; -bx_param_c *host_param = NULL; -static const char *hc_param_str[5] = { - "", - BXPN_USB_UHCI, - BXPN_USB_OHCI, - BXPN_USB_EHCI, - BXPN_USB_XHCI -}; - static const DLGPROC usb_debug_callbacks[5] = { NULL, hc_uhci_callback, @@ -65,7 +52,6 @@ static const DLGPROC usb_debug_callbacks[5] = { hc_xhci_callback }; -Bit32u pci_bar_address = 0; struct CALLBACK_PARAMS g_params; HFONT hTreeViewFont; @@ -74,48 +60,48 @@ HFONT hTreeViewFont; // Common to all HC types // +HWND getBochsWindow() +{ + return GetForegroundWindow(); // FIXME +} + // return 0 to continue with emulation // return -1 to quit emulation -int win32_usb_start(HWND hwnd, int break_type, int wParam, int lParam) +int usb_debug_dialog(int break_type, int param1, int param2) { char str[COMMON_STR_SIZE]; int ret; // get the (host controller) type we are to debug - Bit32s type = SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get(); - if ((type < USB_DEBUG_UHCI) || (type > USB_DEBUG_XHCI)) { - sprintf(str, "Unknown host controller type given: %d", type); - MessageBox(hwnd, str, NULL, MB_ICONINFORMATION); - return 0; - } + bx_param_enum_c *debug_type = SIM->get_param_enum(BXPN_USB_DEBUG_TYPE); - // check to make sure the specified HC was enabled and in use - host_param = SIM->get_param(hc_param_str[type]); - if ((host_param == NULL) || !host_param->get_enabled()) { - sprintf(str, "Parameter not found or enabled: %s", hc_param_str[type]); - MessageBox(hwnd, str, NULL, MB_ICONINFORMATION); + // check to make sure the specified HC is enabled + host_param = SIM->get_param(hc_param_str[usb_debug_type]); + if ((host_param == NULL) || !SIM->get_param_bool("enabled", host_param)->get()) { + sprintf(str, "Selected USB HC not enabled: %s", debug_type->get_choice(usb_debug_type)); + MessageBox(getBochsWindow(), str, NULL, MB_ICONINFORMATION); return 0; } // create a font for the TreeView - hTreeViewFont = CreateFont(14, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, - OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + hTreeViewFont = CreateFont(14, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, + OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Cascadia")); if (hTreeViewFont == NULL) { - hTreeViewFont = CreateFont(14, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, - OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + hTreeViewFont = CreateFont(14, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, + OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Consolas")); } if (hTreeViewFont == NULL) { - hTreeViewFont = CreateFont(14, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, - OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + hTreeViewFont = CreateFont(14, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, + OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Courier New")); } if (hTreeViewFont == NULL) { - MessageBox(hwnd, "Could not create a font for the Tree View Control", NULL, MB_ICONINFORMATION); + MessageBox(getBochsWindow(), "Could not create a font for the Tree View Control", NULL, MB_ICONINFORMATION); return 0; } - + // if the mouse is currently being captured, we need to pause capture mode BOOL capture = SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get(); if (capture) { @@ -123,12 +109,12 @@ int win32_usb_start(HWND hwnd, int break_type, int wParam, int lParam) } // create the dialog and wait for it to return - g_params.type = type; + g_params.type = usb_debug_type; g_params.break_type = break_type; - g_params.wParam = wParam; - g_params.lParam = lParam; - ret = (int) DialogBoxParam(NULL, MAKEINTRESOURCE(dlg_resource[type]), hwnd, - usb_debug_callbacks[type], (LPARAM) 0); + g_params.wParam = param1; + g_params.lParam = param2; + ret = (int) DialogBoxParam(NULL, MAKEINTRESOURCE(dlg_resource[usb_debug_type]), getBochsWindow(), + usb_debug_callbacks[usb_debug_type], (LPARAM) 0); // destroy the font DeleteObject(hTreeViewFont); @@ -136,59 +122,8 @@ int win32_usb_start(HWND hwnd, int break_type, int wParam, int lParam) if (capture) { SIM->get_param_bool(BXPN_MOUSE_ENABLED)->set(1); } - - return ret; -} -// one of the controllers has triggered a debug item. -void win32_usb_trigger(int type, int trigger, int wParam, int lParam) { - - // check that we are the correct controller type - bx_param_enum_c *cntlr_type = SIM->get_param_enum(BXPN_USB_DEBUG_TYPE); - if ((cntlr_type == NULL) || (cntlr_type->get() != type)) - return; - - bx_param_bool_c *bool_trigger; - bx_param_num_c *num_trigger; - switch (trigger) { - case USB_DEBUG_FRAME: - num_trigger = SIM->get_param_num(BXPN_USB_DEBUG_START_FRAME); - if (num_trigger && (num_trigger->get() == BX_USB_DEBUG_SOF_TRIGGER)) { - SIM->usb_config_interface(USB_DEBUG_FRAME, wParam, lParam); - num_trigger->set(BX_USB_DEBUG_SOF_SET); - } - break; - - case USB_DEBUG_COMMAND: - bool_trigger = SIM->get_param_bool(BXPN_USB_DEBUG_DOORBELL); - if (bool_trigger && bool_trigger->get()) - SIM->usb_config_interface(USB_DEBUG_COMMAND, wParam, lParam); - break; - - case USB_DEBUG_EVENT: - bool_trigger = SIM->get_param_bool(BXPN_USB_DEBUG_EVENT); - if (bool_trigger && bool_trigger->get()) - SIM->usb_config_interface(USB_DEBUG_EVENT, wParam, lParam); - break; - - case USB_DEBUG_NONEXIST: - bool_trigger = SIM->get_param_bool(BXPN_USB_DEBUG_NON_EXIST); - if (bool_trigger && bool_trigger->get()) - SIM->usb_config_interface(USB_DEBUG_NONEXIST, wParam, lParam); - break; - - case USB_DEBUG_RESET: - bool_trigger = SIM->get_param_bool(BXPN_USB_DEBUG_RESET); - if (bool_trigger && bool_trigger->get()) - SIM->usb_config_interface(USB_DEBUG_RESET, wParam, lParam); - break; - - case USB_DEBUG_ENABLE: - bool_trigger = SIM->get_param_bool(BXPN_USB_DEBUG_ENABLE); - if (bool_trigger && bool_trigger->get()) - SIM->usb_config_interface(USB_DEBUG_ENABLE, wParam, lParam); - break; - } + return ret; } HWND TreeView = NULL; @@ -235,17 +170,17 @@ INT_PTR CALLBACK dump_dialog_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM else sprintf(str, "%s--Address: 0x%08X: size = %i", g_dump_parms.title, (Bit32u) g_dump_parms.address, g_dump_parms.size); SetWindowText(hDlg, str); - + // we need a fixed width font for the dump - HFONT hDumpFont = CreateFont(14, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, - OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + HFONT hDumpFont = CreateFont(14, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, + OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Courier New")); SNDMSG(GetDlgItem(hDlg, IDC_DUMP), WM_SETFONT, (WPARAM) hDumpFont, FALSE); - + // read in the buffer Bit8u *buffer = new Bit8u[g_dump_parms.size]; DEV_MEM_READ_PHYSICAL(g_dump_parms.address, g_dump_parms.size, buffer); - + // dump it int j = 0; strcpy(str, ""); @@ -293,7 +228,7 @@ INT_PTR CALLBACK dump_dialog_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM break; } } - + return 0; } @@ -301,61 +236,6 @@ INT_PTR CALLBACK dump_dialog_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM /////////////////////////////////////////////////////////////////////////////////////////////// // UHCI // -struct S_ATTRIBUTES attribs_u_command[] = { - // | 31 chars + null | <- max - { (1<<7), (1<<7), 7, "Max Packet" , {-1, } }, - { (1<<6), (1<<6), 6, "Configure Flag" , {-1, } }, - { (1<<5), (1<<5), 5, "Software Debug" , {-1, } }, - { (1<<4), (1<<4), 4, "Force Global Resume" , {-1, } }, - { (1<<3), (1<<3), 3, "Enter Global Suspend Mode" , {-1, } }, - { (1<<2), (1<<2), 2, "Global Reset" , {-1, } }, - { (1<<1), (1<<1), 1, "Host Controller Reset" , {-1, } }, - { (1<<0), (1<<0), 0, "Run/Stop" , {-1, } }, - { 0, (DWORD) -1, -1, "\0" , {-1, } } -}; - -struct S_ATTRIBUTES attribs_u_status[] = { - // | 31 chars + null | <- max - { (1<<5), (1<<5), 5, "HCHalted" , {-1, } }, - { (1<<4), (1<<4), 4, "Host Controller Process Error" , {-1, } }, - { (1<<3), (1<<3), 3, "Host System Error" , {-1, } }, - { (1<<2), (1<<2), 2, "Resume Detect" , {-1, } }, - { (1<<1), (1<<1), 1, "USB Error Interrupt" , {-1, } }, - { (1<<0), (1<<0), 0, "USB Interrupt" , {-1, } }, - { 0, (DWORD) -1, -1, "\0" , {-1, } } -}; - -struct S_ATTRIBUTES attribs_u_interrupt[] = { - // | 31 chars + null | <- max - { (1<<3), (1<<3), 3, "Short packet Interrupt Enable" , {-1, } }, - { (1<<2), (1<<2), 2, "Interrupt On Complete (IOC)" , {-1, } }, - { (1<<1), (1<<1), 1, "Resume Interrupt Enable" , {-1, } }, - { (1<<0), (1<<0), 0, "Timeout/CRC Interrupt Enable" , {-1, } }, - { 0, (DWORD) -1, -1, "\0" , {-1, } } -}; - -struct S_ATTRIBUTES attribs_u_ports[] = { - // | 31 chars + null | <- max - { (1<<15), (1<<15), 15, "Zero (bit 15)" , {-1, } }, - { (1<<14), (1<<14), 14, "Zero (bit 14)" , {-1, } }, - { (1<<13), (1<<13), 13, "Zero (bit 13)" , {-1, } }, - { (1<<12), (1<<12), 12, "Suspend" , {-1, } }, - { (1<<11), (1<<11), 11, "Over-current Changed" , {-1, } }, - { (1<<10), (1<<10), 10, "Over-current Status" , {-1, } }, - { (1<< 9), (1<< 9), 9, "Port Reset" , {-1, } }, - { (1<< 8), (1<< 8), 8, "Low Speed Device Attached" , {-1, } }, - { (1<< 7), (1<< 7), 7, "Reserved (must be 1)" , {-1, } }, - { (1<< 6), (1<< 6), 6, "Resume Detect" , {-1, } }, - { (1<< 5), (1<< 5), 5, "Line Status: D-" , {-1, } }, - { (1<< 4), (1<< 4), 4, "Line Status: D+" , {-1, } }, - { (1<< 3), (1<< 3), 3, "Port Enable/Disable Change" , {-1, } }, - { (1<< 2), (1<< 2), 2, "Port Enabled/Disabled" , {-1, } }, - { (1<< 1), (1<< 1), 1, "Current Status Change" , {-1, } }, - { (1<< 0), (1<< 0), 0, "Current Connect Status" , {-1, } }, - { 0, (DWORD) -1, -1, "\0" , {-1, } } -}; - -BOOL u_changed[IDC_U_EN_END - IDC_U_EN_START + 1]; // lParam: type is in low 8 bits, break_type in high 8-bits of low word INT_PTR CALLBACK hc_uhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) @@ -367,7 +247,7 @@ INT_PTR CALLBACK hc_uhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPa case WM_INITDIALOG: sprintf(str, "Bochs for Windows -- USB Debug: UHCI Host Controller"); SetWindowText(hDlg, str); - + // call the initializer TreeView = GetDlgItem(hDlg, IDC_STACK); SNDMSG(TreeView, WM_SETFONT, (WPARAM) hTreeViewFont, FALSE); @@ -375,7 +255,7 @@ INT_PTR CALLBACK hc_uhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPa if (ret < 0) { MessageBox(hDlg, "Error initializing dialog", NULL, MB_ICONINFORMATION); } - + memset(u_changed, 0, sizeof(u_changed)); EnableWindow(GetDlgItem(hDlg, ID_APPLY), 0); @@ -438,14 +318,11 @@ INT_PTR CALLBACK hc_uhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPa break; } } - + return 0; } -#include "iodev/usb/uhci_core.h" -#include "iodev/usb/usb_uhci.h" - -extern bx_usb_uhci_c *theUSB_UHCI; +bx_list_c *UHCI_state = NULL; // returns -1 if error, else returns ID to control to set the focus to int hc_uhci_init(HWND hwnd) @@ -453,10 +330,11 @@ int hc_uhci_init(HWND hwnd) char str[COMMON_STR_SIZE]; Bit32u frame_addr, frame_num; int ret = IDOK; - - if (theUSB_UHCI == NULL) + + UHCI_state = (bx_list_c*)SIM->get_param("usb_uhci", SIM->get_bochs_root()); + if (UHCI_state == NULL) return -1; - + // set the dialog title to the break type switch (g_params.break_type) { case USB_DEBUG_FRAME: @@ -489,26 +367,26 @@ int hc_uhci_init(HWND hwnd) CheckDlgButton(hwnd, IDC_DEBUG_SOF, (SIM->get_param_num(BXPN_USB_DEBUG_START_FRAME)->get() > BX_USB_DEBUG_SOF_NONE) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwnd, IDC_DEBUG_NONEXIST, SIM->get_param_bool(BXPN_USB_DEBUG_NON_EXIST)->get() ? BST_CHECKED : BST_UNCHECKED); - pci_bar_address = theUSB_UHCI->get_bar_addr(4); + pci_bar_address = get_pci_bar_addr((bx_shadow_data_c*)SIM->get_param("hub.pci_conf", UHCI_state), 4); sprintf(str, "0x%04X", pci_bar_address); SetDlgItemText(hwnd, IDC_PORT_ADDR, str); - - sprintf(str, "0x%04X", theUSB_UHCI->read(pci_bar_address + 0, 2)); + + sprintf(str, "0x%04X", usb_io_read(pci_bar_address + 0, 2)); SetDlgItemText(hwnd, IDC_U_REG_COMMAND, str); - sprintf(str, "0x%04X", theUSB_UHCI->read(pci_bar_address + 2, 2)); + sprintf(str, "0x%04X", usb_io_read(pci_bar_address + 2, 2)); SetDlgItemText(hwnd, IDC_U_REG_STATUS, str); - sprintf(str, "0x%04X", theUSB_UHCI->read(pci_bar_address + 4, 2)); + sprintf(str, "0x%04X", usb_io_read(pci_bar_address + 4, 2)); SetDlgItemText(hwnd, IDC_U_REG_INTERRUPT, str); - sprintf(str, "0x%04X", frame_num = theUSB_UHCI->read(pci_bar_address + 6, 2)); + sprintf(str, "0x%04X", frame_num = usb_io_read(pci_bar_address + 6, 2)); SetDlgItemText(hwnd, IDC_U_REG_FRAME_NUM, str); - sprintf(str, "0x%08X", frame_addr = theUSB_UHCI->read(pci_bar_address + 8, 4)); + sprintf(str, "0x%08X", frame_addr = usb_io_read(pci_bar_address + 8, 4)); SetDlgItemText(hwnd, IDC_U_REG_FRAME_ADDRESS, str); - sprintf(str, "0x%02X", theUSB_UHCI->read(pci_bar_address + 12, 1)); + sprintf(str, "0x%02X", usb_io_read(pci_bar_address + 12, 1)); SetDlgItemText(hwnd, IDC_U_REG_SOF, str); - - sprintf(str, "0x%04X", theUSB_UHCI->read(pci_bar_address + 16, 2)); + + sprintf(str, "0x%04X", usb_io_read(pci_bar_address + 16, 2)); SetDlgItemText(hwnd, IDC_U_REG_PORT0, str); - sprintf(str, "0x%04X", theUSB_UHCI->read(pci_bar_address + 18, 2)); + sprintf(str, "0x%04X", usb_io_read(pci_bar_address + 18, 2)); SetDlgItemText(hwnd, IDC_U_REG_PORT1, str); // display the port types @@ -530,7 +408,7 @@ int hc_uhci_init(HWND hwnd) case USB_DEBUG_COMMAND: // The start of a frame timer was triggered case USB_DEBUG_FRAME: - SetDlgItemText(hwnd, IDC_RING_TYPE, "SOF Frame Address:"); + SetDlgItemText(hwnd, IDC_RING_TYPE, "SOF Frame Address"); if (frame_addr != 0x00000000) { hc_uhci_do_item(frame_addr, frame_num); EnableWindow(GetDlgItem(hwnd, IDC_VIEW_TD), TRUE); @@ -538,11 +416,11 @@ int hc_uhci_init(HWND hwnd) valid = 1; } break; - + // an event triggered. We ignore these in the uhci //case USB_DEBUG_EVENT: // break; - + // first byte (word, dword, qword) of first non-existant port was written to case USB_DEBUG_NONEXIST: // port reset (non-root reset) @@ -554,7 +432,7 @@ int hc_uhci_init(HWND hwnd) EnableWindow(GetDlgItem(hwnd, IDC_VIEW_TD), FALSE); break; } - + if (!valid) { TreeView_SetBkColor(TreeView, COLORREF(0x00A9A9A9)); SetDlgItemText(hwnd, IDC_TREE_COMMENT, "This trigger does not populate the TreeView"); @@ -568,65 +446,46 @@ int hc_uhci_save(HWND hwnd) { char str[COMMON_STR_SIZE]; - if (u_changed[IDC_U_REG_COMMAND - IDC_U_EN_START]) { + if (u_changed[UHCI_REG_COMMAND]) { GetDlgItemText(hwnd, IDC_U_REG_COMMAND, str, COMMON_STR_SIZE); - theUSB_UHCI->write(pci_bar_address + 0, strtol(str, NULL, 0), 2); + usb_io_write(pci_bar_address + 0, strtol(str, NULL, 0), 2); } - if (u_changed[IDC_U_REG_STATUS - IDC_U_EN_START]) { + if (u_changed[UHCI_REG_STATUS]) { GetDlgItemText(hwnd, IDC_U_REG_STATUS, str, COMMON_STR_SIZE); - theUSB_UHCI->write(pci_bar_address + 2, strtol(str, NULL, 0), 2); + usb_io_write(pci_bar_address + 2, strtol(str, NULL, 0), 2); } - if (u_changed[IDC_U_REG_INTERRUPT - IDC_U_EN_START]) { + if (u_changed[UHCI_REG_INTERRUPT]) { GetDlgItemText(hwnd, IDC_U_REG_INTERRUPT, str, COMMON_STR_SIZE); - theUSB_UHCI->write(pci_bar_address + 4, strtol(str, NULL, 0), 2); + usb_io_write(pci_bar_address + 4, strtol(str, NULL, 0), 2); } - if (u_changed[IDC_U_REG_FRAME_NUM - IDC_U_EN_START]) { + if (u_changed[UHCI_REG_FRAME_NUM]) { GetDlgItemText(hwnd, IDC_U_REG_FRAME_NUM, str, COMMON_STR_SIZE); - theUSB_UHCI->write(pci_bar_address + 6, strtol(str, NULL, 0), 2); + usb_io_write(pci_bar_address + 6, strtol(str, NULL, 0), 2); } - if (u_changed[IDC_U_REG_FRAME_ADDRESS - IDC_U_EN_START]) { + if (u_changed[UHCI_REG_FRAME_ADDR]) { GetDlgItemText(hwnd, IDC_U_REG_FRAME_ADDRESS, str, COMMON_STR_SIZE); - theUSB_UHCI->write(pci_bar_address + 8, strtol(str, NULL, 0), 4); + usb_io_write(pci_bar_address + 8, strtol(str, NULL, 0), 4); } - if (u_changed[IDC_U_REG_SOF - IDC_U_EN_START]) { + if (u_changed[UHCI_REG_SOF]) { GetDlgItemText(hwnd, IDC_U_REG_SOF, str, COMMON_STR_SIZE); - theUSB_UHCI->write(pci_bar_address + 12, strtol(str, NULL, 0), 1); + usb_io_write(pci_bar_address + 12, strtol(str, NULL, 0), 1); } - - if (u_changed[IDC_U_REG_PORT0 - IDC_U_EN_START]) { + + if (u_changed[UHCI_REG_PORT0]) { GetDlgItemText(hwnd, IDC_U_REG_PORT0, str, COMMON_STR_SIZE); - theUSB_UHCI->write(pci_bar_address + 16, strtol(str, NULL, 0), 2); + usb_io_write(pci_bar_address + 16, strtol(str, NULL, 0), 2); } - if (u_changed[IDC_U_REG_PORT1 - IDC_U_EN_START]) { + if (u_changed[UHCI_REG_PORT1]) { GetDlgItemText(hwnd, IDC_U_REG_PORT1, str, COMMON_STR_SIZE); - theUSB_UHCI->write(pci_bar_address + 18, strtol(str, NULL, 0), 2); + usb_io_write(pci_bar_address + 18, strtol(str, NULL, 0), 2); } - + memset(u_changed, 0, sizeof(u_changed)); EnableWindow(GetDlgItem(hwnd, ID_APPLY), 0); return 0; } -static bool uhci_add_queue(struct USB_UHCI_QUEUE_STACK *stack, const Bit32u addr) -{ - // check to see if this queue has been processed before - for (int i=0; iqueue_cnt; i++) { - if (stack->queue_stack[i] == addr) - return TRUE; - } - - // if the stack is full, we return TRUE anyway - if (stack->queue_cnt == USB_UHCI_QUEUE_STACK_SIZE) - return TRUE; - - // add the queue's address - stack->queue_stack[stack->queue_cnt] = addr; - stack->queue_cnt++; - - return FALSE; -} - void hc_uhci_do_item(Bit32u FrameAddr, Bit32u FrameNum) { struct USB_UHCI_QUEUE_STACK queue_stack; @@ -656,12 +515,12 @@ void hc_uhci_do_item(Bit32u FrameAddr, Bit32u FrameNum) // if this queue has been added before, stop. break; } - + // read in the queue DEV_MEM_READ_PHYSICAL(item & ~0xF, sizeof(struct QUEUE), (Bit8u *) &queue); sprintf(str, "0x%08X: Queue Head: (0x%08X 0x%08X)", item & ~0xF, queue.horz, queue.vert); Next = TreeViewInsert(TreeView, Next, TVI_LAST, str, (LPARAM) ((item & ~0xF) | 1), 0); - + // if the vert pointer is valid, there are td's in it to process // else only the head pointer may be valid if (!USB_UHCI_IS_LINK_VALID(queue.vert)) { @@ -708,7 +567,7 @@ void uhci_display_td(HWND hwnd) { TVITEM tvitem; INT_PTR ret = -1; Bit32u address = 0; - + HTREEITEM item = TreeView_GetSelection(TreeView); if (item != NULL) { tvitem.mask = TVIF_PARAM | TVIF_HANDLE; @@ -744,21 +603,21 @@ void uhci_display_td(HWND hwnd) { INT_PTR CALLBACK hc_uhci_callback_queue(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x%08X", g_queue.horz & ~0xF); SetDlgItemText(hDlg, IDC_HORZ_PTR, str); - + CheckDlgButton(hDlg, IDC_HORZ_Q, (g_queue.horz & 2) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_HORZ_T, (g_queue.horz & 1) ? BST_CHECKED : BST_UNCHECKED); - + sprintf(str, "0x%08X", g_queue.vert & ~0xF); SetDlgItemText(hDlg, IDC_VERT_PTR, str); - + CheckDlgButton(hDlg, IDC_VERT_Q, (g_queue.vert & 2) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_VERT_T, (g_queue.vert & 1) ? BST_CHECKED : BST_UNCHECKED); - + SetFocus(GetDlgItem(hDlg, IDOK)); return TRUE; case WM_COMMAND: @@ -771,13 +630,13 @@ INT_PTR CALLBACK hc_uhci_callback_queue(HWND hDlg, UINT msg, WPARAM wParam, LPAR g_queue.horz |= (IsDlgButtonChecked(hDlg, IDC_HORZ_Q) == BST_CHECKED) ? 2 : 0; g_queue.horz |= (IsDlgButtonChecked(hDlg, IDC_HORZ_T) == BST_CHECKED) ? 1 : 0; - + GetDlgItemText(hDlg, IDC_VERT_PTR, str, COMMON_STR_SIZE); g_queue.vert = strtol(str, NULL, 0); g_queue.vert |= (IsDlgButtonChecked(hDlg, IDC_VERT_Q) == BST_CHECKED) ? 2 : 0; g_queue.vert |= (IsDlgButtonChecked(hDlg, IDC_VERT_T) == BST_CHECKED) ? 1 : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -787,7 +646,7 @@ INT_PTR CALLBACK hc_uhci_callback_queue(HWND hDlg, UINT msg, WPARAM wParam, LPAR break; } } - + return 0; } @@ -808,7 +667,7 @@ INT_PTR CALLBACK hc_uhci_callback_td(HWND hDlg, UINT msg, WPARAM wParam, LPARAM sprintf(str, "0x%08X", g_td.dword0 & ~0xF); SetDlgItemText(hDlg, IDC_LINK_PTR, str); - + CheckDlgButton(hDlg, IDC_VERT_VF, (g_td.dword0 & 4) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_VERT_Q, (g_td.dword0 & 2) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_VERT_T, (g_td.dword0 & 1) ? BST_CHECKED : BST_UNCHECKED); @@ -847,7 +706,7 @@ INT_PTR CALLBACK hc_uhci_callback_td(HWND hDlg, UINT msg, WPARAM wParam, LPARAM ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_COMBO_PID), 2); else ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_COMBO_PID), 3); - + sprintf(str, "%i", (g_td.dword2 >> 8) & 0x7F); SetDlgItemText(hDlg, IDC_DEVICE_ADDR, str); sprintf(str, "%i", (g_td.dword2 >> 15) & 0x0F); @@ -857,7 +716,7 @@ INT_PTR CALLBACK hc_uhci_callback_td(HWND hDlg, UINT msg, WPARAM wParam, LPARAM sprintf(str, "0x%08X", g_td.dword3); SetDlgItemText(hDlg, IDC_DEVICE_BUFFER, str); - + SetFocus(GetDlgItem(hDlg, IDOK)); return TRUE; case WM_COMMAND: @@ -932,7 +791,7 @@ INT_PTR CALLBACK hc_uhci_callback_td(HWND hDlg, UINT msg, WPARAM wParam, LPARAM GetDlgItemText(hDlg, IDC_DEVICE_BUFFER, str, COMMON_STR_SIZE); g_td.dword3 = strtol(str, NULL, 0); - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -942,7 +801,7 @@ INT_PTR CALLBACK hc_uhci_callback_td(HWND hDlg, UINT msg, WPARAM wParam, LPARAM break; } } - + return 0; } @@ -985,44 +844,6 @@ int hc_ehci_init(HWND hwnd) /////////////////////////////////////////////////////////////////////////////////////////////// // XHCI // - -struct S_ATTRIBUTES attribs_x_ports[] = { - // | 31 chars + null | <- max - { (1ULL<<31), (1ULL<<31), 31, "Warm Port Reset" , {-1, } }, - { (1<<30), (1<<30), 30, "Device Removable" , {-1, } }, - { (1<<29), (1<<29), 29, "Reserved (bit 29)" , {-1, } }, - { (1<<28), (1<<28), 28, "Reserved (bit 28)" , {-1, } }, - { (1<<27), (1<<27), 27, "Wake on Over-current Enable" , {-1, } }, - { (1<<26), (1<<26), 26, "Wake on Disconnect Enable" , {-1, } }, - { (1<<25), (1<<25), 25, "Wake on Connect Enable" , {-1, } }, - { (1<<24), (1<<24), 24, "Cold Attach Status" , {-1, } }, - { (1<<23), (1<<23), 23, "Port Config Error Change" , {-1, } }, - { (1<<22), (1<<22), 22, "Port Link State Change" , {-1, } }, - { (1<<21), (1<<21), 21, "Port Reset Change" , {-1, } }, - { (1<<20), (1<<20), 20, "Over-current Change" , {-1, } }, - { (1<<19), (1<<19), 19, "Warm Port Reset Change" , {-1, } }, - { (1<<18), (1<<18), 18, "Port Enable/Disable Change" , {-1, } }, - { (1<<17), (1<<17), 17, "Connect Status Change" , {-1, } }, - { (1<<16), (1<<16), 16, "Port Link State Write Strobe" , {-1, } }, - { (1<<15), (1<<15), 15, "Port Indicator (bit 1)" , {-1, } }, - { (1<<14), (1<<14), 14, "Port Indicator (bit 0)" , {-1, } }, - { (1<<13), (1<<13), 13, "Port Speed (bit 3)" , {-1, } }, - { (1<<12), (1<<12), 12, "Port Speed (bit 2)" , {-1, } }, - { (1<<11), (1<<11), 11, "Port Speed (bit 1)" , {-1, } }, - { (1<<10), (1<<10), 10, "Port Speed (bit 0)" , {-1, } }, - { (1<< 9), (1<< 9), 9, "Port Power" , {-1, } }, - { (1<< 8), (1<< 8), 8, "Port Link State (bit 3)" , {-1, } }, - { (1<< 7), (1<< 7), 7, "Port Link State (bit 2)" , {-1, } }, - { (1<< 6), (1<< 6), 6, "Port Link State (bit 1)" , {-1, } }, - { (1<< 5), (1<< 5), 5, "Port Link State (bit 0)" , {-1, } }, - { (1<< 4), (1<< 4), 4, "Port Reset" , {-1, } }, - { (1<< 3), (1<< 3), 3, "Over-current Status" , {-1, } }, - { (1<< 2), (1<< 2), 2, "Reserved" , {-1, } }, - { (1<< 1), (1<< 1), 1, "Port Enabled/Disabled" , {-1, } }, - { (1<< 0), (1<< 0), 0, "Current Connect Status" , {-1, } }, - { 0, (DWORD) -1, -1, "\0" , {-1, } } -}; - static bool x_changed[IDC_X_EN_END - IDC_X_EN_START + 1]; // lParam: type is in low 8 bits, break_type in high 8-bits of low word @@ -1035,7 +856,7 @@ INT_PTR CALLBACK hc_xhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPa case WM_INITDIALOG: sprintf(str, "Bochs for Windows -- USB Debug: xHCI Host Controller"); SetWindowText(hDlg, str); - + // call the initializer TreeView = GetDlgItem(hDlg, IDC_STACK); SNDMSG(TreeView, WM_SETFONT, (WPARAM) hTreeViewFont, FALSE); @@ -1043,7 +864,7 @@ INT_PTR CALLBACK hc_xhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPa if (ret < 0) { MessageBox(hDlg, "Error initializing dialog", NULL, MB_ICONINFORMATION); } - + memset(x_changed, 0, sizeof(x_changed)); EnableWindow(GetDlgItem(hDlg, ID_APPLY), 0); @@ -1141,21 +962,13 @@ INT_PTR CALLBACK hc_xhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPa break; */ } - + return 0; } #include "iodev/usb/usb_xhci.h" -extern bx_usb_xhci_c *theUSB_XHCI; - -static Bit32u xhci_read_dword(const Bit32u address) -{ - Bit32u value; - - theUSB_XHCI->read_handler(address, 4, &value, NULL); - return value; -} +bx_list_c *XHCI_state = NULL; // returns -1 if error, else returns ID to control to set the focus to int hc_xhci_init(HWND hwnd) @@ -1167,7 +980,8 @@ int hc_xhci_init(HWND hwnd) unsigned i; int ret = IDOK; - if (theUSB_XHCI == NULL) + XHCI_state = (bx_list_c*)SIM->get_param("usb_xhci", SIM->get_bochs_root()); + if (XHCI_state == NULL) return -1; // set the dialog title to the break type @@ -1182,7 +996,7 @@ int hc_xhci_init(HWND hwnd) SetWindowText(hwnd, "xHCI Debug Dialog: Break Type: Frame"); break; } - + CheckDlgButton(hwnd, IDC_DEBUG_RESET, SIM->get_param_bool(BXPN_USB_DEBUG_RESET)->get() ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwnd, IDC_DEBUG_ENABLE, SIM->get_param_bool(BXPN_USB_DEBUG_ENABLE)->get() ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwnd, IDC_DEBUG_DOORBELL, SIM->get_param_bool(BXPN_USB_DEBUG_DOORBELL)->get() ? BST_CHECKED : BST_UNCHECKED); @@ -1190,10 +1004,10 @@ int hc_xhci_init(HWND hwnd) CheckDlgButton(hwnd, IDC_DEBUG_SOF, (SIM->get_param_num(BXPN_USB_DEBUG_START_FRAME)->get() > BX_USB_DEBUG_SOF_NONE) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwnd, IDC_DEBUG_NONEXIST, SIM->get_param_bool(BXPN_USB_DEBUG_NON_EXIST)->get() ? BST_CHECKED : BST_UNCHECKED); - pci_bar_address = theUSB_XHCI->get_bar_addr(0); + pci_bar_address = get_pci_bar_addr((bx_shadow_data_c*)SIM->get_param("hub.pci_conf", XHCI_state), 0); sprintf(str, "0x%08X", pci_bar_address); SetDlgItemText(hwnd, IDC_PORT_ADDR, str); - + for (i=0; i<8; i++) { dword = xhci_read_dword(pci_bar_address + (i * 4)); sprintf(str, "0x%08X", dword); @@ -1213,7 +1027,8 @@ int hc_xhci_init(HWND hwnd) dword = xhci_read_dword(pci_bar_address + offset + 0x14); sprintf(str, "0x%08X", dword); SetDlgItemText(hwnd, IDC_X_REG_DEVICE_NOTE, str); - sprintf(str, "0x" FMT_ADDRX64, theUSB_XHCI->hub.op_regs.HcCrcr.actual); // we can't read this using read_handler() since the handler will return zero + // we can't read this using DEV_MEM_READ_PHYSICAL since the handler will return zero + sprintf(str, "0x" FMT_ADDRX64, SIM->get_param_num("hub.op_regs.HcCrcr.actual", XHCI_state)->get64()); SetDlgItemText(hwnd, IDC_X_REG_COMMAND_RING, str); qword = xhci_read_dword(pci_bar_address + offset + 0x30) | ((Bit64u) xhci_read_dword(pci_bar_address + offset + 0x34) << 32); @@ -1222,14 +1037,14 @@ int hc_xhci_init(HWND hwnd) dword = xhci_read_dword(pci_bar_address + offset + 0x38); sprintf(str, "0x%08X", dword); SetDlgItemText(hwnd, IDC_X_REG_CONFIGURE, str); - + offset = xhci_read_dword(pci_bar_address + 0x18); dword = xhci_read_dword(pci_bar_address + offset + 0); sprintf(str, "0x%08X", dword); SetDlgItemText(hwnd, IDC_X_REG_MFINDEX, str); - + // show up to 10 port register sets - for (i=0; ihub.n_ports; i++) { + for (i = 0; i < (unsigned)SIM->get_param_num(BXPN_XHCI_N_PORTS)->get(); i++) { dword = xhci_read_dword(pci_bar_address + XHCI_PORT_SET_OFFSET + (i * 16)); sprintf(str, "0x%08X", dword); SetDlgItemText(hwnd, IDC_X_REG_PORT0 + i, str); @@ -1244,7 +1059,7 @@ int hc_xhci_init(HWND hwnd) EnableWindow(GetDlgItem(hwnd, IDC_X_REG_PORT0_ETYPE + i), 0); EnableWindow(GetDlgItem(hwnd, IDC_X_REG_PORT0_TYPE + i), 0); } - + tree_items = 0; TreeView_DeleteAllItems(TreeView); @@ -1253,16 +1068,16 @@ int hc_xhci_init(HWND hwnd) // a command TRB was placed on the command ring case USB_DEBUG_COMMAND: SetDlgItemText(hwnd, IDC_RING_TYPE, "Command Ring Address:"); - RingPtr = theUSB_XHCI->hub.op_regs.HcCrcr.crc; + RingPtr = SIM->get_param_num("hub.op_regs.HcCrcr.crc", XHCI_state)->get(); sprintf(str, "0x" FMT_ADDRX64, RingPtr); SetDlgItemText(hwnd, IDC_FRAME_ADDRESS, str); if (RingPtr != 0) { - hc_xhci_do_ring("Command", RingPtr, theUSB_XHCI->hub.ring_members.command_ring.dq_pointer); + hc_xhci_do_ring("Command", RingPtr, SIM->get_param_num("hub.ring_members.command_ring.dq_pointer", XHCI_state)->get()); EnableWindow(GetDlgItem(hwnd, IDC_VIEW_TRB), 1); valid = 1; } break; - + // an event TRB was placed on an event ring case USB_DEBUG_EVENT: SetDlgItemText(hwnd, IDC_RING_TYPE, "Event Ring:"); @@ -1272,13 +1087,13 @@ int hc_xhci_init(HWND hwnd) EnableWindow(GetDlgItem(hwnd, IDC_VIEW_TRB), 1); valid = 1; break; - + case USB_DEBUG_FRAME: - + SetDlgItemText(hwnd, IDC_RING_TYPE, "SOF Ring Address:"); break; - + // first byte (word, dword, qword) of first non-existant port was written to case USB_DEBUG_NONEXIST: SetDlgItemText(hwnd, IDC_RING_TYPE, "None"); @@ -1294,7 +1109,7 @@ int hc_xhci_init(HWND hwnd) EnableWindow(GetDlgItem(hwnd, IDC_VIEW_TRB), 0); valid = 0; break; - + // enable changed case USB_DEBUG_ENABLE: SetDlgItemText(hwnd, IDC_RING_TYPE, "None"); @@ -1303,7 +1118,7 @@ int hc_xhci_init(HWND hwnd) valid = 0; break; } - + if (!valid) { TreeView_SetBkColor(TreeView, COLORREF(0x00A9A9A9)); SetDlgItemText(hwnd, IDC_TREE_COMMENT, "This trigger does not populate the TreeView"); @@ -1315,9 +1130,9 @@ int hc_xhci_init(HWND hwnd) int hc_xhci_save(HWND hwnd) { - + MessageBox(hwnd, "xHCI: Save to controller is not yet implemented!", NULL, MB_ICONINFORMATION); - + return 0; } @@ -1402,7 +1217,7 @@ void hc_xhci_do_ring(const char *ring_str, Bit64u RingPtr, Bit64u dequeue_ptr) type = TRB_GET_TYPE(trb.command); if (type <= 47) sprintf(str, "0x" FMT_ADDRX64 " %08X 0x%08X (%i) (%s)", trb.parameter, trb.status, trb.command, trb.command & 1, trb_types[type].name); - else + else sprintf(str, "0x" FMT_ADDRX64 " %08X 0x%08X (%i) (Vendor Specific)", trb.parameter, trb.status, trb.command, trb.command & 1); if (address == dequeue_ptr) { strcat(str, " <--- dq_pointer"); @@ -1422,8 +1237,10 @@ void hc_xhci_do_ring(const char *ring_str, Bit64u RingPtr, Bit64u dequeue_ptr) void hc_xhci_do_event_ring(const char *ring_str, int interrupter) { char str[COMMON_STR_SIZE]; + char pname[BX_PATHNAME_LEN]; int trb_count = 0; // count of TRB's processed Bit64u address; + Bit32u size; struct TRB trb; HTREEITEM Parent, Segment; Bit32u state = 0; @@ -1432,19 +1249,23 @@ void hc_xhci_do_event_ring(const char *ring_str, int interrupter) sprintf(str, "%s Ring: Interrupter: %i", ring_str, interrupter); Parent = TreeViewInsert(TreeView, TVI_ROOT, TVI_FIRST, str, 0, 0); - for (unsigned i=0; i<(1<hub.ring_members.event_rings[interrupter].entrys[i].addr; - sprintf(str, "Event Ring Segment %i (0x" FMT_ADDRX64 "), size %i", i, address, theUSB_XHCI->hub.ring_members.event_rings[interrupter].entrys[i].size); + for (unsigned i = 0; i < (1 << MAX_SEG_TBL_SZ_EXP); i++) { + sprintf(pname, "hub.ring_members.event_rings.ring%d.entries.entry%d.addr", interrupter, i); + address = SIM->get_param_num(pname, XHCI_state)->get(); + sprintf(pname, "hub.ring_members.event_rings.ring%d.entries.entry%d.size", interrupter, i); + size = SIM->get_param_num(pname, XHCI_state)->get(); + sprintf(str, "Event Ring Segment %i (0x" FMT_ADDRX64 "), size %i", i, address, size); Segment = TreeViewInsert(TreeView, Parent, TVI_LAST, str, 0, 0); - for (unsigned j=0; jhub.ring_members.event_rings[interrupter].entrys[i].size; j++) { + for (unsigned j = 0; j < size; j++) { state = 0; // clear the state DEV_MEM_READ_PHYSICAL(address, sizeof(struct TRB), (Bit8u *) &trb); type = TRB_GET_TYPE(trb.command); if (type <= 47) sprintf(str, "0x" FMT_ADDRX64 " %08X 0x%08X (%i) (%s)", trb.parameter, trb.status, trb.command, trb.command & 1, trb_types[type].name); - else + else sprintf(str, "0x" FMT_ADDRX64 " %08X 0x%08X (%i) (Vendor Specific)", trb.parameter, trb.status, trb.command, trb.command & 1); - if (address == theUSB_XHCI->hub.ring_members.event_rings[interrupter].cur_trb) { + sprintf(pname, "hub.ring_members.event_rings.ring%d.cur_trb", interrupter); + if (address == (Bit64u)SIM->get_param_num(pname, XHCI_state)->get()) { strcat(str, " <--- eq_pointer"); state |= TVIS_BOLD; } @@ -1452,7 +1273,7 @@ void hc_xhci_do_event_ring(const char *ring_str, int interrupter) if (++trb_count > MAX_TRBS_ALLOWED) // safety catch break; - + address += sizeof(struct TRB); } if (trb_count > MAX_TRBS_ALLOWED) // safety catch @@ -1474,7 +1295,7 @@ void xhci_display_trb(HWND hwnd, int type_mask) { if (tvitem.lParam > 0) { DEV_MEM_READ_PHYSICAL(tvitem.lParam, sizeof(struct TRB), (Bit8u *) &g_trb); const Bit8u type = TRB_GET_TYPE(g_trb.command); - + // check to see if this type of TRB is allowed in this type of ring if ((type > 0) && (type <= 47) && ((trb_types[type].allowed_mask & type_mask) == 0)) { sprintf(str, "TRB type %i not allowed in a %s ring!", type, ring_type[type_mask]); @@ -1608,12 +1429,12 @@ void xhci_display_trb(HWND hwnd, int type_mask) { INT_PTR CALLBACK hc_xhci_callback_trb_normal(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter); SetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str); - + sprintf(str, "%i", TRB_GET_TARGET(g_trb.status)); SetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str); sprintf(str, "%i", TRB_GET_TX_LEN(g_trb.status)); @@ -1623,7 +1444,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_normal(HWND hDlg, UINT msg, WPARAM wParam, sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_BEI, TRB_DC(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_IDT, TRB_IS_IMMED_DATA(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_IOC, TRB_IOC(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); @@ -1649,7 +1470,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_normal(HWND hDlg, UINT msg, WPARAM wParam, g_trb.status |= TRB_SET_TDSIZE(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_TRANS_LEN, str, COMMON_STR_SIZE); g_trb.status |= strtol(str, NULL, 0) & 0x1FFFF; - + g_trb.command = (IsDlgButtonChecked(hDlg, IDC_TRB_BEI) == BST_CHECKED) ? (1<<9) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_IDT) == BST_CHECKED) ? (1<<6) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_IOC) == BST_CHECKED) ? (1<<5) : 0; @@ -1658,7 +1479,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_normal(HWND hDlg, UINT msg, WPARAM wParam, g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_ISP) == BST_CHECKED) ? (1<<2) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_ENT) == BST_CHECKED) ? (1<<1) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -1668,7 +1489,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_normal(HWND hDlg, UINT msg, WPARAM wParam, break; } } - + return 0; } @@ -1676,7 +1497,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_normal(HWND hDlg, UINT msg, WPARAM wParam, INT_PTR CALLBACK hc_xhci_callback_trb_setup(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x%04X", (Bit16u) ((g_trb.parameter & BX_CONST64(0x00000000000000FF)) >> 0)); @@ -1689,7 +1510,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_setup(HWND hDlg, UINT msg, WPARAM wParam, SetDlgItemText(hDlg, IDC_TRB_WINDEX, str); sprintf(str, "0x%04X", (Bit16u) ((g_trb.parameter & BX_CONST64(0xFFFF000000000000)) >> 48)); SetDlgItemText(hDlg, IDC_TRB_WLENGTH, str); - + sprintf(str, "%i", TRB_GET_TARGET(g_trb.status)); SetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str); sprintf(str, "%i", TRB_GET_TX_LEN(g_trb.status)); @@ -1699,7 +1520,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_setup(HWND hDlg, UINT msg, WPARAM wParam, SetDlgItemText(hDlg, IDC_TRB_TRT, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_IDT, TRB_IS_IMMED_DATA(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_IOC, TRB_IOC(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); @@ -1726,14 +1547,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_setup(HWND hDlg, UINT msg, WPARAM wParam, g_trb.status = (strtol(str, NULL, 0) & 0x3FF) << 22; GetDlgItemText(hDlg, IDC_TRB_TRANS_LEN, str, COMMON_STR_SIZE); g_trb.status |= strtol(str, NULL, 0) & 0x1FFFF; - + GetDlgItemText(hDlg, IDC_TRB_TRT, str, COMMON_STR_SIZE); g_trb.command = (strtol(str, NULL, 0) << 16) & 0x00030000; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_IDT) == BST_CHECKED) ? (1<<6) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_IOC) == BST_CHECKED) ? (1<<5) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -1743,7 +1564,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_setup(HWND hDlg, UINT msg, WPARAM wParam, break; } } - + return 0; } @@ -1751,12 +1572,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_setup(HWND hDlg, UINT msg, WPARAM wParam, INT_PTR CALLBACK hc_xhci_callback_trb_data(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter); SetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str); - + sprintf(str, "%i", TRB_GET_TARGET(g_trb.status)); SetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str); sprintf(str, "%i", TRB_GET_TX_LEN(g_trb.status)); @@ -1766,7 +1587,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_data(HWND hDlg, UINT msg, WPARAM wParam, L sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_DIR, (g_trb.command & 0x10000) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_IDT, TRB_IS_IMMED_DATA(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_IOC, TRB_IOC(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); @@ -1792,7 +1613,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_data(HWND hDlg, UINT msg, WPARAM wParam, L g_trb.status |= TRB_SET_TDSIZE(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_TRANS_LEN, str, COMMON_STR_SIZE); g_trb.status |= strtol(str, NULL, 0) & 0x1FFFF; - + g_trb.command = (IsDlgButtonChecked(hDlg, IDC_TRB_DIR) == BST_CHECKED) ? (1<<16) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_IDT) == BST_CHECKED) ? (1<<6) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_IOC) == BST_CHECKED) ? (1<<5) : 0; @@ -1801,7 +1622,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_data(HWND hDlg, UINT msg, WPARAM wParam, L g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_ISP) == BST_CHECKED) ? (1<<2) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_ENT) == BST_CHECKED) ? (1<<1) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -1811,7 +1632,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_data(HWND hDlg, UINT msg, WPARAM wParam, L break; } } - + return 0; } @@ -1819,7 +1640,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_data(HWND hDlg, UINT msg, WPARAM wParam, L INT_PTR CALLBACK hc_xhci_callback_trb_status(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", TRB_GET_TARGET(g_trb.status)); @@ -1827,7 +1648,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_status(HWND hDlg, UINT msg, WPARAM wParam, sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_DIR, (g_trb.command & 0x10000) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_IOC, TRB_IOC(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_CH, TRB_CHAIN(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); @@ -1845,13 +1666,13 @@ INT_PTR CALLBACK hc_xhci_callback_trb_status(HWND hDlg, UINT msg, WPARAM wParam, GetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str, COMMON_STR_SIZE); g_trb.status = (strtol(str, NULL, 0) & 0x3FF) << 22; - + g_trb.command = (IsDlgButtonChecked(hDlg, IDC_TRB_DIR) == BST_CHECKED) ? (1<<16) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_IOC) == BST_CHECKED) ? (1<<5) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_CH) == BST_CHECKED) ? (1<<4) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_ENT) == BST_CHECKED) ? (1<<1) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -1861,7 +1682,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_status(HWND hDlg, UINT msg, WPARAM wParam, break; } } - + return 0; } @@ -1869,18 +1690,18 @@ INT_PTR CALLBACK hc_xhci_callback_trb_status(HWND hDlg, UINT msg, WPARAM wParam, INT_PTR CALLBACK hc_xhci_callback_trb_link(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter & ~BX_CONST64(0x0F)); SetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str); - + sprintf(str, "%i", TRB_GET_TARGET(g_trb.status)); SetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_IOC, TRB_IOC(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_CH, TRB_CHAIN(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_TC, TRB_GET_TOGGLE(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); @@ -1898,12 +1719,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_link(HWND hDlg, UINT msg, WPARAM wParam, L GetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str, COMMON_STR_SIZE); g_trb.status = (strtol(str, NULL, 0) & 0x3FF) << 22; - + g_trb.command = (IsDlgButtonChecked(hDlg, IDC_TRB_IOC) == BST_CHECKED) ? (1<<5) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_CH) == BST_CHECKED) ? (1<<4) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_TC) == BST_CHECKED) ? (1<<1) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -1913,7 +1734,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_link(HWND hDlg, UINT msg, WPARAM wParam, L break; } } - + return 0; } @@ -1921,18 +1742,18 @@ INT_PTR CALLBACK hc_xhci_callback_trb_link(HWND hDlg, UINT msg, WPARAM wParam, L INT_PTR CALLBACK hc_xhci_callback_trb_event(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter); SetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str); - + sprintf(str, "%i", TRB_GET_TARGET(g_trb.status)); SetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_BEI, TRB_DC(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_IOC, TRB_IOC(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_CH, TRB_CHAIN(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); @@ -1951,13 +1772,13 @@ INT_PTR CALLBACK hc_xhci_callback_trb_event(HWND hDlg, UINT msg, WPARAM wParam, GetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str, COMMON_STR_SIZE); g_trb.status = (strtol(str, NULL, 0) & 0x3FF) << 22; - + g_trb.command = (IsDlgButtonChecked(hDlg, IDC_TRB_BEI) == BST_CHECKED) ? (1<<9) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_IOC) == BST_CHECKED) ? (1<<5) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_CH) == BST_CHECKED) ? (1<<4) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_ENT) == BST_CHECKED) ? (1<<1) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -1967,7 +1788,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_event(HWND hDlg, UINT msg, WPARAM wParam, break; } } - + return 0; } @@ -1975,7 +1796,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_event(HWND hDlg, UINT msg, WPARAM wParam, INT_PTR CALLBACK hc_xhci_callback_trb_noop(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", TRB_GET_TARGET(g_trb.status)); @@ -1983,7 +1804,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_noop(HWND hDlg, UINT msg, WPARAM wParam, L sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_IOC, TRB_IOC(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_CH, TRB_CHAIN(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_ENT, TRB_TOGGLE(g_trb.command) ? BST_CHECKED : BST_UNCHECKED); @@ -2000,12 +1821,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_noop(HWND hDlg, UINT msg, WPARAM wParam, L GetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str, COMMON_STR_SIZE); g_trb.status = (strtol(str, NULL, 0) & 0x3FF) << 22; - + g_trb.command = (IsDlgButtonChecked(hDlg, IDC_TRB_IOC) == BST_CHECKED) ? (1<<5) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_CH) == BST_CHECKED) ? (1<<4) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_ENT) == BST_CHECKED) ? (1<<1) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2015,7 +1836,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_noop(HWND hDlg, UINT msg, WPARAM wParam, L break; } } - + return 0; } @@ -2023,14 +1844,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_noop(HWND hDlg, UINT msg, WPARAM wParam, L INT_PTR CALLBACK hc_xhci_callback_trb_enslot(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", TRB_GET_STYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_SLOT_TYPE, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2042,11 +1863,11 @@ INT_PTR CALLBACK hc_xhci_callback_trb_enslot(HWND hDlg, UINT msg, WPARAM wParam, case IDOK: g_trb.parameter = 0; g_trb.status = 0; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_TYPE, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_STYPE(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2056,7 +1877,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_enslot(HWND hDlg, UINT msg, WPARAM wParam, break; } } - + return 0; } @@ -2064,14 +1885,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_enslot(HWND hDlg, UINT msg, WPARAM wParam, INT_PTR CALLBACK hc_xhci_callback_trb_disslot(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", TRB_GET_SLOT(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); // if this is the Negotiate Bandwidth Command, we need to change the title @@ -2087,11 +1908,11 @@ INT_PTR CALLBACK hc_xhci_callback_trb_disslot(HWND hDlg, UINT msg, WPARAM wParam case IDOK: g_trb.parameter = 0; g_trb.status = 0; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2101,7 +1922,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_disslot(HWND hDlg, UINT msg, WPARAM wParam break; } } - + return 0; } @@ -2120,7 +1941,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_address(HWND hDlg, UINT msg, WPARAM wParam SetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_BSR, (g_trb.command & (1<<9)) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); @@ -2140,12 +1961,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_address(HWND hDlg, UINT msg, WPARAM wParam g_trb.parameter = strtol(str, NULL, 0) & ~BX_CONST64(0x0F); g_trb.status = 0; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_BSR) == BST_CHECKED) ? (1<<9) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2155,7 +1976,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_address(HWND hDlg, UINT msg, WPARAM wParam break; } } - + return 0; } @@ -2164,7 +1985,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_configep(HWND hDlg, UINT msg, WPARAM wPara { char str[COMMON_STR_SIZE]; Bit64u address; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter & ~BX_CONST64(0x0F)); @@ -2174,7 +1995,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_configep(HWND hDlg, UINT msg, WPARAM wPara SetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_DECONFIG, (g_trb.command & (1<<9)) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); @@ -2194,12 +2015,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_configep(HWND hDlg, UINT msg, WPARAM wPara g_trb.parameter = strtol(str, NULL, 0) & ~BX_CONST64(0x0F); g_trb.status = 0; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_DECONFIG) == BST_CHECKED) ? (1<<9) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2209,7 +2030,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_configep(HWND hDlg, UINT msg, WPARAM wPara break; } } - + return 0; } @@ -2218,7 +2039,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_evaluate(HWND hDlg, UINT msg, WPARAM wPara { char str[COMMON_STR_SIZE]; Bit64u address; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter & ~BX_CONST64(0x0F)); @@ -2228,7 +2049,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_evaluate(HWND hDlg, UINT msg, WPARAM wPara SetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_BSR, (g_trb.command & (1<<9)) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); @@ -2248,12 +2069,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_evaluate(HWND hDlg, UINT msg, WPARAM wPara g_trb.parameter = strtol(str, NULL, 0) & ~BX_CONST64(0x0F); g_trb.status = 0; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); //g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_BSR) == BST_CHECKED) ? (1<<9) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2263,7 +2084,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_evaluate(HWND hDlg, UINT msg, WPARAM wPara break; } } - + return 0; } @@ -2271,7 +2092,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_evaluate(HWND hDlg, UINT msg, WPARAM wPara INT_PTR CALLBACK hc_xhci_callback_trb_resetep(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", TRB_GET_SLOT(g_trb.command)); @@ -2280,7 +2101,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_resetep(HWND hDlg, UINT msg, WPARAM wParam SetDlgItemText(hDlg, IDC_TRB_EP_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_TSP, (g_trb.command & (1<<9)) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); @@ -2293,14 +2114,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_resetep(HWND hDlg, UINT msg, WPARAM wParam case IDOK: g_trb.parameter = 0; g_trb.status = 0; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_EP_ID, str, COMMON_STR_SIZE); g_trb.command |= TRB_SET_EP(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_TSP) == BST_CHECKED) ? (1<<9) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2310,7 +2131,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_resetep(HWND hDlg, UINT msg, WPARAM wParam break; } } - + return 0; } @@ -2318,7 +2139,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_resetep(HWND hDlg, UINT msg, WPARAM wParam INT_PTR CALLBACK hc_xhci_callback_trb_stopep(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", TRB_GET_SLOT(g_trb.command)); @@ -2327,7 +2148,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_stopep(HWND hDlg, UINT msg, WPARAM wParam, SetDlgItemText(hDlg, IDC_TRB_EP_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_SP, (g_trb.command & (1<<23)) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); @@ -2340,14 +2161,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_stopep(HWND hDlg, UINT msg, WPARAM wParam, case IDOK: g_trb.parameter = 0; g_trb.status = 0; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_EP_ID, str, COMMON_STR_SIZE); g_trb.command |= TRB_SET_EP(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_SP) == BST_CHECKED) ? (1<<23) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2357,7 +2178,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_stopep(HWND hDlg, UINT msg, WPARAM wParam, break; } } - + return 0; } @@ -2365,12 +2186,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_stopep(HWND hDlg, UINT msg, WPARAM wParam, INT_PTR CALLBACK hc_xhci_callback_trb_settrptr(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter & ~BX_CONST64(0x0F)); SetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str); - + sprintf(str, "%i", TRB_GET_STREAM(g_trb.status)); SetDlgItemText(hDlg, IDC_TRB_STREAMID, str); @@ -2380,7 +2201,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_settrptr(HWND hDlg, UINT msg, WPARAM wPara SetDlgItemText(hDlg, IDC_TRB_EP_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2395,13 +2216,13 @@ INT_PTR CALLBACK hc_xhci_callback_trb_settrptr(HWND hDlg, UINT msg, WPARAM wPara GetDlgItemText(hDlg, IDC_TRB_STREAMID, str, COMMON_STR_SIZE); g_trb.status = (strtol(str, NULL, 0) & 0xFFFF) << 16; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_EP_ID, str, COMMON_STR_SIZE); g_trb.command |= TRB_SET_EP(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2411,7 +2232,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_settrptr(HWND hDlg, UINT msg, WPARAM wPara break; } } - + return 0; } @@ -2419,14 +2240,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_settrptr(HWND hDlg, UINT msg, WPARAM wPara INT_PTR CALLBACK hc_xhci_callback_trb_resetdev(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", TRB_GET_SLOT(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); // if this is the NoOp Command, we need to change the title @@ -2442,11 +2263,11 @@ INT_PTR CALLBACK hc_xhci_callback_trb_resetdev(HWND hDlg, UINT msg, WPARAM wPara case IDOK: g_trb.parameter = 0; g_trb.status = 0; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2456,7 +2277,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_resetdev(HWND hDlg, UINT msg, WPARAM wPara break; } } - + return 0; } @@ -2464,20 +2285,20 @@ INT_PTR CALLBACK hc_xhci_callback_trb_resetdev(HWND hDlg, UINT msg, WPARAM wPara INT_PTR CALLBACK hc_xhci_callback_trb_forceevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter & ~BX_CONST64(0x0F)); SetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str); - + sprintf(str, "%i", TRB_GET_TARGET(g_trb.status)); SetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str); - + sprintf(str, "%i", (g_trb.command & (0xFF << 16)) >> 16); SetDlgItemText(hDlg, IDC_TRB_VF_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2492,11 +2313,11 @@ INT_PTR CALLBACK hc_xhci_callback_trb_forceevent(HWND hDlg, UINT msg, WPARAM wPa GetDlgItemText(hDlg, IDC_TRB_INT_TARGET, str, COMMON_STR_SIZE); g_trb.status = (strtol(str, NULL, 0) & 0x3FF) << 22; - + GetDlgItemText(hDlg, IDC_TRB_VF_ID, str, COMMON_STR_SIZE); g_trb.command = (strtol(str, NULL, 0) & 0xFF) << 16; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2506,7 +2327,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_forceevent(HWND hDlg, UINT msg, WPARAM wPa break; } } - + return 0; } @@ -2514,14 +2335,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_forceevent(HWND hDlg, UINT msg, WPARAM wPa INT_PTR CALLBACK hc_xhci_callback_trb_setlat(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", (g_trb.command & (0xFFF << 16)) >> 16); SetDlgItemText(hDlg, IDC_TRB_BELT, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2533,11 +2354,11 @@ INT_PTR CALLBACK hc_xhci_callback_trb_setlat(HWND hDlg, UINT msg, WPARAM wParam, case IDOK: g_trb.parameter = 0; g_trb.status = 0; - + GetDlgItemText(hDlg, IDC_TRB_BELT, str, COMMON_STR_SIZE); g_trb.command = (strtol(str, NULL, 0) & 0xFFF) << 16; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2547,7 +2368,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_setlat(HWND hDlg, UINT msg, WPARAM wParam, break; } } - + return 0; } @@ -2555,7 +2376,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_setlat(HWND hDlg, UINT msg, WPARAM wParam, INT_PTR CALLBACK hc_xhci_callback_trb_getband(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter & ~BX_CONST64(0x0F)); @@ -2567,7 +2388,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_getband(HWND hDlg, UINT msg, WPARAM wParam SetDlgItemText(hDlg, IDC_TRB_DEV_SPEED, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2579,15 +2400,15 @@ INT_PTR CALLBACK hc_xhci_callback_trb_getband(HWND hDlg, UINT msg, WPARAM wParam case IDOK: GetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str, COMMON_STR_SIZE); g_trb.parameter = strtol(str, NULL, 0) & ~BX_CONST64(0x0F); - + g_trb.status = 0; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_DEV_SPEED, str, COMMON_STR_SIZE); g_trb.command |= (strtol(str, NULL, 0) & 0x0F) << 16; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2597,7 +2418,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_getband(HWND hDlg, UINT msg, WPARAM wParam break; } } - + return 0; } @@ -2605,7 +2426,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_getband(HWND hDlg, UINT msg, WPARAM wParam INT_PTR CALLBACK hc_xhci_callback_trb_forcehdr(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter & ~BX_CONST64(0x1F)); @@ -2618,7 +2439,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_forcehdr(HWND hDlg, UINT msg, WPARAM wPara SetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2630,14 +2451,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_forcehdr(HWND hDlg, UINT msg, WPARAM wPara case IDOK: GetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str, COMMON_STR_SIZE); g_trb.parameter = strtol(str, NULL, 0) & ~BX_CONST64(0x1F); - + GetDlgItemText(hDlg, IDC_TRB_HDR_HI, str, COMMON_STR_SIZE); g_trb.status = strtol(str, NULL, 0); - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2647,7 +2468,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_forcehdr(HWND hDlg, UINT msg, WPARAM wPara break; } } - + return 0; } @@ -2655,7 +2476,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_forcehdr(HWND hDlg, UINT msg, WPARAM wPara INT_PTR CALLBACK hc_xhci_callback_trb_transevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter); @@ -2670,7 +2491,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_transevent(HWND hDlg, UINT msg, WPARAM wPa SetDlgItemText(hDlg, IDC_TRB_EP_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_ED, (g_trb.command & 4) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); @@ -2683,17 +2504,17 @@ INT_PTR CALLBACK hc_xhci_callback_trb_transevent(HWND hDlg, UINT msg, WPARAM wPa case IDOK: GetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str, COMMON_STR_SIZE); g_trb.parameter = strtol(str, NULL, 0); - + GetDlgItemText(hDlg, IDC_TRB_COMP_CODE, str, COMMON_STR_SIZE); g_trb.status = TRB_SET_COMP_CODE(strtol(str, NULL, 0)); - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_EP_ID, str, COMMON_STR_SIZE); g_trb.command |= TRB_SET_EP(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_ED) == BST_CHECKED) ? (1<<2) : 0; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2703,7 +2524,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_transevent(HWND hDlg, UINT msg, WPARAM wPa break; } } - + return 0; } @@ -2711,7 +2532,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_transevent(HWND hDlg, UINT msg, WPARAM wPa INT_PTR CALLBACK hc_xhci_callback_trb_compcompletion(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter); @@ -2728,7 +2549,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_compcompletion(HWND hDlg, UINT msg, WPARAM SetDlgItemText(hDlg, IDC_TRB_VF_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2740,18 +2561,18 @@ INT_PTR CALLBACK hc_xhci_callback_trb_compcompletion(HWND hDlg, UINT msg, WPARAM case IDOK: GetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str, COMMON_STR_SIZE); g_trb.parameter = strtol(str, NULL, 0); - + GetDlgItemText(hDlg, IDC_TRB_COMP_CODE, str, COMMON_STR_SIZE); g_trb.status = TRB_SET_COMP_CODE(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_COMP_LPARAM, str, COMMON_STR_SIZE); g_trb.status |= strtol(str, NULL, 0) & 0x00FFFFFF; - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_VF_ID, str, COMMON_STR_SIZE); g_trb.command |= (strtol(str, NULL, 0) & 0xFF) << 16; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2761,7 +2582,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_compcompletion(HWND hDlg, UINT msg, WPARAM break; } } - + return 0; } @@ -2769,7 +2590,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_compcompletion(HWND hDlg, UINT msg, WPARAM INT_PTR CALLBACK hc_xhci_callback_trb_pschange(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, (g_trb.parameter & BX_CONST64(0x00000000FF000000)) >> 24); @@ -2780,7 +2601,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_pschange(HWND hDlg, UINT msg, WPARAM wPara sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2792,12 +2613,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_pschange(HWND hDlg, UINT msg, WPARAM wPara case IDOK: GetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str, COMMON_STR_SIZE); g_trb.parameter = (Bit64u) (strtol(str, NULL, 0) & 0xFF) << 24; - + GetDlgItemText(hDlg, IDC_TRB_COMP_CODE, str, COMMON_STR_SIZE); g_trb.status = TRB_SET_COMP_CODE(strtol(str, NULL, 0)); - + g_trb.command = (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2807,7 +2628,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_pschange(HWND hDlg, UINT msg, WPARAM wPara break; } } - + return 0; } @@ -2815,7 +2636,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_pschange(HWND hDlg, UINT msg, WPARAM wPara INT_PTR CALLBACK hc_xhci_callback_trb_bandrequ(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", TRB_GET_COMP_CODE(g_trb.status)); @@ -2825,7 +2646,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_bandrequ(HWND hDlg, UINT msg, WPARAM wPara SetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2836,14 +2657,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_bandrequ(HWND hDlg, UINT msg, WPARAM wPara switch (LOWORD(wParam)) { case IDOK: g_trb.parameter = 0; - + GetDlgItemText(hDlg, IDC_TRB_COMP_CODE, str, COMMON_STR_SIZE); g_trb.status = TRB_SET_COMP_CODE(strtol(str, NULL, 0)); - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2853,7 +2674,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_bandrequ(HWND hDlg, UINT msg, WPARAM wPara break; } } - + return 0; } @@ -2861,12 +2682,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_bandrequ(HWND hDlg, UINT msg, WPARAM wPara INT_PTR CALLBACK hc_xhci_callback_trb_doorbell(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter & 0x1F); SetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str); - + sprintf(str, "%i", TRB_GET_COMP_CODE(g_trb.status)); SetDlgItemText(hDlg, IDC_TRB_COMP_CODE, str); @@ -2876,7 +2697,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_doorbell(HWND hDlg, UINT msg, WPARAM wPara SetDlgItemText(hDlg, IDC_TRB_VF_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2888,16 +2709,16 @@ INT_PTR CALLBACK hc_xhci_callback_trb_doorbell(HWND hDlg, UINT msg, WPARAM wPara case IDOK: GetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str, COMMON_STR_SIZE); g_trb.parameter = strtol(str, NULL, 0) & 0x1F; - + GetDlgItemText(hDlg, IDC_TRB_COMP_CODE, str, COMMON_STR_SIZE); g_trb.status = TRB_SET_COMP_CODE(strtol(str, NULL, 0)); - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_VF_ID, str, COMMON_STR_SIZE); g_trb.command |= (strtol(str, NULL, 0) & 0xFF) << 16; g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2907,7 +2728,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_doorbell(HWND hDlg, UINT msg, WPARAM wPara break; } } - + return 0; } @@ -2915,7 +2736,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_doorbell(HWND hDlg, UINT msg, WPARAM wPara INT_PTR CALLBACK hc_xhci_callback_trb_hostevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", TRB_GET_COMP_CODE(g_trb.status)); @@ -2923,7 +2744,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_hostevent(HWND hDlg, UINT msg, WPARAM wPar sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); // if this is the MFINDEX Wrap Event, we need to change the title @@ -2938,12 +2759,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_hostevent(HWND hDlg, UINT msg, WPARAM wPar switch (LOWORD(wParam)) { case IDOK: g_trb.parameter = 0; - + GetDlgItemText(hDlg, IDC_TRB_COMP_CODE, str, COMMON_STR_SIZE); g_trb.status = TRB_SET_COMP_CODE(strtol(str, NULL, 0)); - + g_trb.command = (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -2953,7 +2774,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_hostevent(HWND hDlg, UINT msg, WPARAM wPar break; } } - + return 0; } @@ -2961,14 +2782,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_hostevent(HWND hDlg, UINT msg, WPARAM wPar INT_PTR CALLBACK hc_xhci_callback_trb_devnotevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter >> 8); SetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str); sprintf(str, "%i", (Bit8u) (g_trb.parameter & 0xF0) >> 4); SetDlgItemText(hDlg, IDC_TRB_NOT_TYPE, str); - + sprintf(str, "%i", TRB_GET_COMP_CODE(g_trb.status)); SetDlgItemText(hDlg, IDC_TRB_COMP_CODE, str); @@ -2976,7 +2797,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_devnotevent(HWND hDlg, UINT msg, WPARAM wP SetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -2990,14 +2811,14 @@ INT_PTR CALLBACK hc_xhci_callback_trb_devnotevent(HWND hDlg, UINT msg, WPARAM wP g_trb.parameter = (Bit64u) strtol(str, NULL, 0) << 8; GetDlgItemText(hDlg, IDC_TRB_NOT_TYPE, str, COMMON_STR_SIZE); g_trb.parameter |= (strtol(str, NULL, 0) & 0xF) << 4; - + GetDlgItemText(hDlg, IDC_TRB_COMP_CODE, str, COMMON_STR_SIZE); g_trb.status = TRB_SET_COMP_CODE(strtol(str, NULL, 0)); - + GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command = TRB_SET_SLOT(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -3007,7 +2828,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_devnotevent(HWND hDlg, UINT msg, WPARAM wP break; } } - + return 0; } @@ -3015,12 +2836,12 @@ INT_PTR CALLBACK hc_xhci_callback_trb_devnotevent(HWND hDlg, UINT msg, WPARAM wP INT_PTR CALLBACK hc_xhci_callback_trb_necfw(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -3033,9 +2854,9 @@ INT_PTR CALLBACK hc_xhci_callback_trb_necfw(HWND hDlg, UINT msg, WPARAM wParam, g_trb.parameter = 0; g_trb.status = 0; - + g_trb.command = (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -3045,7 +2866,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_necfw(HWND hDlg, UINT msg, WPARAM wParam, break; } } - + return 0; } @@ -3053,15 +2874,15 @@ INT_PTR CALLBACK hc_xhci_callback_trb_necfw(HWND hDlg, UINT msg, WPARAM wParam, INT_PTR CALLBACK hc_xhci_callback_trb_necun(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter); SetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str); - + sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -3073,11 +2894,11 @@ INT_PTR CALLBACK hc_xhci_callback_trb_necun(HWND hDlg, UINT msg, WPARAM wParam, case IDOK: GetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str, COMMON_STR_SIZE); g_trb.parameter = strtol(str, NULL, 0); - + g_trb.status = 0; - + g_trb.command = (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -3087,7 +2908,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_necun(HWND hDlg, UINT msg, WPARAM wParam, break; } } - + return 0; } @@ -3095,7 +2916,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_necun(HWND hDlg, UINT msg, WPARAM wParam, INT_PTR CALLBACK hc_xhci_callback_trb_necfwevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { char str[COMMON_STR_SIZE]; - + switch (msg) { case WM_INITDIALOG: sprintf(str, "0x" FMT_ADDRX64, g_trb.parameter); @@ -3112,7 +2933,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_necfwevent(HWND hDlg, UINT msg, WPARAM wPa SetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str); sprintf(str, "%i", TRB_GET_TYPE(g_trb.command)); SetDlgItemText(hDlg, IDC_TRB_TYPE, str); - + CheckDlgButton(hDlg, IDC_TRB_C, (g_trb.command & 1) ? BST_CHECKED : BST_UNCHECKED); SetFocus(GetDlgItem(hDlg, IDOK)); @@ -3124,18 +2945,18 @@ INT_PTR CALLBACK hc_xhci_callback_trb_necfwevent(HWND hDlg, UINT msg, WPARAM wPa case IDOK: GetDlgItemText(hDlg, IDC_TRB_DATA_PTR, str, COMMON_STR_SIZE); g_trb.parameter = strtol(str, NULL, 0); - + GetDlgItemText(hDlg, IDC_TRB_COMP_CODE, str, COMMON_STR_SIZE); g_trb.status = TRB_SET_COMP_CODE(strtol(str, NULL, 0)); GetDlgItemText(hDlg, IDC_TRB_COMP_LPARAM, str, COMMON_STR_SIZE); g_trb.status |= strtol(str, NULL, 0) & 0x0000FFFF; - + GetDlgItemText(hDlg, IDC_TRB_COMP_HPARAM, str, COMMON_STR_SIZE); g_trb.command = (strtol(str, NULL, 0) & 0x0000FFFF) << 16; GetDlgItemText(hDlg, IDC_TRB_SLOT_ID, str, COMMON_STR_SIZE); g_trb.command |= TRB_SET_SLOT(strtol(str, NULL, 0)); g_trb.command |= (IsDlgButtonChecked(hDlg, IDC_TRB_C) == BST_CHECKED) ? (1<<0) : 0; - + EndDialog(hDlg, 1); break; case IDCANCEL: @@ -3145,7 +2966,7 @@ INT_PTR CALLBACK hc_xhci_callback_trb_necfwevent(HWND hDlg, UINT msg, WPARAM wPa break; } } - + return 0; } @@ -3230,7 +3051,7 @@ static void hc_xhci_callback_context_ep_get(HWND hDlg) char str[COMMON_STR_SIZE]; Bit32u *p; int i; - + // display the EP (with Drop and Add bits) p = (Bit32u *) &xhci_context[0]; if (xhci_current_ep_context == 1) { @@ -3243,7 +3064,7 @@ static void hc_xhci_callback_context_ep_get(HWND hDlg) if (p[1] & (1 << xhci_current_ep_context)) strcat(str, "(A)"); SetDlgItemText(hDlg, IDC_CONTEXT_OF_STR, str); - + // EP Context p = (Bit32u *) &xhci_context[CONTEXT_SIZE + (xhci_current_ep_context * CONTEXT_SIZE)]; sprintf(str, "%i", (p[0] & (0xFF << 24)) >> 24); @@ -3273,9 +3094,9 @@ static void hc_xhci_callback_context_ep_get(HWND hDlg) SetDlgItemText(hDlg, IDC_CONTEXT_MAX_ESIT_LO, str); sprintf(str, "%i", (p[4] & (0xFFFF << 0)) >> 0); SetDlgItemText(hDlg, IDC_CONTEXT_AVERAGE_LEN, str); - + EnableWindow(GetDlgItem(hDlg, IDC_CONTEXT_STREAM_CONTEXT), (((p[0] & (0x1F << 10)) >> 10) > 0)); - + for (i=0; i<3; i++) { sprintf(str, "0x%08X", p[5+i]); SetDlgItemText(hDlg, IDC_CONTEXT_RSVDO_EP_0 + i, str); @@ -3287,7 +3108,7 @@ static void hc_xhci_callback_context_ep_get(HWND hDlg) EnableWindow(GetDlgItem(hDlg, IDC_CONTEXT_RSVDO_EP_0 + i), 1); } #endif - + xhci_context_changed = 0; EnableWindow(GetDlgItem(hDlg, ID_APPLY), 0); } @@ -3297,7 +3118,7 @@ static void hc_xhci_callback_context_ep_put(HWND hDlg) char str[COMMON_STR_SIZE]; Bit32u *p; int i; - + // EP Context p = (Bit32u *) &xhci_context[CONTEXT_SIZE + (xhci_current_ep_context * CONTEXT_SIZE)]; GetDlgItemText(hDlg, IDC_CONTEXT_MAX_ESIT_HI, str, COMMON_STR_SIZE); @@ -3411,7 +3232,7 @@ INT_PTR CALLBACK hc_xhci_callback_context(HWND hDlg, UINT msg, WPARAM wParam, LP EnableWindow(GetDlgItem(hDlg, IDC_CONTEXT_RSVDO_SLOT_0 + i), 1); } #endif - + // Endpoint Context hc_xhci_callback_context_ep_get(hDlg); @@ -3510,7 +3331,7 @@ INT_PTR CALLBACK hc_xhci_callback_context(HWND hDlg, UINT msg, WPARAM wParam, LP else if (ret == IDCANCEL) break; } - + // Context structure p = (Bit32u *) &xhci_context[0]; GetDlgItemText(hDlg, IDC_CONTEXT_DROP, str, COMMON_STR_SIZE); @@ -3564,7 +3385,7 @@ INT_PTR CALLBACK hc_xhci_callback_context(HWND hDlg, UINT msg, WPARAM wParam, LP } #endif DEV_MEM_WRITE_PHYSICAL(xhci_context_address, CONTEXT_SIZE + (32 * CONTEXT_SIZE), xhci_context); - + delete [] xhci_context; EndDialog(hDlg, 1); break; @@ -3619,7 +3440,7 @@ INT_PTR CALLBACK hc_xhci_callback_context(HWND hDlg, UINT msg, WPARAM wParam, LP break; } } - + return 0; } @@ -3633,7 +3454,7 @@ static void CALLBACK hc_xhci_callback_str_context_get(HWND hDlg) if (xhci_str_current_context == 0) strcat(str, "(Reserved)"); SetDlgItemText(hDlg, IDC_CONTEXT_OF_STR, str); - + // String Context p = (Bit32u *) &xhci_str_context[xhci_str_current_context * 32]; sprintf(str, "0x" FMT_ADDRX64, ((Bit64u) p[1] << 32) | (p[0] & ~BX_CONST64(0xF))); @@ -3647,7 +3468,7 @@ static void CALLBACK hc_xhci_callback_str_context_get(HWND hDlg) SetDlgItemText(hDlg, IDC_STR_CONTEXT_RSVDO_0, str); sprintf(str, "0x%08X", p[3]); SetDlgItemText(hDlg, IDC_STR_CONTEXT_RSVDO_1, str); - + xhci_str_context_changed = 0; EnableWindow(GetDlgItem(hDlg, ID_APPLY), 0); } @@ -3671,7 +3492,7 @@ static void CALLBACK hc_xhci_callback_str_context_put(HWND hDlg) p[1] |= (strtol(str, NULL, 0) & 0xFF) << 24; GetDlgItemText(hDlg, IDC_STR_CONTEXT_RSVDO_1, str, COMMON_STR_SIZE); p[2] = strtol(str, NULL, 0); - + xhci_str_context_changed = 0; EnableWindow(GetDlgItem(hDlg, ID_APPLY), 0); } @@ -3681,7 +3502,7 @@ INT_PTR CALLBACK hc_xhci_callback_str_context(HWND hDlg, UINT msg, WPARAM wParam { char str[COMMON_STR_SIZE]; int i; - + switch (msg) { case WM_INITDIALOG: xhci_str_current_context = 0; @@ -3736,9 +3557,9 @@ INT_PTR CALLBACK hc_xhci_callback_str_context(HWND hDlg, UINT msg, WPARAM wParam else if (ret == IDCANCEL) break; } - + DEV_MEM_WRITE_PHYSICAL(xhci_str_context_address, MAX_PSA_SIZE_NUM * 32, xhci_str_context); - + delete [] xhci_str_context; EndDialog(hDlg, 1); break; @@ -3764,7 +3585,7 @@ INT_PTR CALLBACK hc_xhci_callback_str_context(HWND hDlg, UINT msg, WPARAM wParam break; } } - + return 0; } @@ -3807,7 +3628,7 @@ static INT_PTR CALLBACK attribute_callback(HWND hDlg, UINT msg, WPARAM wParam, L // no need to show the caption if no 'single-only' entries ShowWindow(GetDlgItem(hDlg, IDC_CAPTION), bCaption); break; - + case WM_COMMAND: switch (HIWORD(wParam)) { case BN_CLICKED: @@ -3826,7 +3647,7 @@ static INT_PTR CALLBACK attribute_callback(HWND hDlg, UINT msg, WPARAM wParam, L break; } break; - + case LBN_SELCHANGE: i = ListBox_GetCaretIndex(ListBox); // index to just clicked item if (ListBox_GetSel(ListBox, i)) { diff --git a/bochs/gui/win32usb.h b/bochs/gui/win32usb.h index bf29eac621..5e27b786d1 100644 --- a/bochs/gui/win32usb.h +++ b/bochs/gui/win32usb.h @@ -1,161 +1,130 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2023 Benjamin David Lunt -// Copyright (C) 2003-2021 The Bochs Project -// -// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -#ifndef BX_WIN32_USB_H -#define BX_WIN32_USB_H - -#if BX_USE_WIN32USBDEBUG - -#define COMMON_STR_SIZE 128 - -#define USB_DEBUG_NONE 0 -#define USB_DEBUG_UHCI 1 -#define USB_DEBUG_OHCI 2 -#define USB_DEBUG_EHCI 3 -#define USB_DEBUG_XHCI 4 - -int win32_usb_start(HWND hwnd, int break_type, int wParam, int lParam); - -// USB debug break_type -#define USB_DEBUG_FRAME 1 -#define USB_DEBUG_COMMAND 2 -#define USB_DEBUG_EVENT 3 -#define USB_DEBUG_NONEXIST 4 -#define USB_DEBUG_RESET 5 -#define USB_DEBUG_ENABLE 6 - -void win32_usb_trigger(int type, int trigger, int wParam, int lParam); - -// lParam flags -#define USB_LPARAM_FLAG_BEFORE 0x00000001 -#define USB_LPARAM_FLAG_AFTER 0x00000002 - -struct CALLBACK_PARAMS { - int type; - int break_type; - int wParam; - int lParam; -}; - -struct DUMP_PARAMS { - char title[COMMON_STR_SIZE]; - bx_phy_address address; - int size; // amount to dump (no more than 512) - bool big; // use 64-bit addresses? -}; -INT_PTR CALLBACK dump_dialog_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); - -/////////////////////////////////////////////////////////////////////////////////////////////// -// UHCI -// -INT_PTR CALLBACK hc_uhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -void hc_uhci_do_item(Bit32u FrameAddr, Bit32u FrameNum); -int hc_uhci_init(HWND hwnd); -int hc_uhci_save(HWND hwnd); -void uhci_display_td(HWND hwnd); - -INT_PTR CALLBACK hc_uhci_callback_queue(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_uhci_callback_td(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); - -/////////////////////////////////////////////////////////////////////////////////////////////// -// OHCI -// -INT_PTR CALLBACK hc_ohci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -int hc_ohci_init(HWND hwnd); - -/////////////////////////////////////////////////////////////////////////////////////////////// -// EHCI -// -INT_PTR CALLBACK hc_ehci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -int hc_ehci_init(HWND hwnd); - - -/////////////////////////////////////////////////////////////////////////////////////////////// -// XHCI -// -#define VIEW_TRB_TYPE_NONE 0 -#define VIEW_TRB_TYPE_COMMAND 1 -#define VIEW_TRB_TYPE_EVENT 2 -#define VIEW_TRB_TYPE_TRANSFER 4 - -struct VIEW_TRB_TYPE { - Bit8u allowed_mask; - char name[22]; -}; - -#define MAX_TRBS_ALLOWED 4096 - -INT_PTR CALLBACK hc_xhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -int hc_xhci_init(HWND hwnd); -int hc_xhci_save(HWND hwnd); -void hc_xhci_do_ring(const char *ring_str, Bit64u RingPtr, Bit64u dequeue_ptr); -void hc_xhci_do_event_ring(const char *ring_str, int interrupter); -void xhci_display_trb(HWND hwnd, int type_mask); -INT_PTR CALLBACK hc_xhci_callback_trb_normal(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_setup(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_data(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_status(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_link(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_event(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_noop(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_enslot(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_disslot(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_address(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_configep(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_evaluate(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_resetep(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_stopep(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_settrptr(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_resetdev(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_forceevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_setlat(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_getband(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_forcehdr(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_transevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_compcompletion(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_pschange(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_bandrequ(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_doorbell(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_hostevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_devnotevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); - -INT_PTR CALLBACK hc_xhci_callback_trb_necfw(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_necun(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_trb_necfwevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); - -INT_PTR CALLBACK hc_xhci_callback_context(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK hc_xhci_callback_str_context(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); - - -/////////////////////////////////////////////////////////////////////////////////////////////// -// Attributes -struct S_ATTRIBUTES { - DWORD64 attrb; - DWORD64 mask; - int index; - char str[32]; - int groups[10]; // up to 10 items can be grouped. Increase if we need more. -}; -void do_attributes(HWND hwnd, DWORD id, const int size, const char *title, const struct S_ATTRIBUTES *attribs); - - -#endif // BX_USE_WIN32USBDEBUG -#endif // BX_WIN32_USB_H +///////////////////////////////////////////////////////////////////////// +// $Id$ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 Benjamin David Lunt +// Copyright (C) 2003-2024 The Bochs Project +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef BX_WIN32_USB_H +#define BX_WIN32_USB_H + +#if BX_USB_DEBUGGER + +struct CALLBACK_PARAMS { + int type; + int break_type; + int wParam; + int lParam; +}; + +struct DUMP_PARAMS { + char title[COMMON_STR_SIZE]; + bx_phy_address address; + int size; // amount to dump (no more than 512) + bool big; // use 64-bit addresses? +}; +INT_PTR CALLBACK dump_dialog_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +/////////////////////////////////////////////////////////////////////////////////////////////// +// UHCI +// +INT_PTR CALLBACK hc_uhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +void hc_uhci_do_item(Bit32u FrameAddr, Bit32u FrameNum); +int hc_uhci_init(HWND hwnd); +int hc_uhci_save(HWND hwnd); +void uhci_display_td(HWND hwnd); + +INT_PTR CALLBACK hc_uhci_callback_queue(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_uhci_callback_td(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +/////////////////////////////////////////////////////////////////////////////////////////////// +// OHCI +// +INT_PTR CALLBACK hc_ohci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int hc_ohci_init(HWND hwnd); + +/////////////////////////////////////////////////////////////////////////////////////////////// +// EHCI +// +INT_PTR CALLBACK hc_ehci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int hc_ehci_init(HWND hwnd); + + +/////////////////////////////////////////////////////////////////////////////////////////////// +// XHCI +// +#define VIEW_TRB_TYPE_NONE 0 +#define VIEW_TRB_TYPE_COMMAND 1 +#define VIEW_TRB_TYPE_EVENT 2 +#define VIEW_TRB_TYPE_TRANSFER 4 + +struct VIEW_TRB_TYPE { + Bit8u allowed_mask; + char name[22]; +}; + +#define MAX_TRBS_ALLOWED 4096 + +INT_PTR CALLBACK hc_xhci_callback(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int hc_xhci_init(HWND hwnd); +int hc_xhci_save(HWND hwnd); +void hc_xhci_do_ring(const char *ring_str, Bit64u RingPtr, Bit64u dequeue_ptr); +void hc_xhci_do_event_ring(const char *ring_str, int interrupter); +void xhci_display_trb(HWND hwnd, int type_mask); +INT_PTR CALLBACK hc_xhci_callback_trb_normal(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_setup(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_data(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_status(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_link(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_event(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_noop(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_enslot(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_disslot(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_address(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_configep(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_evaluate(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_resetep(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_stopep(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_settrptr(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_resetdev(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_forceevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_setlat(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_getband(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_forcehdr(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_transevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_compcompletion(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_pschange(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_bandrequ(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_doorbell(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_hostevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_devnotevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +INT_PTR CALLBACK hc_xhci_callback_trb_necfw(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_necun(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_trb_necfwevent(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +INT_PTR CALLBACK hc_xhci_callback_context(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK hc_xhci_callback_str_context(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + + +/////////////////////////////////////////////////////////////////////////////////////////////// +// Attributes +void do_attributes(HWND hwnd, DWORD id, const int size, const char *title, const struct S_ATTRIBUTES *attribs); + + +#endif // BX_USB_DEBUGGER +#endif // BX_WIN32_USB_H diff --git a/bochs/gui/wx.cc b/bochs/gui/wx.cc index d3d55adb9d..44ef44a668 100644 --- a/bochs/gui/wx.cc +++ b/bochs/gui/wx.cc @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2023 The Bochs Project +// Copyright (C) 2002-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -140,10 +140,14 @@ wxCriticalSection event_thread_lock; BxEvent event_queue[MAX_EVENTS]; unsigned long num_events; static bool mouse_captured = 0; -static bool wx_hide_ips = 0; +static unsigned wxBitmapEntries = 0; +static unsigned wxToolbarEntries = 0; #if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__) static Bit32u convertStringToGDKKey (const char *string); #endif +#if BX_DEBUGGER && BX_DEBUGGER_GUI && defined(WIN32) +bool wx_enh_dbg_global_ini = false; +#endif ////////////////////////////////////////////////////////////// @@ -221,6 +225,27 @@ void MyPanel::OnPaint(wxPaintEvent& WXUNUSED(event)) needRefresh = false; } +void MyPanel::SetMouseCapture(bool en) +{ + theFrame->SetToolBarBitmap(ID_Toolbar_Mouse_en, en); + if (en) { + mouseSavedX = wxScreenX / 2; + mouseSavedY = wxScreenY / 2; + WarpPointer(mouseSavedX, mouseSavedY); +#if defined(__WXMSW__) + ShowCursor(0); +#else + SetCursor(wxCURSOR_BLANK); +#endif + } else { +#if defined(__WXMSW__) + ShowCursor(1); +#else + SetCursor(wxNullCursor); +#endif + } +} + void MyPanel::ToggleMouse(bool fromToolbar) { static bool first_enable = true; @@ -243,22 +268,7 @@ void MyPanel::ToggleMouse(bool fromToolbar) } enable->set(en); IFDBG_MOUSE(wxLogDebug (wxT ("now mouse is %sabled", en ? "en" : "dis"))); - if (en) { - mouseSavedX = wxScreenX / 2; - mouseSavedY = wxScreenY / 2; - WarpPointer(mouseSavedX, mouseSavedY); -#if defined(__WXMSW__) - ShowCursor(0); -#else - SetCursor(wxCURSOR_BLANK); -#endif - } else { -#if defined(__WXMSW__) - ShowCursor(1); -#else - SetCursor(wxNullCursor); -#endif - } + SetMouseCapture(en); if (needmutex) wxMutexGuiLeave(); } @@ -967,7 +977,7 @@ DWORD WINAPI DebugGuiThread(LPVOID) { MSG msg; - bx_gui->init_debug_dialog(); + bx_gui->init_debug_dialog(0); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -1026,35 +1036,29 @@ void bx_wx_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) #endif // parse x11 specific options + Bit8u flags = BX_GUI_OPT_HIDE_IPS; if (argc > 1) { for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "cmdmode")) { - BX_ERROR(("Ignoring option 'cmdmode' - not supported by wxWidgets port")); - } else if (!strcmp(argv[i], "gui_debug")) { -#if BX_DEBUGGER && BX_DEBUGGER_GUI - BX_ERROR(("Ignoring option 'gui_debug' - wxWidgets port always uses gui debugger")); -#else - BX_ERROR(("Ignoring option 'gui_debug' - debugger not present")); -#endif -#if BX_SHOW_IPS - } else if (!strcmp(argv[i], "hideIPS")) { - BX_INFO(("hide IPS display in status bar")); - wx_hide_ips = 1; -#endif - } else { - BX_PANIC(("Unknown wx option '%s'", argv[i])); + if (!parse_common_gui_options(argv[i], flags)) { + if (!strcmp(argv[i], "cmdmode")) { + BX_ERROR(("Ignoring option 'cmdmode' - not supported by wxWidgets port")); + } else { + BX_PANIC(("Unknown wx option '%s'", argv[i])); + } } } } #if BX_DEBUGGER && BX_DEBUGGER_GUI + SIM->set_debug_gui(1); #ifdef WIN32 // on Windows the debugger gui must run in a separate thread DWORD threadID; + wx_enh_dbg_global_ini = gui_opts.enh_dbg_global_ini; CreateThread(NULL, 0, DebugGuiThread, NULL, 0, &threadID); #else wxMutexGuiEnter(); - init_debug_dialog(); + init_debug_dialog(gui_opts.enh_dbg_global_ini); wxMutexGuiLeave(); #endif #endif @@ -1063,12 +1067,19 @@ void bx_wx_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) msg.Printf(wxT("Enable mouse capture\nThere is also a shortcut for this: %s."), theGui->get_toggle_info()); theFrame->SetToolBarHelp(ID_Toolbar_Mouse_en, msg); + if (SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get()) { + thePanel->SetMouseCapture(1); + mouse_captured = 1; + } num_events = 0; new_gfx_api = 1; new_text_api = 1; dialog_caps = BX_GUI_DLG_USER | BX_GUI_DLG_SNAPSHOT | BX_GUI_DLG_SAVE_RESTORE; +#if BX_USB_DEBUGGER + dialog_caps |= BX_GUI_DLG_USB; +#endif } void bx_wx_gui_c::handle_events(void) @@ -1088,6 +1099,7 @@ void bx_wx_gui_c::handle_events(void) case BX_TOOLBAR_PASTE: paste_handler(); break; case BX_TOOLBAR_SNAPSHOT: tb_button = 3; break; case BX_TOOLBAR_USER: tb_button = 4; break; + case BX_TOOLBAR_USB_DEBUG: tb_button = 5; break; default: wxLogDebug (wxT ("unknown toolbar id %d"), event_queue[i].u.toolbar.button); } @@ -1197,6 +1209,11 @@ void bx_wx_gui_c::handle_events(void) } else if (tb_button == 4) { // userbutton_handler() also calls a dialog. userbutton_handler(); +#if BX_USB_DEBUGGER + } else if (tb_button == 5) { + // usb_handler() also calls a dialog. + usb_handler(); +#endif } } @@ -1430,7 +1447,9 @@ unsigned bx_wx_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, un UNUSED(bmap); UNUSED(xdim); UNUSED(ydim); - return(0); + // Return pseudo ID for replace_bitmap() feature + unsigned bmid = wxBitmapEntries++; + return bmid; } @@ -1439,7 +1458,9 @@ unsigned bx_wx_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, voi UNUSED(bmap_id); UNUSED(alignment); UNUSED(f); - return(0); + // Return pseudo ID for replace_bitmap() feature + unsigned hbid = wxToolbarEntries++; + return hbid; } void bx_wx_gui_c::show_headerbar(void) @@ -1448,8 +1469,18 @@ void bx_wx_gui_c::show_headerbar(void) void bx_wx_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id) { - UNUSED(hbar_id); - UNUSED(bmap_id); + // Use pseudo IDs to determine toolbar button to change + if (hbar_id == floppyA_hbar_id) { + theFrame->SetToolBarBitmap(ID_Edit_FD_0, bmap_id == floppyA_bmap_id); + } else if (hbar_id == floppyB_hbar_id) { + theFrame->SetToolBarBitmap(ID_Edit_FD_1, bmap_id == floppyB_bmap_id); + } else if (hbar_id == cdrom1_hbar_id) { + theFrame->SetToolBarBitmap(ID_Edit_Cdrom1, bmap_id == cdrom1_bmap_id); +#if BX_USB_DEBUGGER + } else if (hbar_id == usbdbg_hbar_id) { + theFrame->SetToolBarBitmap(ID_Toolbar_USB_Debug, bmap_id == usbdbg_trigger_bmap_id); +#endif + } } @@ -1465,6 +1496,8 @@ void bx_wx_gui_c::exit(void) close_debug_dialog(); wxMutexGuiLeave(); #endif + wxBitmapEntries = 0; + wxToolbarEntries = 0; } void bx_wx_gui_c::mouse_enabled_changed_specific(bool val) @@ -1532,7 +1565,7 @@ void bx_wx_gui_c::show_ips(Bit32u ips_count) { char ips_text[40]; - if (!wx_hide_ips) { + if (!gui_opts.hide_ips) { ips_count /= 1000; sprintf(ips_text, "IPS: %u.%3.3uM", ips_count / 1000, ips_count % 1000); theFrame->SetStatusText(wxString(ips_text, wxConvUTF8), 0); diff --git a/bochs/gui/wxmain.cc b/bochs/gui/wxmain.cc index 18f1e1a94a..757538363c 100644 --- a/bochs/gui/wxmain.cc +++ b/bochs/gui/wxmain.cc @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2023 The Bochs Project +// Copyright (C) 2002-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -71,6 +71,7 @@ #endif #include #include +#include #include "osdep.h" // workarounds for missing stuff #include "gui/paramtree.h" // config parameter tree @@ -81,18 +82,26 @@ #include "extplugin.h" // include XPM icons -#include "bitmaps/cdromd.xpm" +#include "bitmaps/cdrom1.xpm" +#include "bitmaps/cdrom1_eject.xpm" #include "bitmaps/copy.xpm" #include "bitmaps/floppya.xpm" +#include "bitmaps/floppya_eject.xpm" #include "bitmaps/floppyb.xpm" +#include "bitmaps/floppyb_eject.xpm" #include "bitmaps/paste.xpm" #include "bitmaps/power.xpm" #include "bitmaps/reset.xpm" #include "bitmaps/snapshot.xpm" #include "bitmaps/mouse.xpm" +#include "bitmaps/mouse_dis.xpm" //#include "bitmaps/configbutton.xpm" #include "bitmaps/userbutton.xpm" #include "bitmaps/saverestore.xpm" +#if BX_USB_DEBUGGER +#include "bitmaps/usbdbg.xpm" +#include "bitmaps/usbdbg_trigger.xpm" +#endif #ifdef __WXGTK__ #include "icon_bochs.xpm" #endif @@ -236,7 +245,7 @@ bool MyApp::OnInit() // simulation begins. This is responsible for displaying any error // dialogs during bochsrc and command line processing. SIM->set_notify_callback(&MyApp::DefaultCallback, this); - MyFrame *frame = new MyFrame(wxT("Bochs x86 Emulator"), wxPoint(50,50), wxSize(450,340), wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION); + MyFrame *frame = new MyFrame(wxT("Bochs x86 Emulator"), wxPoint(50,50), wxSize(640,480), wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION); theFrame = frame; // hack alert frame->Show(TRUE); SetTopWindow(frame); @@ -344,6 +353,9 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_TOOL(ID_Toolbar_Snapshot, MyFrame::OnToolbarClick) EVT_TOOL(ID_Toolbar_Mouse_en, MyFrame::OnToolbarClick) EVT_TOOL(ID_Toolbar_User, MyFrame::OnToolbarClick) +#if BX_USB_DEBUGGER + EVT_TOOL(ID_Toolbar_USB_Debug, MyFrame::OnToolbarClick) +#endif END_EVENT_TABLE() @@ -435,18 +447,21 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, bxToolBar->AddTool(id, wxT(""), wxBitmap(xpm_name), tooltip); \ } while (0) - BX_ADD_TOOL(ID_Edit_FD_0, floppya_xpm, wxT("Change Floppy A")); - BX_ADD_TOOL(ID_Edit_FD_1, floppyb_xpm, wxT("Change Floppy B")); - BX_ADD_TOOL(ID_Edit_Cdrom1, cdromd_xpm, wxT("Change CDROM")); + BX_ADD_TOOL(ID_Edit_FD_0, floppya_eject_xpm, wxT("Change floppy A: media")); + BX_ADD_TOOL(ID_Edit_FD_1, floppyb_eject_xpm, wxT("Change floppy B: media")); + BX_ADD_TOOL(ID_Edit_Cdrom1, cdrom1_eject_xpm, wxT("Change first CDROM media")); + BX_ADD_TOOL(ID_Toolbar_Mouse_en, mouse_dis_xpm, wxT("Enable mouse capture")); +#if BX_USB_DEBUGGER + BX_ADD_TOOL(ID_Toolbar_USB_Debug, usbdbg_xpm, wxT("USB Debugger support not enabled")); +#endif + bxToolBar->AddSeparator(); + BX_ADD_TOOL(ID_Toolbar_User, userbutton_xpm, wxT("Send keyboard shortcut")); + BX_ADD_TOOL(ID_Toolbar_Copy, copy_xpm, wxT("Copy text mode screen to the clipboard")); + BX_ADD_TOOL(ID_Toolbar_Paste, paste_xpm, wxT("Paste clipboard text as emulated keystrokes")); + BX_ADD_TOOL(ID_Toolbar_Snapshot, snapshot_xpm, wxT("Save snapshot of the Bochs screen")); BX_ADD_TOOL(ID_Toolbar_Reset, reset_xpm, wxT("Reset the system")); - BX_ADD_TOOL(ID_Toolbar_Power, power_xpm, wxT("Turn power on/off")); - BX_ADD_TOOL(ID_Toolbar_SaveRestore, saverestore_xpm, wxT("")); - - BX_ADD_TOOL(ID_Toolbar_Copy, copy_xpm, wxT("Copy to clipboard")); - BX_ADD_TOOL(ID_Toolbar_Paste, paste_xpm, wxT("Paste from clipboard")); - BX_ADD_TOOL(ID_Toolbar_Snapshot, snapshot_xpm, wxT("Save screen snapshot")); - BX_ADD_TOOL(ID_Toolbar_Mouse_en, mouse_xpm, wxT("Enable mouse capture\nThere is also a shortcut for this: a CTRL key + the middle mouse button.")); - BX_ADD_TOOL(ID_Toolbar_User, userbutton_xpm, wxT("Keyboard shortcut")); + BX_ADD_TOOL(ID_Toolbar_SaveRestore, saverestore_xpm, wxT("Restore simulation state")); + BX_ADD_TOOL(ID_Toolbar_Power, power_xpm, wxT("Turn power on")); bxToolBar->Realize(); UpdateToolBar(false); @@ -483,10 +498,14 @@ void MyFrame::OnConfigNew(wxCommandEvent& WXUNUSED(event)) void MyFrame::OnConfigRead(wxCommandEvent& WXUNUSED(event)) { char bochsrc[512]; + wxString fullName, workDir; long style = wxFD_OPEN; wxFileDialog *fdialog = new wxFileDialog(this, wxT("Read configuration"), wxT(""), wxT(""), wxT("*.*"), style); if (fdialog->ShowModal() == wxID_OK) { - strncpy(bochsrc, fdialog->GetPath().mb_str(wxConvUTF8), sizeof(bochsrc) - 1); + fullName = fdialog->GetPath(); + wxFileName::SplitPath(fullName, &workDir, NULL, NULL); + wxSetWorkingDirectory(workDir); + strncpy(bochsrc, fullName.mb_str(wxConvUTF8), sizeof(bochsrc) - 1); bochsrc[sizeof(bochsrc) - 1] = '\0'; SIM->reset_all_param(); SIM->read_rc(bochsrc); @@ -859,9 +878,14 @@ void MyFrame::UpdateToolBar(bool simPresent) bxToolBar->EnableTool(ID_Toolbar_User, simPresent); if (simPresent) { bxToolBar->SetToolShortHelp(ID_Toolbar_SaveRestore, wxT("Save simulation state")); + bxToolBar->SetToolShortHelp(ID_Toolbar_Power, wxT("Turn power off")); } else { bxToolBar->SetToolShortHelp(ID_Toolbar_SaveRestore, wxT("Restore simulation state")); + bxToolBar->SetToolShortHelp(ID_Toolbar_Power, wxT("Turn power on")); } +#if BX_USB_DEBUGGER + bxToolBar->EnableTool(ID_Toolbar_USB_Debug, false); +#endif } void MyFrame::OnStartSim(wxCommandEvent& event) @@ -1271,6 +1295,7 @@ void MyFrame::OnToolbarClick(wxCommandEvent& event) case ID_Toolbar_Snapshot: which = BX_TOOLBAR_SNAPSHOT; break; case ID_Toolbar_Mouse_en: panel->ToggleMouse(true); break; case ID_Toolbar_User: which = BX_TOOLBAR_USER; break; + case ID_Toolbar_USB_Debug: which = BX_TOOLBAR_USB_DEBUG; break; default: wxLogError(wxT("unknown toolbar id %d"), id); } @@ -1286,6 +1311,38 @@ void MyFrame::SetToolBarHelp(int id, wxString& text) bxToolBar->SetToolShortHelp(id, text); } +void MyFrame::SetToolBarBitmap(int id, bool onoff) +{ + wxBitmap bitmap; + + switch (id) { + case ID_Edit_FD_0: + bitmap = wxBitmap(onoff ? floppya_xpm : floppya_eject_xpm); + break; + case ID_Edit_FD_1: + bitmap = wxBitmap(onoff ? floppyb_xpm : floppyb_eject_xpm); + break; + case ID_Edit_Cdrom1: + bitmap = wxBitmap(onoff ? cdrom1_xpm : cdrom1_eject_xpm); + break; + case ID_Toolbar_Mouse_en: + bitmap = wxBitmap(onoff ? mouse_xpm : mouse_dis_xpm); + break; +#if BX_USB_DEBUGGER + case ID_Toolbar_USB_Debug: + if (!bxToolBar->GetToolEnabled(ID_Toolbar_USB_Debug)) { + bxToolBar->EnableTool(ID_Toolbar_USB_Debug, true); + bxToolBar->SetToolShortHelp(ID_Toolbar_USB_Debug, wxT("Trigger the USB debugger")); + } + bitmap = wxBitmap(onoff ? usbdbg_trigger_xpm : usbdbg_xpm); + break; +#endif + default: + return; + } + bxToolBar->SetToolNormalBitmap(id, bitmap); +} + ////////////////////////////////////////////////////////////////////// // Simulation Thread ////////////////////////////////////////////////////////////////////// diff --git a/bochs/gui/wxmain.h b/bochs/gui/wxmain.h index fb4796c970..e3e26cf333 100644 --- a/bochs/gui/wxmain.h +++ b/bochs/gui/wxmain.h @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2021 The Bochs Project +// Copyright (C) 2002-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -85,6 +85,7 @@ enum ID_Toolbar_Mouse_en, ID_Toolbar_User, ID_Toolbar_SaveRestore, + ID_Toolbar_USB_Debug, // dialog box: LogMsgAskDialog ID_Continue, ID_Die, @@ -155,6 +156,7 @@ class MyPanel: public wxPanel void OnKillFocus(wxFocusEvent& event); void MyRefresh(); static void OnPluginInit(); + void SetMouseCapture(bool en); void ToggleMouse(bool fromToolbar); private: bool needRefresh; @@ -215,6 +217,7 @@ class MyFrame: public wxFrame void UpdateToolBar(bool simPresent); void SetToolBarHelp(int id, wxString& text); + void SetToolBarBitmap(int id, bool onoff); private: wxCriticalSection sim_thread_lock; diff --git a/bochs/gui/x.cc b/bochs/gui/x.cc index ac0ae89407..7024b4ec99 100644 --- a/bochs/gui/x.cc +++ b/bochs/gui/x.cc @@ -137,7 +137,6 @@ static void disable_cursor(); static void enable_cursor(); // keyboard -static bool x11_nokeyrepeat = 0; static bool x11_use_kbd_mapping = 0; static Bit32u convertStringToXKeysym(const char *string); @@ -167,7 +166,7 @@ static long bx_status_leds[3]; static long bx_status_graytext; static char bx_status_info_text[34]; #if BX_SHOW_IPS -static bool x11_ips_update = 0, x11_hide_ips = 0; +static bool x11_ips_update = 0; static char x11_ips_text[20]; static Bit8u x11_show_info_msg = 0; static Bit8u x11_info_msg_counter = 0; @@ -598,9 +597,6 @@ void bx_x_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) XSetWindowAttributes win_attr; unsigned long plane_masks_return[1]; XColor color; -#if BX_DEBUGGER && BX_DEBUGGER_GUI - bool x11_with_debug_gui = 0; -#endif #if BX_HAVE_XRANDR_H int event_base, error_base; #endif @@ -610,42 +606,13 @@ void bx_x_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) progname = argv[0]; console.present = 1; - // parse x11 specific options - if (argc > 1) { - for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "nokeyrepeat")) { - BX_INFO(("disabled host keyboard repeat")); - x11_nokeyrepeat = 1; - } else if (!strcmp(argv[i], "gui_debug")) { -#if BX_DEBUGGER && BX_DEBUGGER_GUI - x11_with_debug_gui = 1; -#else - SIM->message_box("ERROR", "Bochs debugger not available - ignoring 'gui_debug' option"); -#endif -#if BX_SHOW_IPS - } else if (!strcmp(argv[i], "hideIPS")) { - BX_INFO(("hide IPS display in status bar")); - x11_hide_ips = 1; -#endif - } else if (!strcmp(argv[i], "cmdmode")) { - command_mode.present = 1; - } else if (!strcmp(argv[i], "no_gui_console")) { - console.present = 0; - } else { - BX_PANIC(("Unknown x11 option '%s'", argv[i])); - } - } - } - -#if BX_DEBUGGER && BX_DEBUGGER_GUI - if (x11_with_debug_gui) { - // This is only necessary when GTK+ and Xlib are sharing the same - // connection. XInitThreads() must finish before any calls to GTK+ - // or Xlib are made. - if (XInitThreads() == 0) { - BX_PANIC(("trying to run Bochs with the GTK+ " - "debugger on a non-threading X11.")); - } +#if (BX_DEBUGGER && BX_DEBUGGER_GUI) || BX_SUPPORT_SOUNDLOW || BX_SUPPORT_VOODOO || BX_USB_DEBUGGER + // This is only necessary when GTK+ and Xlib are sharing the same + // connection. XInitThreads() must finish before any calls to GTK+ + // or Xlib are made. + if (XInitThreads() == 0) { + BX_PANIC(("trying to run Bochs with the GTK+ " + "debugger on a non-threading X11.")); } #endif @@ -659,6 +626,22 @@ void bx_x_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) /* get screen size from display structure macro */ bx_x_screen_num = DefaultScreen(bx_x_display); + // redirect notify callback to X11 specific code + SIM->get_notify_callback(&old_callback, &old_callback_arg); + assert(old_callback != NULL); + SIM->set_notify_callback(x11_notify_callback, NULL); + + // parse x11 specific options + Bit8u flags = BX_GUI_OPT_NOKEYREPEAT | BX_GUI_OPT_HIDE_IPS | BX_GUI_OPT_CMDMODE + | BX_GUI_OPT_NO_GUI_CONSOLE; + if (argc > 1) { + for (i = 1; i < argc; i++) { + if (!parse_common_gui_options(argv[i], flags)) { + BX_PANIC(("Unknown x11 option '%s'", argv[i])); + } + } + } + /* Note that in a real application, x and y would default to 0 * but would be settable from the command line or resource database. */ @@ -899,11 +882,6 @@ void bx_x_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) XFlush(bx_x_display); - // redirect notify callback to X11 specific code - SIM->get_notify_callback(&old_callback, &old_callback_arg); - assert(old_callback != NULL); - SIM->set_notify_callback(x11_notify_callback, NULL); - // loads keymap for x11 x11_use_kbd_mapping = SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get(); if (x11_use_kbd_mapping) { @@ -912,9 +890,9 @@ void bx_x_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) #if BX_DEBUGGER && BX_DEBUGGER_GUI // initialize debugger gui - if (x11_with_debug_gui) { + if (gui_opts.enh_dbg_enabled) { SIM->set_debug_gui(1); - init_debug_dialog(); + init_debug_dialog(gui_opts.enh_dbg_global_ini); } #endif @@ -949,6 +927,9 @@ void bx_x_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y) new_gfx_api = 1; new_text_api = 1; dialog_caps |= (BX_GUI_DLG_USER | BX_GUI_DLG_SNAPSHOT | BX_GUI_DLG_CDROM); +#if BX_USB_DEBUGGER + dialog_caps |= BX_GUI_DLG_USB; +#endif } void bx_x_gui_c::handle_events(void) @@ -975,7 +956,7 @@ void bx_x_gui_c::handle_events(void) XNextEvent(bx_x_display, &report); current_z = 0; - if (x11_nokeyrepeat && (report.type == KeyRelease) && X11_KeyRepeat(bx_x_display, &report)) { + if (gui_opts.nokeyrepeat && (report.type == KeyRelease) && X11_KeyRepeat(bx_x_display, &report)) { return; } @@ -1727,7 +1708,7 @@ void bx_x_gui_c::set_mouse_mode_absxy(bool mode) void bx_x_gui_c::show_ips(Bit32u ips_count) { if (x11_info_msg_counter == 0) { - if (!x11_ips_update && !x11_hide_ips) { + if (!x11_ips_update && !gui_opts.hide_ips) { ips_count /= 1000; sprintf(x11_ips_text, "IPS: %u.%3.3uM", ips_count / 1000, ips_count % 1000); x11_ips_update = 1; diff --git a/bochs/iodev/cmos.cc b/bochs/iodev/cmos.cc index bd796b39b3..d1e92b0328 100644 --- a/bochs/iodev/cmos.cc +++ b/bochs/iodev/cmos.cc @@ -794,21 +794,21 @@ void bx_cmos_c::update_clock() time_calendar = utctime(& BX_CMOS_THIS s.timeval); // update seconds - BX_CMOS_THIS s.reg[REG_SEC] = bin_to_bcd(time_calendar->tm_sec, BX_CMOS_THIS s.rtc_mode_binary); + BX_CMOS_THIS s.reg[REG_SEC] = bin_to_bcd((Bit8u)time_calendar->tm_sec, BX_CMOS_THIS s.rtc_mode_binary); // update minutes - BX_CMOS_THIS s.reg[REG_MIN] = bin_to_bcd(time_calendar->tm_min, BX_CMOS_THIS s.rtc_mode_binary); + BX_CMOS_THIS s.reg[REG_MIN] = bin_to_bcd((Bit8u)time_calendar->tm_min, BX_CMOS_THIS s.rtc_mode_binary); // update hours if (BX_CMOS_THIS s.rtc_mode_12hour) { - hour = time_calendar->tm_hour; + hour = (Bit8u)time_calendar->tm_hour; val_bcd = (hour > 11) ? 0x80 : 0x00; if (hour > 11) hour -= 12; if (hour == 0) hour = 12; val_bcd |= bin_to_bcd(hour, BX_CMOS_THIS s.rtc_mode_binary); BX_CMOS_THIS s.reg[REG_HOUR] = val_bcd; } else { - BX_CMOS_THIS s.reg[REG_HOUR] = bin_to_bcd(time_calendar->tm_hour, BX_CMOS_THIS s.rtc_mode_binary); + BX_CMOS_THIS s.reg[REG_HOUR] = bin_to_bcd((Bit8u)time_calendar->tm_hour, BX_CMOS_THIS s.rtc_mode_binary); } // update day of the week diff --git a/bochs/iodev/display/banshee.cc b/bochs/iodev/display/banshee.cc index 32306c1ccb..ed1a1ea4a7 100644 --- a/bochs/iodev/display/banshee.cc +++ b/bochs/iodev/display/banshee.cc @@ -886,7 +886,7 @@ void bx_banshee_c::mem_read(bx_phy_address addr, unsigned len, void *data) #endif for (unsigned i = 0; i < len; i++) { if (pci_conf[0x30] & 0x01) { - *data_ptr = pci_rom[(addr & mask) + i]; + *data_ptr = pci_rom[addr & mask]; } else { *data_ptr = 0xff; } @@ -941,6 +941,16 @@ void bx_banshee_c::mem_read(bx_phy_address addr, unsigned len, void *data) case 2: *((Bit16u*)data) = (Bit16u)value; break; + case 3: +#ifdef BX_LITTLE_ENDIAN + *((Bit16u*)data) = (Bit16u)value; + *((Bit8u*)data + 2) = (Bit8u)(value >> 16); +#else + for (unsigned i = 0; i < 3; i++) { + *((Bit8u*)data + i) = (Bit8u)(value >> ((2 - i) << 3)); + } +#endif + break; case 4: *((Bit32u*)data) = (Bit32u)value; break; @@ -954,8 +964,8 @@ void bx_banshee_c::mem_read(bx_phy_address addr, unsigned len, void *data) void bx_banshee_c::mem_write(bx_phy_address addr, unsigned len, void *data) { - Bit32u offset = (addr & 0x1ffffff); - Bit64u value = 0; + Bit32u offset = (addr & 0x1ffffff), value; + Bit64u value64 = 0; Bit32u mask = 0xffffffff; #ifdef BX_LITTLE_ENDIAN @@ -964,13 +974,14 @@ void bx_banshee_c::mem_write(bx_phy_address addr, unsigned len, void *data) Bit8u *data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { - value |= ((Bit64u)*data_ptr << (i * 8)); + value64 |= ((Bit64u)*data_ptr << (i * 8)); #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } + value = (Bit32u)value64; if ((addr & ~0x1ffffff) == pci_bar[0].addr) { if (offset < 0x80000) { write(offset, value, len); @@ -1008,10 +1019,10 @@ void bx_banshee_c::mem_write(bx_phy_address addr, unsigned len, void *data) cmdfifo_w(&v->fbi.cmdfifo[0], offset, value); } else if (len == 8) { cmdfifo_w(&v->fbi.cmdfifo[0], offset, value); - cmdfifo_w(&v->fbi.cmdfifo[0], offset + 4, value >> 32); + cmdfifo_w(&v->fbi.cmdfifo[0], offset + 4, value64 >> 32); } else { BX_ERROR(("CMDFIFO #0 write with len = %d redirected to LFB", len)); - mem_write_linear(offset, value, len); + mem_write_linear(offset, value64, len); } } else if (v->fbi.cmdfifo[1].enabled && (offset >= v->fbi.cmdfifo[1].base) && (offset < v->fbi.cmdfifo[1].end)) { @@ -1019,13 +1030,13 @@ void bx_banshee_c::mem_write(bx_phy_address addr, unsigned len, void *data) cmdfifo_w(&v->fbi.cmdfifo[1], offset, value); } else if (len == 8) { cmdfifo_w(&v->fbi.cmdfifo[1], offset, value); - cmdfifo_w(&v->fbi.cmdfifo[1], offset + 4, value >> 32); + cmdfifo_w(&v->fbi.cmdfifo[1], offset + 4, value64 >> 32); } else { BX_ERROR(("CMDFIFO #1 write with len = %d redirected to LFB", len)); - mem_write_linear(offset, value, len); + mem_write_linear(offset, value64, len); } } else { - mem_write_linear(offset, value, len); + mem_write_linear(offset, value64, len); } } } @@ -1974,7 +1985,8 @@ void bx_banshee_c::blt_screen_to_screen() w = BLT.dst_w; h = BLT.dst_h; BX_DEBUG(("Screen to screen blt: %d x %d ROP0 %02X", w, h, BLT.rop[0])); - if ((BLT.src_fmt != 0) && (BLT.dst_fmt != BLT.src_fmt)) { + if ((BLT.src_fmt != 0) && (BLT.dst_fmt != BLT.src_fmt) && + !(BLT.src_fmt == 3 && BLT.dst_fmt == 5)) { BX_ERROR(("Pixel format conversion not supported yet")); } if (!blt_apply_clipwindow(&sx, &sy, &dx, &dy, &w, &h)) { @@ -2048,6 +2060,27 @@ void bx_banshee_c::blt_screen_to_screen() src_ptr += spitch; dst_ptr += dpitch; } while (--nrows); + } else if (BLT.src_fmt == 3 && BLT.dst_fmt == 5) { + int spxsize = 2; + src_ptr += (sy * abs(spitch) + sx * spxsize); + nrows = h; + do { + src_ptr1 = src_ptr; + dst_ptr1 = dst_ptr; + ncols = w; + do { +#ifdef BX_LITTLE_ENDIAN + BLT.rop_fn[0](dst_ptr1, (Bit8u*)&v->fbi.pen[*(Bit16u*)src_ptr1], dpitch, spitch, abs(dpxsize), 1); +#else + Bit32u color32 = bx_bswap32(v->fbi.pen[bx_bswap16(*(Bit16u*)src_ptr1)]); + BLT.rop_fn[0](dst_ptr1, (Bit8u*)&color32, dpitch, spitch, abs(dpxsize), 1); +#endif + src_ptr1 += spxsize; + dst_ptr1 += dpxsize; + } while (--ncols); + src_ptr += spitch; + dst_ptr += dpitch; + } while (--nrows); } else { src_ptr += (sy * abs(spitch) + sx * abs(dpxsize) + bkw_adj); BLT.rop_fn[0](dst_ptr + bkw_adj, src_ptr, dpitch, spitch, w * abs(dpxsize), h); diff --git a/bochs/iodev/display/svga_cirrus.cc b/bochs/iodev/display/svga_cirrus.cc index 0f1cccd481..2713752d21 100644 --- a/bochs/iodev/display/svga_cirrus.cc +++ b/bochs/iodev/display/svga_cirrus.cc @@ -206,7 +206,7 @@ // PCI 0x40-0xff: device dependent fields // default PnP memory and memory-mapped I/O sizes -#define CIRRUS_PNPMEM_SIZE CIRRUS_VIDEO_MEMORY_BYTES +#define CIRRUS_PNPMEM_SIZE (16 << 20) #define CIRRUS_PNPMMIO_SIZE 0x1000 static bx_svga_cirrus_c *theSvga = NULL; @@ -393,6 +393,10 @@ void bx_svga_cirrus_c::register_state(void) new bx_shadow_num_c(list, "bank_base1", &BX_CIRRUS_THIS bank_base[1], BASE_HEX); new bx_shadow_num_c(list, "bank_limit0", &BX_CIRRUS_THIS bank_limit[0], BASE_HEX); new bx_shadow_num_c(list, "bank_limit1", &BX_CIRRUS_THIS bank_limit[1], BASE_HEX); + new bx_shadow_num_c(list, "ext_latch0", &BX_CIRRUS_THIS ext_latch[0], BASE_HEX); + new bx_shadow_num_c(list, "ext_latch1", &BX_CIRRUS_THIS ext_latch[1], BASE_HEX); + new bx_shadow_num_c(list, "ext_latch2", &BX_CIRRUS_THIS ext_latch[2], BASE_HEX); + new bx_shadow_num_c(list, "ext_latch3", &BX_CIRRUS_THIS ext_latch[3], BASE_HEX); bx_list_c *cursor = new bx_list_c(list, "hw_cursor"); new bx_shadow_num_c(cursor, "x", &BX_CIRRUS_THIS hw_cursor.x, BASE_HEX); new bx_shadow_num_c(cursor, "y", &BX_CIRRUS_THIS hw_cursor.y, BASE_HEX); @@ -453,7 +457,7 @@ void bx_svga_cirrus_c::redraw_area(unsigned x0, unsigned y0, unsigned width, yt1 = (BX_CIRRUS_THIS svga_yres - 1) / Y_TILESIZE; } if ((x0 + width) > svga_xres) { - BX_CIRRUS_THIS redraw_area(0, y0 + 1, width, height); + BX_CIRRUS_THIS redraw_area(0, y0 + 1, x0 + width - svga_xres, height); } for (yti=yt0; yti<=yt1; yti++) { for (xti=xt0; xti<=xt1; xti++) { @@ -534,9 +538,7 @@ Bit8u bx_svga_cirrus_c::mem_read(bx_phy_address addr) } } } -#endif -#if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { if ((addr >= BX_CIRRUS_THIS pci_bar[0].addr) && (addr < (BX_CIRRUS_THIS pci_bar[0].addr + CIRRUS_PNPMEM_SIZE))) { @@ -589,7 +591,11 @@ Bit8u bx_svga_cirrus_c::mem_read(bx_phy_address addr) } #endif // BX_SUPPORT_PCI if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { - return BX_CIRRUS_THIS bx_vgacore_c::mem_read(addr); + if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x1e) != 0) { + return BX_CIRRUS_THIS vga_mem_read(addr); + } else { + return BX_CIRRUS_THIS bx_vgacore_c::mem_read(addr); + } } if (addr >= 0xA0000 && addr <= 0xAFFFF) @@ -628,38 +634,132 @@ Bit8u bx_svga_cirrus_c::mem_read(bx_phy_address addr) else { return 0xff; } - } - else if (addr >= 0xB8000 && addr <= 0xB8100) { + } else if (addr >= 0xB8000 && addr <= 0xB8100) { // memory-mapped I/O. Bit32u offset = (Bit32u) (addr - 0xb8000); if ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x04) return svga_mmio_blt_read(offset); - } - else { - BX_DEBUG(("mem_read 0x%08x", (Bit32u)addr)); + } else { + BX_DEBUG(("mem_read from address 0x%08x ignored", (Bit32u)addr)); } return 0xff; } +Bit8u bx_svga_cirrus_c::vga_mem_read(bx_phy_address addr) +{ + Bit32u offset; + Bit8u read_map_select = BX_CIRRUS_THIS s.graphics_ctrl.read_map_select; + + switch (BX_CIRRUS_THIS s.graphics_ctrl.memory_mapping) { + case 1: // 0xA0000 .. 0xAFFFF + if ((addr < 0xa0000) || (addr > 0xaffff)) return 0xff; + offset = addr & 0xffff; + break; + case 2: // 0xB0000 .. 0xB7FFF + if ((addr < 0xb0000) || (addr > 0xb7fff)) return 0xff; + offset = addr & 0x7fff; + break; + case 3: // 0xB8000 .. 0xBFFFF + if (addr < 0xb8000) return 0xff; + offset = addr & 0x7fff; + break; + default: // 0xA0000 .. 0xBFFFF + offset = addr & 0x1ffff; + } + + offset = (offset & 0x7fff) + BX_CIRRUS_THIS bank_base[(offset >> 15) & 1]; + if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) { + offset <<= 1; + } else if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { + offset <<= 2; + } + offset &= BX_CIRRUS_THIS s.vgamem_mask; + + /* read mode 0 */ + BX_CIRRUS_THIS s.graphics_ctrl.latch[0] = BX_CIRRUS_THIS s.memory[offset << 2]; + BX_CIRRUS_THIS s.graphics_ctrl.latch[1] = BX_CIRRUS_THIS s.memory[(offset << 2) + 1]; + BX_CIRRUS_THIS s.graphics_ctrl.latch[2] = BX_CIRRUS_THIS s.memory[(offset << 2) + 2]; + BX_CIRRUS_THIS s.graphics_ctrl.latch[3] = BX_CIRRUS_THIS s.memory[(offset << 2) + 3]; + if (BX_CIRRUS_THIS control.reg[0x0b] & 0x08) { + BX_CIRRUS_THIS ext_latch[0] = BX_CIRRUS_THIS s.memory[(offset << 2) + 4]; + BX_CIRRUS_THIS ext_latch[1] = BX_CIRRUS_THIS s.memory[(offset << 2) + 5]; + BX_CIRRUS_THIS ext_latch[2] = BX_CIRRUS_THIS s.memory[(offset << 2) + 6]; + BX_CIRRUS_THIS ext_latch[3] = BX_CIRRUS_THIS s.memory[(offset << 2) + 7]; + } + if (BX_CIRRUS_THIS s.graphics_ctrl.read_mode == 1) { + /* read mode 1 */ + Bit8u color_compare = BX_CIRRUS_THIS s.graphics_ctrl.color_compare & 0x0f; + Bit8u color_dont_care = BX_CIRRUS_THIS s.graphics_ctrl.color_dont_care & 0x0f; + Bit8u latch0, latch1, latch2, latch3; + + latch0 = BX_CIRRUS_THIS s.graphics_ctrl.latch[0]; + latch1 = BX_CIRRUS_THIS s.graphics_ctrl.latch[1]; + latch2 = BX_CIRRUS_THIS s.graphics_ctrl.latch[2]; + latch3 = BX_CIRRUS_THIS s.graphics_ctrl.latch[3]; + + latch0 ^= ccdat[color_compare][0]; + latch1 ^= ccdat[color_compare][1]; + latch2 ^= ccdat[color_compare][2]; + latch3 ^= ccdat[color_compare][3]; + + latch0 &= ccdat[color_dont_care][0]; + latch1 &= ccdat[color_dont_care][1]; + latch2 &= ccdat[color_dont_care][2]; + latch3 &= ccdat[color_dont_care][3]; + + return ~(latch0 | latch1 | latch2 | latch3); + } else { + return BX_CIRRUS_THIS s.graphics_ctrl.latch[read_map_select]; + } +} + #if BX_SUPPORT_PCI bool bx_svga_cirrus_c::cirrus_mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit8u *data_ptr; + if ((addr & ~(CIRRUS_PNPMEM_SIZE - 1)) == BX_CIRRUS_THIS pci_bar[0].addr) { + Bit8u swap = (Bit8u)(addr >> 22); + if (swap == 1) { + Bit32u val32 = bx_bswap16((*(Bit32u*)data) & 0xffff); + val32 |= (bx_bswap16((*(Bit32u*)data) >> 16) << 16); + *((Bit32u*)data) = val32; + } else if (swap == 2) { + Bit32u val32 = bx_bswap32(*(Bit32u*)data); + *((Bit32u*)data) = val32; + } + } #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif - for (unsigned i = 0; i < len; i++) { - BX_CIRRUS_THIS mem_write(addr, *data_ptr); - addr++; + if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) { + // cpu-to-video BLT + for (unsigned i = 0; i < len; i++) { + if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) { + *(BX_CIRRUS_THIS bitblt.memsrc_ptr)++ = *data_ptr; + if (BX_CIRRUS_THIS bitblt.memsrc_ptr >= BX_CIRRUS_THIS bitblt.memsrc_endptr) { + svga_asyncbitblt_next(); + } + } #ifdef BX_LITTLE_ENDIAN - data_ptr++; + data_ptr++; #else // BX_BIG_ENDIAN - data_ptr--; + data_ptr--; +#endif + } + } else { + for (unsigned i = 0; i < len; i++) { + BX_CIRRUS_THIS mem_write(addr, *data_ptr); + addr++; +#ifdef BX_LITTLE_ENDIAN + data_ptr++; +#else // BX_BIG_ENDIAN + data_ptr--; #endif + } } return 1; } @@ -687,15 +787,6 @@ void bx_svga_cirrus_c::mem_write(bx_phy_address addr, Bit8u value) return; } - // cpu-to-video BLT - if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) { - *(BX_CIRRUS_THIS bitblt.memsrc_ptr)++ = (value); - if (BX_CIRRUS_THIS bitblt.memsrc_ptr >= BX_CIRRUS_THIS bitblt.memsrc_endptr) { - svga_asyncbitblt_next(); - } - return; - } - // BX_DEBUG(("write offset 0x%08x,value 0x%02x",offset,value)); if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { offset <<= 4; @@ -740,7 +831,11 @@ void bx_svga_cirrus_c::mem_write(bx_phy_address addr, Bit8u value) } #endif // BX_SUPPORT_PCI if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { - BX_CIRRUS_THIS bx_vgacore_c::mem_write(addr,value); + if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x1e) != 0) { + BX_CIRRUS_THIS vga_mem_write(addr,value); + } else { + BX_CIRRUS_THIS bx_vgacore_c::mem_write(addr,value); + } return; } @@ -796,9 +891,365 @@ void bx_svga_cirrus_c::mem_write(bx_phy_address addr, Bit8u value) if ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x04) { svga_mmio_blt_write(offset & 0xff, value); } + } else { + BX_DEBUG(("mem_write() to address 0x%08x ignored (value 0x%02x)", (Bit32u)addr, value)); } - else { - BX_DEBUG(("mem_write 0x%08x, value 0x%02x", (Bit32u)addr, value)); +} + +void bx_svga_cirrus_c::vga_mem_write(bx_phy_address addr, Bit8u value) +{ + Bit32u offset; + Bit8u new_val[8] = {0,0,0,0,0,0,0,0}; + unsigned start_addr; + Bit8u write_mode, sequ_map_mask; + + switch (BX_CIRRUS_THIS s.graphics_ctrl.memory_mapping) { + case 1: // 0xA0000 .. 0xAFFFF + if ((addr < 0xa0000) || (addr > 0xaffff)) return; + offset = addr & 0xffff; + break; + case 2: // 0xB0000 .. 0xB7FFF + if ((addr < 0xb0000) || (addr > 0xb7fff)) return; + offset = addr & 0x7fff; + break; + case 3: // 0xB8000 .. 0xBFFFF + if (addr < 0xb8000) return; + offset = addr & 0x7fff; + break; + default: // 0xA0000 .. 0xBFFFF + offset = addr & 0x1ffff; + } + + offset = (offset & 0x7fff) + BX_CIRRUS_THIS bank_base[(offset >> 15) & 1]; + if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) { + offset <<= 1; + } else if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { + offset <<= 2; + } + offset &= BX_CIRRUS_THIS s.vgamem_mask; + + if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x04) == 0x04) { + write_mode = BX_CIRRUS_THIS control.reg[0x05] & 0x07; + sequ_map_mask = BX_CIRRUS_THIS sequencer.reg[0x02]; + } else { + write_mode = BX_CIRRUS_THIS s.graphics_ctrl.write_mode; + sequ_map_mask = BX_CIRRUS_THIS s.sequencer.map_mask & 0x0f; + } + + start_addr = BX_CIRRUS_THIS s.CRTC.start_addr; + + switch (write_mode) { + unsigned i; + + case 0: /* write mode 0 */ + { + const Bit8u bitmask = BX_CIRRUS_THIS s.graphics_ctrl.bitmask; + const Bit8u set_reset = BX_CIRRUS_THIS s.graphics_ctrl.set_reset; + const Bit8u enable_set_reset = BX_CIRRUS_THIS s.graphics_ctrl.enable_set_reset; + /* perform rotate on CPU data in case its needed */ + if (BX_CIRRUS_THIS s.graphics_ctrl.data_rotate) { + value = (value >> BX_CIRRUS_THIS s.graphics_ctrl.data_rotate) | + (value << (8 - BX_CIRRUS_THIS s.graphics_ctrl.data_rotate)); + } + new_val[0] = BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & ~bitmask; + new_val[1] = BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & ~bitmask; + new_val[2] = BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & ~bitmask; + new_val[3] = BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & ~bitmask; + switch (BX_CIRRUS_THIS s.graphics_ctrl.raster_op) { + case 0: // replace + new_val[0] |= ((enable_set_reset & 1) + ? ((set_reset & 1) ? bitmask : 0) + : (value & bitmask)); + new_val[1] |= ((enable_set_reset & 2) + ? ((set_reset & 2) ? bitmask : 0) + : (value & bitmask)); + new_val[2] |= ((enable_set_reset & 4) + ? ((set_reset & 4) ? bitmask : 0) + : (value & bitmask)); + new_val[3] |= ((enable_set_reset & 8) + ? ((set_reset & 8) ? bitmask : 0) + : (value & bitmask)); + break; + case 1: // AND + new_val[0] |= ((enable_set_reset & 1) + ? ((set_reset & 1) + ? (BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & bitmask) + : 0) + : (value & BX_CIRRUS_THIS s.graphics_ctrl.latch[0]) & bitmask); + new_val[1] |= ((enable_set_reset & 2) + ? ((set_reset & 2) + ? (BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & bitmask) + : 0) + : (value & BX_CIRRUS_THIS s.graphics_ctrl.latch[1]) & bitmask); + new_val[2] |= ((enable_set_reset & 4) + ? ((set_reset & 4) + ? (BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & bitmask) + : 0) + : (value & BX_CIRRUS_THIS s.graphics_ctrl.latch[2]) & bitmask); + new_val[3] |= ((enable_set_reset & 8) + ? ((set_reset & 8) + ? (BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & bitmask) + : 0) + : (value & BX_CIRRUS_THIS s.graphics_ctrl.latch[3]) & bitmask); + break; + case 2: // OR + new_val[0] + |= ((enable_set_reset & 1) + ? ((set_reset & 1) + ? bitmask + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & bitmask)) + : ((value | BX_CIRRUS_THIS s.graphics_ctrl.latch[0]) & bitmask)); + new_val[1] + |= ((enable_set_reset & 2) + ? ((set_reset & 2) + ? bitmask + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & bitmask)) + : ((value | BX_CIRRUS_THIS s.graphics_ctrl.latch[1]) & bitmask)); + new_val[2] + |= ((enable_set_reset & 4) + ? ((set_reset & 4) + ? bitmask + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & bitmask)) + : ((value | BX_CIRRUS_THIS s.graphics_ctrl.latch[2]) & bitmask)); + new_val[3] + |= ((enable_set_reset & 8) + ? ((set_reset & 8) + ? bitmask + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & bitmask)) + : ((value | BX_CIRRUS_THIS s.graphics_ctrl.latch[3]) & bitmask)); + break; + case 3: // XOR + new_val[0] + |= ((enable_set_reset & 1) + ? ((set_reset & 1) + ? (~BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & bitmask) + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & bitmask)) + : (value ^ BX_CIRRUS_THIS s.graphics_ctrl.latch[0]) & bitmask); + new_val[1] + |= ((enable_set_reset & 2) + ? ((set_reset & 2) + ? (~BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & bitmask) + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & bitmask)) + : (value ^ BX_CIRRUS_THIS s.graphics_ctrl.latch[1]) & bitmask); + new_val[2] + |= ((enable_set_reset & 4) + ? ((set_reset & 4) + ? (~BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & bitmask) + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & bitmask)) + : (value ^ BX_CIRRUS_THIS s.graphics_ctrl.latch[2]) & bitmask); + new_val[3] + |= ((enable_set_reset & 8) + ? ((set_reset & 8) + ? (~BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & bitmask) + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & bitmask)) + : (value ^ BX_CIRRUS_THIS s.graphics_ctrl.latch[3]) & bitmask); + break; + default: + BX_PANIC(("vga_mem_write: write mode 0: op = %u", + (unsigned) BX_CIRRUS_THIS s.graphics_ctrl.raster_op)); + } + } + break; + + case 1: /* write mode 1 */ + for (i=0; i<4; i++) { + new_val[i] = BX_CIRRUS_THIS s.graphics_ctrl.latch[i]; + } + if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x0c) == 0x0c) { + for (i=0; i<4; i++) { + new_val[i + 4] = BX_CIRRUS_THIS ext_latch[i]; + } + } + break; + + case 2: /* write mode 2 */ + { + const Bit8u bitmask = BX_CIRRUS_THIS s.graphics_ctrl.bitmask; + + new_val[0] = BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & ~bitmask; + new_val[1] = BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & ~bitmask; + new_val[2] = BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & ~bitmask; + new_val[3] = BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & ~bitmask; + switch (BX_CIRRUS_THIS s.graphics_ctrl.raster_op) { + case 0: // write + new_val[0] |= (value & 1) ? bitmask : 0; + new_val[1] |= (value & 2) ? bitmask : 0; + new_val[2] |= (value & 4) ? bitmask : 0; + new_val[3] |= (value & 8) ? bitmask : 0; + break; + case 1: // AND + new_val[0] |= (value & 1) + ? (BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & bitmask) + : 0; + new_val[1] |= (value & 2) + ? (BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & bitmask) + : 0; + new_val[2] |= (value & 4) + ? (BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & bitmask) + : 0; + new_val[3] |= (value & 8) + ? (BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & bitmask) + : 0; + break; + case 2: // OR + new_val[0] |= (value & 1) + ? bitmask + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & bitmask); + new_val[1] |= (value & 2) + ? bitmask + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & bitmask); + new_val[2] |= (value & 4) + ? bitmask + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & bitmask); + new_val[3] |= (value & 8) + ? bitmask + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & bitmask); + break; + case 3: // XOR + new_val[0] |= (value & 1) + ? (~BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & bitmask) + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & bitmask); + new_val[1] |= (value & 2) + ? (~BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & bitmask) + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & bitmask); + new_val[2] |= (value & 4) + ? (~BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & bitmask) + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & bitmask); + new_val[3] |= (value & 8) + ? (~BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & bitmask) + : (BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & bitmask); + break; + } + } + break; + + case 3: /* write mode 3 */ + { + const Bit8u bitmask = BX_CIRRUS_THIS s.graphics_ctrl.bitmask & value; + const Bit8u set_reset = BX_CIRRUS_THIS s.graphics_ctrl.set_reset; + + /* perform rotate on CPU data */ + if (BX_CIRRUS_THIS s.graphics_ctrl.data_rotate) { + value = (value >> BX_CIRRUS_THIS s.graphics_ctrl.data_rotate) | + (value << (8 - BX_CIRRUS_THIS s.graphics_ctrl.data_rotate)); + } + new_val[0] = BX_CIRRUS_THIS s.graphics_ctrl.latch[0] & ~bitmask; + new_val[1] = BX_CIRRUS_THIS s.graphics_ctrl.latch[1] & ~bitmask; + new_val[2] = BX_CIRRUS_THIS s.graphics_ctrl.latch[2] & ~bitmask; + new_val[3] = BX_CIRRUS_THIS s.graphics_ctrl.latch[3] & ~bitmask; + + value &= bitmask; + + switch (BX_CIRRUS_THIS s.graphics_ctrl.raster_op) { + case 0: // write + new_val[0] |= (set_reset & 1) ? value : 0; + new_val[1] |= (set_reset & 2) ? value : 0; + new_val[2] |= (set_reset & 4) ? value : 0; + new_val[3] |= (set_reset & 8) ? value : 0; + break; + case 1: // AND + new_val[0] |= ((set_reset & 1) ? value : 0) + & BX_CIRRUS_THIS s.graphics_ctrl.latch[0]; + new_val[1] |= ((set_reset & 2) ? value : 0) + & BX_CIRRUS_THIS s.graphics_ctrl.latch[1]; + new_val[2] |= ((set_reset & 4) ? value : 0) + & BX_CIRRUS_THIS s.graphics_ctrl.latch[2]; + new_val[3] |= ((set_reset & 8) ? value : 0) + & BX_CIRRUS_THIS s.graphics_ctrl.latch[3]; + break; + case 2: // OR + new_val[0] |= ((set_reset & 1) ? value : 0) + | BX_CIRRUS_THIS s.graphics_ctrl.latch[0]; + new_val[1] |= ((set_reset & 2) ? value : 0) + | BX_CIRRUS_THIS s.graphics_ctrl.latch[1]; + new_val[2] |= ((set_reset & 4) ? value : 0) + | BX_CIRRUS_THIS s.graphics_ctrl.latch[2]; + new_val[3] |= ((set_reset & 8) ? value : 0) + | BX_CIRRUS_THIS s.graphics_ctrl.latch[3]; + break; + case 3: // XOR + new_val[0] |= ((set_reset & 1) ? value : 0) + ^ BX_CIRRUS_THIS s.graphics_ctrl.latch[0]; + new_val[1] |= ((set_reset & 2) ? value : 0) + ^ BX_CIRRUS_THIS s.graphics_ctrl.latch[1]; + new_val[2] |= ((set_reset & 4) ? value : 0) + ^ BX_CIRRUS_THIS s.graphics_ctrl.latch[2]; + new_val[3] |= ((set_reset & 8) ? value : 0) + ^ BX_CIRRUS_THIS s.graphics_ctrl.latch[3]; + break; + } + } + break; + + default: + BX_PANIC(("vga_mem_write: write mode %u ?", + (unsigned) BX_CIRRUS_THIS s.graphics_ctrl.write_mode)); + } + + if (sequ_map_mask & 0x0f) { + BX_CIRRUS_THIS s.vga_mem_updated |= (sequ_map_mask & 0x0f); + if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x04) == 0x04) { + if (sequ_map_mask & 0x80) + BX_CIRRUS_THIS s.memory[offset << 2] = new_val[0]; + if (sequ_map_mask & 0x40) + BX_CIRRUS_THIS s.memory[(offset << 2) + 1] = new_val[1]; + if (sequ_map_mask & 0x20) + BX_CIRRUS_THIS s.memory[(offset << 2) + 2] = new_val[2]; + if (sequ_map_mask & 0x10) + BX_CIRRUS_THIS s.memory[(offset << 2) + 3] = new_val[3]; + if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x08) == 0x08) { + if (sequ_map_mask & 0x08) + BX_CIRRUS_THIS s.memory[(offset << 2) + 4] = new_val[4]; + if (sequ_map_mask & 0x04) + BX_CIRRUS_THIS s.memory[(offset << 2) + 5] = new_val[5]; + if (sequ_map_mask & 0x02) + BX_CIRRUS_THIS s.memory[(offset << 2) + 6] = new_val[6]; + if (sequ_map_mask & 0x01) + BX_CIRRUS_THIS s.memory[(offset << 2) + 7] = new_val[7]; + } + } else { + if (sequ_map_mask & 0x01) + BX_CIRRUS_THIS s.memory[offset << 2] = new_val[0]; + if (sequ_map_mask & 0x02) + BX_CIRRUS_THIS s.memory[(offset << 2) + 1] = new_val[1]; + if (sequ_map_mask & 0x04) + BX_CIRRUS_THIS s.memory[(offset << 2) + 2] = new_val[2]; + if (sequ_map_mask & 0x08) + BX_CIRRUS_THIS s.memory[(offset << 2) + 3] = new_val[3]; + } + + if (BX_CIRRUS_THIS s.graphics_ctrl.graphics_alpha) { + unsigned x_tileno, y_tileno; + if (BX_CIRRUS_THIS s.line_offset > 0) { + if (BX_CIRRUS_THIS s.line_compare < BX_CIRRUS_THIS s.vertical_display_end) { + if (BX_CIRRUS_THIS s.x_dotclockdiv2) { + x_tileno = (offset % BX_CIRRUS_THIS s.line_offset) / (X_TILESIZE / 16); + } else { + x_tileno = (offset % BX_CIRRUS_THIS s.line_offset) / (X_TILESIZE / 8); + } + if (BX_CIRRUS_THIS s.y_doublescan) { + y_tileno = ((offset / BX_CIRRUS_THIS s.line_offset) * 2 + BX_CIRRUS_THIS s.line_compare + 1) / Y_TILESIZE; + } else { + y_tileno = ((offset / BX_CIRRUS_THIS s.line_offset) + BX_CIRRUS_THIS s.line_compare + 1) / Y_TILESIZE; + } + SET_TILE_UPDATED(BX_CIRRUS_THIS, x_tileno, y_tileno, 1); + } + if (offset >= start_addr) { + offset -= start_addr; + if (BX_CIRRUS_THIS s.x_dotclockdiv2) { + x_tileno = (offset % BX_CIRRUS_THIS s.line_offset) / (X_TILESIZE / 16); + } else { + x_tileno = (offset % BX_CIRRUS_THIS s.line_offset) / (X_TILESIZE / 8); + } + if (BX_CIRRUS_THIS s.y_doublescan) { + y_tileno = (offset / BX_CIRRUS_THIS s.line_offset) / (Y_TILESIZE / 2); + } else { + y_tileno = (offset / BX_CIRRUS_THIS s.line_offset) / Y_TILESIZE; + } + SET_TILE_UPDATED(BX_CIRRUS_THIS, x_tileno, y_tileno, 1); + } + } + } } } @@ -1094,6 +1545,7 @@ void bx_svga_cirrus_c::draw_hardware_cursor(unsigned xc, unsigned yc, bx_svga_ti Bit8u * plane0_ptr, *plane0_ptr2; Bit8u * plane1_ptr, *plane1_ptr2; unsigned long fgcol, bgcol; + Bit32u hwc_offset; Bit64u plane0, plane1; cx0 = hwcx > xc ? hwcx : xc; @@ -1104,7 +1556,12 @@ void bx_svga_cirrus_c::draw_hardware_cursor(unsigned xc, unsigned yc, bx_svga_ti if (info->bpp == 15) info->bpp = 16; tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h) + info->pitch * (cy0 - yc) + (info->bpp / 8) * (cx0 - xc); - plane0_ptr = BX_CIRRUS_THIS s.memory + BX_CIRRUS_THIS s.memsize - 16384; + if (BX_CIRRUS_THIS svga_dispbpp == 4) { + hwc_offset = 0x40000 - 16384; // VGA (TODO: check this) + } else { + hwc_offset = BX_CIRRUS_THIS memsize_mask - 16383; // Cirrus + } + plane0_ptr = BX_CIRRUS_THIS s.memory + hwc_offset; switch (size) { case 32: @@ -1137,7 +1594,7 @@ void bx_svga_cirrus_c::draw_hardware_cursor(unsigned xc, unsigned yc, bx_svga_ti } else { // FIXME: this is a hack that works in Windows guests // TODO: compare hidden DAC entries with DAC entries to find nearest match - fgcol = 0xff; + fgcol = (BX_CIRRUS_THIS svga_dispbpp == 4) ? 0x3f : 0xff; bgcol = 0x00; } @@ -1215,25 +1672,40 @@ void bx_svga_cirrus_c::update(void) BX_CIRRUS_THIS s.vga_mem_updated = 0x0f; BX_CIRRUS_THIS svga_needs_update_mode = 0; } - BX_CIRRUS_THIS bx_vgacore_c::update(); - return; + if ((BX_CIRRUS_THIS s.graphics_ctrl.shift_reg != 0) || + (BX_CIRRUS_THIS hw_cursor.size == 0)) { + BX_CIRRUS_THIS bx_vgacore_c::update(); + return; + } else { + BX_CIRRUS_THIS svga_dispbpp = 4; + BX_CIRRUS_THIS svga_needs_update_tile = 1; + } } else { if (BX_CIRRUS_THIS svga_needs_update_mode) { svga_modeupdate(); } } - width = BX_CIRRUS_THIS svga_xres; - height = BX_CIRRUS_THIS svga_yres; - pitch = BX_CIRRUS_THIS svga_pitch; - - if (BX_CIRRUS_THIS svga_needs_update_mode) { + if (BX_CIRRUS_THIS svga_dispbpp != 4) { width = BX_CIRRUS_THIS svga_xres; height = BX_CIRRUS_THIS svga_yres; - bx_gui->dimension_update(width, height, 0, 0, BX_CIRRUS_THIS svga_dispbpp); - BX_CIRRUS_THIS s.last_bpp = BX_CIRRUS_THIS svga_dispbpp; - BX_CIRRUS_THIS svga_needs_update_mode = 0; - BX_CIRRUS_THIS svga_needs_update_dispentire = 1; + pitch = BX_CIRRUS_THIS svga_pitch; + if (BX_CIRRUS_THIS svga_needs_update_mode) { + bx_gui->dimension_update(width, height, 0, 0, BX_CIRRUS_THIS svga_dispbpp); + BX_CIRRUS_THIS s.last_bpp = BX_CIRRUS_THIS svga_dispbpp; + BX_CIRRUS_THIS svga_needs_update_mode = 0; + BX_CIRRUS_THIS svga_needs_update_dispentire = 1; + } + } else { + BX_CIRRUS_THIS determine_screen_dimensions(&height, &width); + pitch = BX_CIRRUS_THIS s.line_offset; + if ((width != BX_CIRRUS_THIS s.last_xres) || (height != BX_CIRRUS_THIS s.last_yres) || + (BX_CIRRUS_THIS s.last_bpp > 8)) { + bx_gui->dimension_update(width, height); + BX_CIRRUS_THIS s.last_xres = width; + BX_CIRRUS_THIS s.last_yres = height; + BX_CIRRUS_THIS s.last_bpp = 8; + } } if (BX_CIRRUS_THIS svga_needs_update_dispentire) { @@ -1247,10 +1719,10 @@ void bx_svga_cirrus_c::update(void) BX_CIRRUS_THIS svga_needs_update_tile = 0; unsigned xc, yc, xti, yti; - unsigned r, c, w, h; + unsigned r, c, w, h, x, y; int i; Bit8u red, green, blue; - Bit32u colour; + Bit32u colour, row_addr; Bit8u * vid_ptr, * vid_ptr2; Bit8u * tile_ptr, * tile_ptr2; bx_svga_tileinfo_t info; @@ -1261,14 +1733,44 @@ void bx_svga_cirrus_c::update(void) tile_ptr = bx_gui->get_snapshot_buffer(); if (tile_ptr != NULL) { for (yc = 0; yc < height; yc++) { - memcpy(tile_ptr, vid_ptr, info.pitch); - vid_ptr += pitch; + if (BX_CIRRUS_THIS svga_dispbpp != 4) { + memcpy(tile_ptr, vid_ptr, info.pitch); + vid_ptr += pitch; + } else { + tile_ptr2 = tile_ptr; + row_addr = BX_CIRRUS_THIS s.CRTC.start_addr + (yc * pitch); + for (xc = 0; xc < width; xc++) { + *(tile_ptr2++) = BX_CIRRUS_THIS get_vga_pixel(xc, yc, row_addr, 0xffff, 0, BX_CIRRUS_THIS s.memory); + } + } tile_ptr += info.pitch; } } } else if (info.is_indexed) { switch (BX_CIRRUS_THIS svga_dispbpp) { case 4: + for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); + for (r=0; r>= 1; + row_addr = BX_CIRRUS_THIS s.CRTC.start_addr + (y * pitch); + tile_ptr2 = tile_ptr; + for (c=0; cgraphics_tile_update_in_place(xc, yc, w, h); + SET_TILE_UPDATED(BX_CIRRUS_THIS, xti, yti, 0); + } + } + } + break; case 15: case 16: case 24: @@ -1316,7 +1818,40 @@ void bx_svga_cirrus_c::update(void) else { switch (BX_CIRRUS_THIS svga_dispbpp) { case 4: - BX_ERROR(("cannot draw 4bpp SVGA")); + for (yc=0, yti=0; ycgraphics_tile_get(xc, yc, &w, &h); + for (r=0; r>= 1; + row_addr = BX_CIRRUS_THIS s.CRTC.start_addr + (y * pitch); + for (c=0; c> i; + } + } else { + for (i=info.bpp-8; i>-8; i-=8) { + *(tile_ptr2++) = colour >> i; + } + } + } + tile_ptr += info.pitch; + } + draw_hardware_cursor(xc, yc, &info); + bx_gui->graphics_tile_update_in_place(xc, yc, w, h); + SET_TILE_UPDATED(BX_CIRRUS_THIS, xti, yti, 0); + } + } + } break; case 8: for (yc=0, yti = 0; yc> 3); - BX_CIRRUS_THIS redraw.y = offset / BX_CIRRUS_THIS bitblt.dstpitch; + if (BX_CIRRUS_THIS bitblt.dstpitch > 0) { + BX_CIRRUS_THIS redraw.x = (offset % BX_CIRRUS_THIS bitblt.dstpitch) / (BX_CIRRUS_THIS svga_bpp >> 3); + BX_CIRRUS_THIS redraw.y = offset / BX_CIRRUS_THIS bitblt.dstpitch; + } else { + BX_CIRRUS_THIS redraw.x = 0; + BX_CIRRUS_THIS redraw.y = 0; + } BX_CIRRUS_THIS redraw.w = BX_CIRRUS_THIS bitblt.bltwidth / (BX_CIRRUS_THIS svga_bpp >> 3); BX_CIRRUS_THIS redraw.h = BX_CIRRUS_THIS bitblt.bltheight; if (BX_CIRRUS_THIS s.y_doublescan) { diff --git a/bochs/iodev/display/svga_cirrus.h b/bochs/iodev/display/svga_cirrus.h index 5777a6a089..f4e580cabf 100644 --- a/bochs/iodev/display/svga_cirrus.h +++ b/bochs/iodev/display/svga_cirrus.h @@ -91,6 +91,8 @@ class bx_svga_cirrus_c : public bx_vgacore_c Bit32u svga_read(Bit32u address, unsigned io_len); void svga_write(Bit32u address, Bit32u value, unsigned io_len); #endif + BX_CIRRUS_SMF Bit8u vga_mem_read(bx_phy_address addr); + BX_CIRRUS_SMF void vga_mem_write(bx_phy_address addr, Bit8u value); BX_CIRRUS_SMF void mem_write_mode4and5_8bpp(Bit8u mode, Bit32u offset, Bit8u value); BX_CIRRUS_SMF void mem_write_mode4and5_16bpp(Bit8u mode, Bit32u offset, Bit8u value); @@ -206,6 +208,7 @@ class bx_svga_cirrus_c : public bx_vgacore_c Bit32u bank_limit[2]; Bit32u memsize_mask; Bit8u *disp_ptr; + Bit8u ext_latch[4]; struct { bx_bitblt_rop_t rop_handler; diff --git a/bochs/iodev/display/vga.cc b/bochs/iodev/display/vga.cc index 7f026140fc..cb518b5948 100644 --- a/bochs/iodev/display/vga.cc +++ b/bochs/iodev/display/vga.cc @@ -1135,12 +1135,12 @@ Bit32u bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len) } else { BX_VGA_THIS s.ext_offset = (BX_VGA_THIS vbe.bank[0] << 16); } - BX_VGA_THIS s.memsize_mask = BX_VGA_THIS s.memsize - 1; + BX_VGA_THIS s.vgamem_mask = BX_VGA_THIS s.memsize - 1; } else if (((value & VBE_DISPI_ENABLED) == 0) && BX_VGA_THIS vbe.enabled) { BX_INFO(("VBE disabling")); BX_VGA_THIS s.text_buffer_update = true; BX_VGA_THIS s.ext_offset = 0; - BX_VGA_THIS s.memsize_mask = 0x3ffff; + BX_VGA_THIS s.vgamem_mask = 0x3ffff; } BX_VGA_THIS vbe.enabled = ((value & VBE_DISPI_ENABLED) != 0); BX_VGA_THIS vbe.get_capabilities = ((value & VBE_DISPI_GETCAPS) != 0); diff --git a/bochs/iodev/display/vgacore.cc b/bochs/iodev/display/vgacore.cc index fb7f7d36bb..a50c8d4ad1 100644 --- a/bochs/iodev/display/vgacore.cc +++ b/bochs/iodev/display/vgacore.cc @@ -44,7 +44,7 @@ static const Bit32u text_snap_size[4] = { 0x20000, 0x10000, 0x8000, 0x8000 }; -static const Bit8u ccdat[16][4] = { +const Bit8u ccdat[16][4] = { { 0x00, 0x00, 0x00, 0x00 }, { 0xff, 0x00, 0x00, 0x00 }, { 0x00, 0xff, 0x00, 0x00 }, @@ -107,7 +107,7 @@ void bx_vgacore_c::init(void) BX_VGA_THIS s.memory = new Bit8u[BX_VGA_THIS s.memsize]; memset(BX_VGA_THIS s.memory, 0, BX_VGA_THIS s.memsize); } - BX_VGA_THIS s.memsize_mask = 0x3ffff; + BX_VGA_THIS s.vgamem_mask = 0x3ffff; BX_VGA_THIS init_gui(); BX_VGA_THIS s.num_x_tiles = BX_VGA_THIS s.max_xres / X_TILESIZE + @@ -358,7 +358,7 @@ void bx_vgacore_c::vgacore_register_state(bx_list_c *parent) new bx_shadow_num_c(list, "last_bpp", &BX_VGA_THIS s.last_bpp); new bx_shadow_num_c(list, "last_fw", &BX_VGA_THIS s.last_fw); new bx_shadow_num_c(list, "last_fh", &BX_VGA_THIS s.last_fh); - new bx_shadow_num_c(list, "memsize_mask", &BX_VGA_THIS s.memsize_mask); + new bx_shadow_num_c(list, "vgamem_mask", &BX_VGA_THIS s.vgamem_mask); BXRS_PARAM_BOOL(list, vga_override, BX_VGA_THIS s.vga_override); new bx_shadow_data_c(list, "memory", BX_VGA_THIS s.memory, BX_VGA_THIS s.memsize); } @@ -427,7 +427,7 @@ void bx_vgacore_c::calculate_retrace_timing() } cwidth = ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 1) ? 8 : 9; hfreq = (float)vclock / (crtcp.htotal * cwidth); - f_htotal_usec = 1000000.0 / hfreq; + f_htotal_usec = 1000000.0f / hfreq; BX_VGA_THIS s.htotal_usec = (Bit32u)f_htotal_usec; hbstart = BX_VGA_THIS s.CRTC.reg[2]; BX_VGA_THIS s.hbstart_usec = (Bit32u)((1000000.0 * hbstart * cwidth) / vclock); @@ -1236,7 +1236,7 @@ Bit8u bx_vgacore_c::get_vga_pixel(Bit16u x, Bit16u y, Bit32u raddr, Bit16u lc, b x += BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning; } bit_no = 7 - (x % 8); - byte_offset = ((raddr + (x / 8)) << 2) & BX_VGA_THIS s.memsize_mask; + byte_offset = ((raddr + (x / 8)) << 2) & BX_VGA_THIS s.vgamem_mask; attribute = (((vgamem_ptr[byte_offset] >> bit_no) & 0x01) << 0) | (((vgamem_ptr[byte_offset + 1] >> bit_no) & 0x01) << 1) | @@ -1609,9 +1609,9 @@ void bx_vgacore_c::update(void) tm_info.blink_flags |= BX_TEXT_BLINK_MODE; if (cs_toggle) tm_info.blink_flags |= BX_TEXT_BLINK_TOGGLE; - if (cs_visible) - tm_info.blink_flags |= BX_TEXT_BLINK_STATE; } + if (cs_visible) + tm_info.blink_flags |= BX_TEXT_BLINK_STATE; if ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 0) { if (tm_info.h_panning >= 8) tm_info.h_panning = 0; @@ -1731,7 +1731,7 @@ Bit8u bx_vgacore_c::mem_read(bx_phy_address addr) offset = addr & 0x1FFFF; } } else { - offset = addr; + offset = (Bit32u)addr; } if (BX_VGA_THIS s.sequencer.chain_four) { @@ -1830,7 +1830,7 @@ void bx_vgacore_c::mem_write(bx_phy_address addr, Bit8u value) offset = addr & 0x1FFFF; } } else { - offset = addr; + offset = (Bit32u)addr; } start_addr = BX_VGA_THIS s.CRTC.start_addr; @@ -2279,8 +2279,8 @@ void bx_vgacore_c::debug_dump(int argc, char **argv) (unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol); dbg_printf("s.misc_output.vert_sync_pol = %u ", (unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol); - switch ((BX_VGA_THIS s.misc_output.vert_sync_pol << 1) | - BX_VGA_THIS s.misc_output.horiz_sync_pol) { + switch (((int)BX_VGA_THIS s.misc_output.vert_sync_pol << 1) | + (int)BX_VGA_THIS s.misc_output.horiz_sync_pol) { case 1: dbg_printf("(400 lines)\n"); break; case 2: dbg_printf("(350 lines)\n"); break; case 3: dbg_printf("(480 lines)\n"); break; diff --git a/bochs/iodev/display/vgacore.h b/bochs/iodev/display/vgacore.h index db4d402b07..2736a1be0b 100644 --- a/bochs/iodev/display/vgacore.h +++ b/bochs/iodev/display/vgacore.h @@ -67,6 +67,8 @@ typedef struct { Bit16u vrstart; } bx_crtc_params_t; +extern const Bit8u ccdat[16][4]; + #if BX_SUPPORT_PCI class bx_nonvga_device_c : public bx_pci_device_c { public: @@ -236,7 +238,7 @@ class bx_vgacore_c : public bx_vga_stub_c { bool *vga_tile_updated; Bit8u *memory; Bit32u memsize; - Bit32u memsize_mask; + Bit32u vgamem_mask; bool text_buffer_update; Bit8u *text_buffer; // active text memory in legacy format Bit8u *text_snapshot; // current text snapshot diff --git a/bochs/iodev/display/voodoo.cc b/bochs/iodev/display/voodoo.cc index e0fbbd403f..a648a1357f 100644 --- a/bochs/iodev/display/voodoo.cc +++ b/bochs/iodev/display/voodoo.cc @@ -556,7 +556,7 @@ void bx_voodoo_base_c::redraw_area(unsigned x0, unsigned y0, unsigned width, void bx_voodoo_base_c::update(void) { Bit32u start; - unsigned iHeight, iWidth; + unsigned iHeight, iWidth, riHeight, riWidth; unsigned pitch, xc, yc, xti, yti; unsigned r, c, w, h; int i; @@ -597,7 +597,24 @@ void bx_voodoo_base_c::update(void) } iWidth = s.vdraw.width; iHeight = s.vdraw.height; - Bit8u *disp_ptr = &v->fbi.ram[start & v->fbi.mask]; + if (v->banshee.half_mode) { + riHeight = iHeight / 2; + if (v->banshee.double_width) { + riWidth = iWidth / 2; + } else { + riWidth = iWidth; + } + } else { + riHeight = iHeight; + riWidth = iWidth; + } + start &= v->fbi.mask; + Bit8u *disp_ptr = &v->fbi.ram[start]; + if ((start + pitch * (riHeight - 1) + riWidth) > (v->fbi.mask + 1)) { + BX_ERROR(("skip address wrap during update() (start = 0x%08x)", start)); + BX_UNLOCK(render_mutex); + return; + } if (bx_gui->graphics_tile_info_common(&info)) { if (info.snapshot_mode) { @@ -1174,7 +1191,7 @@ Bit32u bx_voodoo_1_2_c::get_retrace(bool hv) Bit32u bx_voodoo_1_2_c::get_vtotal_usec(void) { - return s.vdraw.vtotal_usec; + return (Bit32u)s.vdraw.vtotal_usec; } void bx_voodoo_1_2_c::output_enable(bool enabled) diff --git a/bochs/iodev/display/voodoo_data.h b/bochs/iodev/display/voodoo_data.h index 3bde87c411..5f5a29cb1d 100644 --- a/bochs/iodev/display/voodoo_data.h +++ b/bochs/iodev/display/voodoo_data.h @@ -1509,7 +1509,9 @@ struct _cmdfifo_info Bit32u depth; /* current depth */ Bit32u depth_needed; /* depth needed for command */ Bit32u holes; /* number of holes */ + Bit32u retAddr; bool cmd_ready; + bool jsr; }; diff --git a/bochs/iodev/display/voodoo_func.h b/bochs/iodev/display/voodoo_func.h index c8ce83c5be..685cb21342 100644 --- a/bochs/iodev/display/voodoo_func.h +++ b/bochs/iodev/display/voodoo_func.h @@ -2471,7 +2471,6 @@ Bit32u lfb_w(Bit32u offset, Bit32u data, Bit32u mem_mask) { Bit16u *dest, *depth; Bit32u destmax, depthmax; - Bit32u forcefront=0; int sr[2], sg[2], sb[2], sa[2], sw[2]; int x, y, scry, mask; @@ -2679,7 +2678,7 @@ Bit32u lfb_w(Bit32u offset, Bit32u data, Bit32u mem_mask) mask &= ~(0xf0 + LFB_DEPTH_PRESENT_MSW); /* select the target buffer */ - destbuf = (v->type >= VOODOO_BANSHEE) ? (!forcefront) : LFBMODE_WRITE_BUFFER_SELECT(v->reg[lfbMode].u); + destbuf = (v->type >= VOODOO_BANSHEE) ? 1 : LFBMODE_WRITE_BUFFER_SELECT(v->reg[lfbMode].u); switch (destbuf) { case 0: /* front buffer */ @@ -2691,6 +2690,8 @@ Bit32u lfb_w(Bit32u offset, Bit32u data, Bit32u mem_mask) case 1: /* back buffer */ dest = (Bit16u *)(v->fbi.ram + v->fbi.rgboffs[v->fbi.backbuf]); destmax = (v->fbi.mask + 1 - v->fbi.rgboffs[v->fbi.backbuf]) / 2; + if (v->fbi.rgboffs[v->fbi.frontbuf] == v->fbi.rgboffs[v->fbi.backbuf]) + v->fbi.video_changed = 1; break; default: /* reserved */ @@ -2936,11 +2937,13 @@ Bit32u cmdfifo_r(cmdfifo_info *f) data = *(Bit32u*)(&v->fbi.ram[f->rdptr & v->fbi.mask]); f->rdptr += 4; - if (f->rdptr >= f->end) { - BX_INFO(("CMDFIFO RdPtr rollover")); - f->rdptr = f->base; + if (!f->jsr) { + if (f->rdptr >= f->end) { + BX_INFO(("CMDFIFO RdPtr rollover")); + f->rdptr = f->base; + } + f->depth--; } - f->depth--; return data; } @@ -2961,6 +2964,24 @@ void cmdfifo_process(cmdfifo_info *f) switch (code) { case 0: // NOP break; + case 1: // JSR + if (f->jsr) { + BX_ERROR(("cmdfifo_process(): JSR: already inside of subroutine")); + } else { + f->jsr = true; + f->retAddr = f->rdptr; + f->rdptr = (command >> 4) & 0xfffffc; + } + break; + case 2: // RET + if (!f->jsr) { + BX_ERROR(("cmdfifo_process(): RET: not inside of subroutine")); + } else { + f->rdptr = f->retAddr; + f->retAddr = 0; + f->jsr = false; + } + break; case 3: // JMP f->rdptr = (command >> 4) & 0xfffffc; if (f->count_holes) { @@ -3209,7 +3230,7 @@ void cmdfifo_process(cmdfifo_info *f) BX_ERROR(("CMDFIFO: unsupported packet type %d", type)); } f->depth_needed = cmdfifo_calc_depth_needed(f); - if (f->depth < f->depth_needed) { + if (!f->jsr && f->depth < f->depth_needed) { f->cmd_ready = 0; } } diff --git a/bochs/iodev/gameport.cc b/bochs/iodev/gameport.cc index 3d076598af..eb57bc0d7a 100644 --- a/bochs/iodev/gameport.cc +++ b/bochs/iodev/gameport.cc @@ -32,7 +32,7 @@ #ifdef __linux__ -#ifndef ANDROID +#ifndef __ANDROID__ #include #endif #include @@ -136,7 +136,7 @@ void bx_gameport_c::register_state(void) void bx_gameport_c::poll_joydev(void) { -#ifndef ANDROID +#ifndef __ANDROID__ #ifdef __linux__ struct js_event e; fd_set joyfds; @@ -181,7 +181,7 @@ void bx_gameport_c::poll_joydev(void) BX_GAMEPORT_THIS delay_y = 25 + (joypos.wYpos / 60); } #endif -#endif //ANDROID +#endif //__ANDROID__ } // static IO port read callback handler diff --git a/bochs/iodev/harddrv.cc b/bochs/iodev/harddrv.cc index dec55160d8..eceef8299a 100644 --- a/bochs/iodev/harddrv.cc +++ b/bochs/iodev/harddrv.cc @@ -3373,7 +3373,7 @@ bool bx_hard_drive_c::bmdma_present(void) { #if BX_SUPPORT_PCI if (BX_HD_THIS pci_enabled) { - #ifndef ANDROID + #ifndef __ANDROID__ // DMA emulation works very bad under Android return DEV_ide_bmdma_present(); #endif diff --git a/bochs/iodev/iodev.h b/bochs/iodev/iodev.h index 321a896c9b..6360187ca2 100644 --- a/bochs/iodev/iodev.h +++ b/bochs/iodev/iodev.h @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2021 The Bochs Project +// Copyright (C) 2001-2024 The Bochs Project // // I/O port handlers API Copyright (C) 2003 by Frank Cornelis // @@ -173,9 +173,6 @@ class BOCHSAPI bx_pci_device_c : public bx_devmodel_c { void set_name(const char *name) {pci_name = name;} const char* get_name(void) {return pci_name;} -#if BX_USE_WIN32USBDEBUG - Bit32u get_bar_addr(int indx) const { return pci_bar[indx].addr; } -#endif protected: const char *pci_name; diff --git a/bochs/iodev/network/Makefile.in b/bochs/iodev/network/Makefile.in index 4dbb0638b3..acf97d54a5 100644 --- a/bochs/iodev/network/Makefile.in +++ b/bochs/iodev/network/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2021 The Bochs Project +# Copyright (C) 2012-2024 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -59,14 +59,19 @@ SLIRP_OBJS = \ slirp/arp_table.o \ slirp/bootp.o \ slirp/cksum.o \ - slirp/compat.o \ + slirp/dhcpv6.o \ slirp/dnssearch.o \ slirp/if.o \ + slirp/ip6_icmp.o \ + slirp/ip6_input.o \ + slirp/ip6_output.o \ slirp/ip_icmp.o \ slirp/ip_input.o \ slirp/ip_output.o \ slirp/mbuf.o \ slirp/misc.o \ + slirp/ncsi.o \ + slirp/ndp_table.o \ slirp/sbuf.o \ slirp/slirp.o \ slirp/socket.o \ @@ -75,7 +80,9 @@ SLIRP_OBJS = \ slirp/tcp_subr.o \ slirp/tcp_timer.o \ slirp/tftp.o \ - slirp/udp.o + slirp/udp.o \ + slirp/udp6.o \ + slirp/util.o BX_INCDIRS = -I.. -I../.. -I$(srcdir)/.. -I$(srcdir)/../.. -I../../@INSTRUMENT_DIR@ -I$(srcdir)/../../@INSTRUMENT_DIR@ LOCAL_CXXFLAGS = $(MCH_CFLAGS) @@ -87,8 +94,8 @@ OBJS_THAT_CAN_BE_PLUGINS = \ $(NETLOW_OBJS) OBJS_THAT_SUPPORT_OTHER_PLUGINS = \ - netutil.o \ - $(SLIRP_OBJS) + @SLIRP_OBJS@ \ + netutil.o NONPLUGIN_OBJS = @IODEV_EXT_NON_PLUGIN_OBJS@ PLUGIN_OBJS = @IODEV_EXT_PLUGIN_OBJS@ @@ -120,8 +127,8 @@ libbx_%.la: %.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module $< -o $@ -rpath $(PLUGIN_PATH) # special link rules for plugins that require more than one object file -libbx_eth_slirp.la: eth_slirp.lo $(SLIRP_OBJS:.o=.lo) - $(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module eth_slirp.lo $(SLIRP_OBJS:.o=.lo) -o libbx_eth_slirp.la -rpath $(PLUGIN_PATH) +libbx_eth_slirp.la: eth_slirp.lo @SLIRP_OBJS2@ + $(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module eth_slirp.lo @SLIRP_OBJS2@ -o libbx_eth_slirp.la -rpath $(PLUGIN_PATH) @SLIRP_LINK_OPTS@ libbx_eth_vnet.la: eth_vnet.lo netutil.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module eth_vnet.lo netutil.lo -o libbx_eth_vnet.la -rpath $(PLUGIN_PATH) @@ -134,8 +141,8 @@ bx_%.dll: %.o bx_eth_null.dll: eth_null.o @LINK_DLL@ eth_null.o $(WIN32_DLL_IMPORT_LIBRARY) -bx_eth_slirp.dll: eth_slirp.o $(SLIRP_OBJS) - @LINK_DLL@ eth_slirp.o $(SLIRP_OBJS) $(WIN32_DLL_IMPORT_LIBRARY) $(NETMOD_LINK_OPTS@LINK_VAR@) +bx_eth_slirp.dll: eth_slirp.o @SLIRP_OBJS@ + @LINK_DLL@ eth_slirp.o @SLIRP_OBJS@ $(WIN32_DLL_IMPORT_LIBRARY) $(NETMOD_LINK_OPTS@LINK_VAR@) bx_eth_socket.dll: eth_socket.o @LINK_DLL@ eth_socket.o $(WIN32_DLL_IMPORT_LIBRARY) $(NETMOD_LINK_OPTS@LINK_VAR@) @@ -175,382 +182,424 @@ dist-clean: clean # building plugins. ########################################### e1000.o: e1000.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../param_names.h \ - ../../pc_system.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h ../../gui/gui.h \ - ../pci.h netmod.h e1000.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../param_names.h ../../pc_system.h ../../bx_debug/debug.h \ + ../../config.h ../../osdep.h ../../memory/memory-bochs.h \ + ../../gui/siminterface.h ../../gui/paramtree.h ../../gui/gui.h ../pci.h \ + netmod.h e1000.h eth_fbsd.o: eth_fbsd.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_linux.o: eth_linux.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_null.o: eth_null.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_slirp.o: eth_slirp.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h slirp/slirp.h ../../config.h slirp/slirp_config.h slirp/debug.h \ - slirp/libslirp.h slirp/compat.h ../../qemu-queue.h slirp/ip.h \ - slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ - slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h slirp/if.h \ - slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h slirp/libslirp.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h slirp/libslirp.h eth_socket.o: eth_socket.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_tap.o: eth_tap.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_tuntap.o: eth_tuntap.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_vde.o: eth_vde.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_vnet.o: eth_vnet.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h netutil.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h netutil.h eth_win32.o: eth_win32.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h ne2k.o: ne2k.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../param_names.h \ - ../../pc_system.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h ../../gui/gui.h \ - ../pci.h ne2k.h netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../param_names.h ../../pc_system.h ../../bx_debug/debug.h \ + ../../config.h ../../osdep.h ../../memory/memory-bochs.h \ + ../../gui/siminterface.h ../../gui/paramtree.h ../../gui/gui.h ../pci.h \ + ne2k.h netmod.h netmod.o: netmod.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ - ../../gui/siminterface.h netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../gui/siminterface.h ../../gui/paramtree.h netmod.h netutil.o: netutil.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../pc_system.h netmod.h netutil.h + ../../logio.h ../../misc/bswap.h ../../pc_system.h netmod.h netutil.h pcipnic.o: pcipnic.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ - ../../osdep.h ../../gui/paramtree.h ../../logio.h \ - ../../instrument/stubs/instrument.h ../../misc/bswap.h ../../plugin.h \ + ../../osdep.h ../../logio.h ../../misc/bswap.h ../../plugin.h \ ../../extplugin.h ../../param_names.h ../../pc_system.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h ../../gui/gui.h + ../../memory/memory-bochs.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../gui/gui.h slirp/arp_table.o: slirp/arp_table.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ - slirp/tftp.h -slirp/bootp.o: slirp/bootp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/cksum.o: slirp/cksum.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/compat.o: slirp/compat.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/bootp.o: slirp/bootp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/cksum.o: slirp/cksum.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h +slirp/dhcpv6.o: slirp/dhcpv6.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h slirp/dhcpv6.h slirp/dnssearch.o: slirp/dnssearch.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ - slirp/tftp.h -slirp/if.o: slirp/if.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h \ - ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../param_names.h \ - ../../pc_system.h ../../bx_debug/debug.h ../../osdep.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h ../../gui/gui.h -slirp/ip_icmp.o: slirp/ip_icmp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ - slirp/tftp.h -slirp/ip_input.o: slirp/ip_input.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/if.o: slirp/if.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ip6_icmp.o: slirp/ip6_icmp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ip6_input.o: slirp/ip6_input.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ip6_output.o: slirp/ip6_output.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ip_icmp.o: slirp/ip_icmp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ip_input.o: slirp/ip_input.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h slirp/ip_output.o: slirp/ip_output.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ - slirp/tftp.h -slirp/mbuf.o: slirp/mbuf.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/misc.o: slirp/misc.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/sbuf.o: slirp/sbuf.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/slirp.o: slirp/slirp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h \ - ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../param_names.h \ - ../../pc_system.h ../../bx_debug/debug.h ../../osdep.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h ../../gui/gui.h -slirp/socket.o: slirp/socket.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/mbuf.o: slirp/mbuf.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/misc.o: slirp/misc.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ncsi.o: slirp/ncsi.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h slirp/ncsi-pkt.h +slirp/ndp_table.o: slirp/ndp_table.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/sbuf.o: slirp/sbuf.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/slirp.o: slirp/slirp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/socket.o: slirp/socket.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h slirp/tcp_input.o: slirp/tcp_input.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h slirp/tcp_output.o: slirp/tcp_output.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h -slirp/tcp_subr.o: slirp/tcp_subr.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ +slirp/tcp_subr.o: slirp/tcp_subr.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h slirp/tcp_timer.o: slirp/tcp_timer.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ - slirp/tftp.h -slirp/tftp.o: slirp/tftp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/udp.o: slirp/udp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/tftp.o: slirp/tftp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/udp6.o: slirp/udp6.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h slirp/dhcpv6.h +slirp/udp.o: slirp/udp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/util.o: slirp/util.@CPP_SUFFIX@ ../../config.h slirp/util.h slirp/libslirp.h \ + slirp/compat.h e1000.lo: e1000.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../param_names.h \ - ../../pc_system.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h ../../gui/gui.h \ - ../pci.h netmod.h e1000.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../param_names.h ../../pc_system.h ../../bx_debug/debug.h \ + ../../config.h ../../osdep.h ../../memory/memory-bochs.h \ + ../../gui/siminterface.h ../../gui/paramtree.h ../../gui/gui.h ../pci.h \ + netmod.h e1000.h eth_fbsd.lo: eth_fbsd.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_linux.lo: eth_linux.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_null.lo: eth_null.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_slirp.lo: eth_slirp.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h slirp/slirp.h ../../config.h slirp/slirp_config.h slirp/debug.h \ - slirp/libslirp.h slirp/compat.h ../../qemu-queue.h slirp/ip.h \ - slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ - slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h slirp/if.h \ - slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h slirp/libslirp.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h slirp/libslirp.h eth_socket.lo: eth_socket.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_tap.lo: eth_tap.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_tuntap.lo: eth_tuntap.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_vde.lo: eth_vde.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h eth_vnet.lo: eth_vnet.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h netutil.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h netutil.h eth_win32.lo: eth_win32.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ - netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../pc_system.h netmod.h ne2k.lo: ne2k.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../param_names.h \ - ../../pc_system.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h ../../gui/gui.h \ - ../pci.h ne2k.h netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../param_names.h ../../pc_system.h ../../bx_debug/debug.h \ + ../../config.h ../../osdep.h ../../memory/memory-bochs.h \ + ../../gui/siminterface.h ../../gui/paramtree.h ../../gui/gui.h ../pci.h \ + ne2k.h netmod.h netmod.lo: netmod.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ - ../../gui/siminterface.h netmod.h + ../../logio.h ../../misc/bswap.h ../../plugin.h ../../extplugin.h \ + ../../gui/siminterface.h ../../gui/paramtree.h netmod.h netutil.lo: netutil.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../pc_system.h netmod.h netutil.h + ../../logio.h ../../misc/bswap.h ../../pc_system.h netmod.h netutil.h pcipnic.lo: pcipnic.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ - ../../osdep.h ../../gui/paramtree.h ../../logio.h \ - ../../instrument/stubs/instrument.h ../../misc/bswap.h ../../plugin.h \ + ../../osdep.h ../../logio.h ../../misc/bswap.h ../../plugin.h \ ../../extplugin.h ../../param_names.h ../../pc_system.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h ../../gui/gui.h + ../../memory/memory-bochs.h ../../gui/siminterface.h \ + ../../gui/paramtree.h ../../gui/gui.h slirp/arp_table.lo: slirp/arp_table.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ - slirp/tftp.h -slirp/bootp.lo: slirp/bootp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/cksum.lo: slirp/cksum.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/compat.lo: slirp/compat.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/bootp.lo: slirp/bootp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/cksum.lo: slirp/cksum.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h +slirp/dhcpv6.lo: slirp/dhcpv6.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h slirp/dhcpv6.h slirp/dnssearch.lo: slirp/dnssearch.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ - slirp/tftp.h -slirp/if.lo: slirp/if.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h \ - ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../param_names.h \ - ../../pc_system.h ../../bx_debug/debug.h ../../osdep.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h ../../gui/gui.h -slirp/ip_icmp.lo: slirp/ip_icmp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ - slirp/tftp.h -slirp/ip_input.lo: slirp/ip_input.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/if.lo: slirp/if.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ip6_icmp.lo: slirp/ip6_icmp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ip6_input.lo: slirp/ip6_input.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ip6_output.lo: slirp/ip6_output.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ip_icmp.lo: slirp/ip_icmp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ip_input.lo: slirp/ip_input.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h slirp/ip_output.lo: slirp/ip_output.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ - slirp/tftp.h -slirp/mbuf.lo: slirp/mbuf.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/misc.lo: slirp/misc.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/sbuf.lo: slirp/sbuf.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/slirp.lo: slirp/slirp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h \ - ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ - ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ - ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../param_names.h \ - ../../pc_system.h ../../bx_debug/debug.h ../../osdep.h \ - ../../memory/memory-bochs.h ../../gui/siminterface.h ../../gui/gui.h -slirp/socket.lo: slirp/socket.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/mbuf.lo: slirp/mbuf.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/misc.lo: slirp/misc.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/ncsi.lo: slirp/ncsi.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h slirp/ncsi-pkt.h +slirp/ndp_table.lo: slirp/ndp_table.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/sbuf.lo: slirp/sbuf.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/slirp.lo: slirp/slirp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/socket.lo: slirp/socket.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h slirp/tcp_input.lo: slirp/tcp_input.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h slirp/tcp_output.lo: slirp/tcp_output.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h -slirp/tcp_subr.lo: slirp/tcp_subr.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ +slirp/tcp_subr.lo: slirp/tcp_subr.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ slirp/tftp.h slirp/tcp_timer.lo: slirp/tcp_timer.@CPP_SUFFIX@ slirp/slirp.h ../../config.h \ - slirp/slirp_config.h slirp/debug.h slirp/libslirp.h slirp/compat.h \ - ../../qemu-queue.h slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h \ - slirp/tcp_timer.h slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h \ - slirp/socket.h slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h \ - slirp/tftp.h -slirp/tftp.lo: slirp/tftp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h -slirp/udp.lo: slirp/udp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/slirp_config.h \ - slirp/debug.h slirp/libslirp.h slirp/compat.h ../../qemu-queue.h \ - slirp/ip.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ - slirp/udp.h slirp/ip_icmp.h slirp/mbuf.h slirp/sbuf.h slirp/socket.h \ - slirp/if.h slirp/main.h slirp/misc.h slirp/bootp.h slirp/tftp.h + slirp/compat.h slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h \ + slirp/ip6.h slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h \ + slirp/udp.h slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/tftp.lo: slirp/tftp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/udp6.lo: slirp/udp6.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h slirp/dhcpv6.h +slirp/udp.lo: slirp/udp.@CPP_SUFFIX@ slirp/slirp.h ../../config.h slirp/compat.h \ + slirp/debug.h slirp/util.h slirp/libslirp.h slirp/ip.h slirp/ip6.h \ + slirp/tcp.h slirp/tcp_var.h slirp/tcpip.h slirp/tcp_timer.h slirp/udp.h \ + slirp/socket.h slirp/misc.h slirp/sbuf.h slirp/ip_icmp.h \ + slirp/ip6_icmp.h slirp/mbuf.h slirp/if.h slirp/main.h slirp/bootp.h \ + slirp/tftp.h +slirp/util.lo: slirp/util.@CPP_SUFFIX@ ../../config.h slirp/util.h slirp/libslirp.h \ + slirp/compat.h diff --git a/bochs/iodev/network/eth_slirp.cc b/bochs/iodev/network/eth_slirp.cc index c8304de7d7..735f1b2817 100644 --- a/bochs/iodev/network/eth_slirp.cc +++ b/bochs/iodev/network/eth_slirp.cc @@ -1,8 +1,6 @@ ///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2014-2021 The Bochs Project +// Copyright (C) 2014-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -19,7 +17,8 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // -// eth_slirp.cc - Bochs port of Qemu's slirp implementation +// eth_slirp.cc - Bochs port of Qemu's slirp implementation (updated from libslirp 4.8.0) +// Portion of this software comes with the following license: BSD-3-Clause #define BX_PLUGGABLE @@ -35,8 +34,37 @@ #if BX_NETWORKING && BX_NETMOD_SLIRP -#include "slirp/slirp.h" +#ifdef _WIN32 +/* as defined in sdkddkver.h */ +#ifdef _WIN32_WINNT +#if _WIN32_WINNT < 0x0601 +#undef _WIN32_WINNT +#endif +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0601 /* Windows 7 */ +#endif +/* reduces the number of implicitly included headers */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#endif + +#if defined(_MSC_VER) +#define CPP_STD _MSVC_LANG +#else +#define CPP_STD __cplusplus +#endif + +#if BX_HAVE_LIBSLIRP +#include +#ifdef __MINGW32__ +typedef ssize_t slirp_ssize_t; +#endif +#else #include "slirp/libslirp.h" +#endif +#include static unsigned int bx_slirp_instances = 0; @@ -60,13 +88,6 @@ static int rx_timer_index = BX_NULL_TIMER_HANDLE; fd_set rfds, wfds, xfds; int nfds; -extern int slirp_hostfwd(Slirp *s, const char *redir_str, int legacy_format); -#ifndef WIN32 -extern int slirp_smb(Slirp *s, char *smb_tmpdir, const char *exported_dir, - struct in_addr vserver_addr); -void slirp_smb_cleanup(Slirp *s, char *smb_tmpdir); -#endif - class bx_slirp_pktmover_c : public eth_pktmover_c { public: bx_slirp_pktmover_c(const char *netif, const char *macaddr, @@ -74,27 +95,36 @@ class bx_slirp_pktmover_c : public eth_pktmover_c { logfunctions *netdev, const char *script); virtual ~bx_slirp_pktmover_c(); void sendpkt(void *buf, unsigned io_len); - void receive(void *pkt, unsigned pkt_len); - int can_receive(void); + slirp_ssize_t receive(void *pkt, unsigned pkt_len); + void slirp_msg(bool error, const char *msg); private: Slirp *slirp; unsigned netdev_speed; - int restricted; - struct in_addr net, mask, host, dhcp, dns; - char *bootfile, *hostname, **dnssearch; + SlirpConfig config; char *hostfwd[MAX_HOSTFWD]; int n_hostfwd; #ifndef WIN32 char *smb_export, *smb_tmpdir; struct in_addr smb_srv; #endif + bool slirp_logging; + Bit8u debug_switches; char *pktlog_fn; FILE *pktlog_txt; - bool slirp_logging; + + logfunctions *slirplog; bool parse_slirp_conf(const char *conf); static void rx_timer_handler(void *); + void rx_timer(void); + +#ifndef WIN32 + int slirp_smb(Slirp *s, char *smb_tmpdir, const char *exported_dir, + struct in_addr vserver_addr); + void slirp_smb_cleanup(Slirp *s, char *smb_tmpdir); +#endif + int slirp_hostfwd(Slirp *s, const char *redir_str, int legacy_format); }; class bx_slirp_locator_c : public eth_locator_c { @@ -109,6 +139,241 @@ class bx_slirp_locator_c : public eth_locator_c { } bx_slirp_match; +static slirp_ssize_t send_packet(const void *buf, size_t len, void *opaque) +{ + bx_slirp_pktmover_c *class_ptr = (bx_slirp_pktmover_c *)opaque; + + return class_ptr->receive((void*)buf, (unsigned)len); +} + +static void guest_error(const char *msg, void *opaque) +{ + char errmsg[512]; + + sprintf(errmsg, "guest error: %s", msg); + ((bx_slirp_pktmover_c*)opaque)->slirp_msg(true, errmsg); +} + +static int64_t clock_get_ns(void *opaque) +{ + return bx_pc_system.time_usec() * 1000; +} + +struct timer { + SlirpTimerId id; + void *cb_opaque; + int64_t expire; + struct timer *next; +}; + +static struct timer *timer_queue; + +static void *timer_new_opaque(SlirpTimerId id, void *cb_opaque, void *opaque) +{ + ((bx_slirp_pktmover_c*)opaque)->slirp_msg(false, "timer_new_opaque()"); + struct timer *new_timer = new timer; + new_timer->id = id; + new_timer->cb_opaque = cb_opaque; + new_timer->next = NULL; + return new_timer; +} + +static void timer_free(void *_timer, void *opaque) +{ + ((bx_slirp_pktmover_c*)opaque)->slirp_msg(false, "timer_free()"); + struct timer *timer1 = (timer*)_timer; + struct timer **t; + + for (t = &timer_queue; *t != NULL; *t = (*t)->next) { + if (*t == timer1) { + /* Not expired yet, drop it */ + *t = timer1->next; + break; + } + } + + delete [] timer1; +} + +static void timer_mod(void *_timer, int64_t expire_time, void *opaque) +{ + ((bx_slirp_pktmover_c*)opaque)->slirp_msg(false, "timer_mod()"); + struct timer *timer1 = (timer*)_timer; + struct timer **t; + + timer1->expire = expire_time * 1000 * 1000; + + for (t = &timer_queue; *t != NULL; *t = (*t)->next) { + if (expire_time < (*t)->expire) + break; + } + + timer1->next = *t; + *t = timer1; +} + +static int npoll; + +static void register_poll_fd(int fd, void *opaque) +{ + npoll++; +} + +static void unregister_poll_fd(int fd, void *opaque) +{ + npoll--; +} + +static void notify(void *opaque) +{ + // Nothing here yet +} + +#if CPP_STD >= 201703 +static struct SlirpCb callbacks = { + .send_packet = send_packet, + .guest_error = guest_error, + .clock_get_ns = clock_get_ns, + .timer_free = timer_free, + .timer_mod = timer_mod, + .register_poll_fd = register_poll_fd, + .unregister_poll_fd = unregister_poll_fd, + .notify = notify, + .timer_new_opaque = timer_new_opaque, +}; +#else +static struct SlirpCb callbacks; +#endif + +bx_slirp_pktmover_c::bx_slirp_pktmover_c(const char *netif, + const char *macaddr, + eth_rx_handler_t rxh, + eth_rx_status_t rxstat, + logfunctions *netdev, + const char *script) +{ + char prefix[10]; + + slirp = NULL; + pktlog_fn = NULL; + n_hostfwd = 0; +#if CPP_STD < 201703 + callbacks.send_packet = send_packet, + callbacks.guest_error = guest_error, + callbacks.clock_get_ns = clock_get_ns, + callbacks.timer_free = timer_free, + callbacks.timer_mod = timer_mod, + callbacks.register_poll_fd = register_poll_fd, + callbacks.unregister_poll_fd = unregister_poll_fd, + callbacks.notify = notify, + callbacks.timer_new_opaque = timer_new_opaque, +#endif + /* default settings according to historic slirp */ + memset(&config, 0, sizeof(config)); + config.version = 4; + config.in_enabled = true; + config.disable_host_loopback = false; + config.enable_emu = false; + config.disable_dns = false; + config.restricted = false; + config.vnetwork.s_addr = htonl(0x0a000200); /* 10.0.2.0 */ + config.vnetmask.s_addr = htonl(0xffffff00); /* 255.255.255.0 */ + config.vhost.s_addr = htonl(0x0a000202); /* 10.0.2.2 */ + config.vdhcp_start.s_addr = htonl(0x0a00020f); /* 10.0.2.15 */ + config.vnameserver.s_addr = htonl(0x0a000203); /* 10.0.2.3 */ + config.tftp_path = netif; + config.vdomainname = "local"; + /* enable IPv6 support by default using QEMU settings */ + config.in6_enabled = true; + inet_pton(AF_INET6, "fec0::", &config.vprefix_addr6); +#ifndef WIN32 + smb_export = NULL; + smb_tmpdir = NULL; + smb_srv.s_addr = 0; +#endif + + this->netdev = netdev; +#if BX_HAVE_LIBSLIRP + BX_INFO(("slirp network driver (libslirp version %s)", slirp_version_string())); +#else + BX_INFO(("slirp network driver (based on libslirp version %s)", slirp_version_string())); + debug_switches = 0; +#endif + + this->rxh = rxh; + this->rxstat = rxstat; + Bit32u status = this->rxstat(this->netdev) & BX_NETDEV_SPEED; + this->netdev_speed = (status == BX_NETDEV_1GBIT) ? 1000 : + (status == BX_NETDEV_100MBIT) ? 100 : 10; + if (bx_slirp_instances == 0) { + rx_timer_index = + DEV_register_timer(this, this->rx_timer_handler, 1000, 1, 1, + "eth_slirp"); +#ifndef WIN32 + signal(SIGPIPE, SIG_IGN); +#endif + } + + if ((strlen(script) > 0) && (strcmp(script, "none"))) { + if (!parse_slirp_conf(script)) { + BX_ERROR(("reading slirp config failed")); + } + if (config.in6_enabled) { + BX_INFO(("IPv6 enabled (using default QEMU settings)")); + config.vprefix_len = 64; + config.vhost6 = config.vprefix_addr6; + config.vhost6.s6_addr[15] |= 2; + config.vnameserver6 = config.vprefix_addr6; + config.vnameserver6.s6_addr[15] |= 3; + } + } + slirplog = new logfunctions(); + sprintf(prefix, "SLIRP%d", bx_slirp_instances); + slirplog->put(prefix); + slirp = slirp_new(&config, &callbacks, this); +#if !BX_HAVE_LIBSLIRP + if (debug_switches != 0) { + slirplog->setonoff(LOGLEV_DEBUG, ACT_REPORT); + } + slirp_set_logfn(slirp, slirplog, debug_switches); +#endif + if (n_hostfwd > 0) { + for (int i = 0; i < n_hostfwd; i++) { + slirp_hostfwd(slirp, hostfwd[i], 0); + } + } +#ifndef WIN32 + if (smb_export != NULL) { + smb_tmpdir = (char*)malloc(128); + if (slirp_smb(slirp, smb_tmpdir, smb_export, smb_srv) < 0) { + BX_ERROR(("failed to initialize SMB support")); + } + } +#endif + if (pktlog_fn != NULL) { + pktlog_txt = fopen(pktlog_fn, "wb"); + slirp_logging = (pktlog_txt != NULL); + if (slirp_logging) { + fprintf(pktlog_txt, "slirp packetmover readable log file\n"); + if (strlen(netif) > 0) { + fprintf(pktlog_txt, "TFTP root = %s\n", netif); + } else { + fprintf(pktlog_txt, "TFTP service disabled\n"); + } + fprintf(pktlog_txt, "guest MAC address = "); + int i; + for (i=0; i<6; i++) + fprintf(pktlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "\n"); + fprintf(pktlog_txt, "--\n"); + fflush(pktlog_txt); + } + free(pktlog_fn); + } else { + slirp_logging = 0; + } + bx_slirp_instances++; +} + bx_slirp_pktmover_c::~bx_slirp_pktmover_c() { if (slirp != NULL) { @@ -120,14 +385,15 @@ bx_slirp_pktmover_c::~bx_slirp_pktmover_c() free(smb_export); } #endif - if (bootfile != NULL) free(bootfile); - if (hostname != NULL) free(hostname); - if (dnssearch != NULL) { + if (config.bootfile != NULL) free((void*)config.bootfile); + if (config.vhostname != NULL) free((void*)config.vhostname); + if (config.tftp_server_name != NULL) free((void*)config.tftp_server_name); + if (config.vdnssearch != NULL) { size_t i = 0; - while (dnssearch[i] != NULL) { - free(dnssearch[i++]); + while (config.vdnssearch[i] != NULL) { + free((void*)config.vdnssearch[i++]); } - free(dnssearch); + free((void*)config.vdnssearch); } while (n_hostfwd > 0) { free(hostfwd[--n_hostfwd]); @@ -144,6 +410,31 @@ bx_slirp_pktmover_c::~bx_slirp_pktmover_c() } } +#if defined(WIN32) +#if !BX_HAVE_LIBSLIRP +#define inet_aton slirp_inet_aton +int slirp_inet_aton(const char *cp, struct in_addr *ia); +#else +int inet_aton(const char *cp, struct in_addr *ia) +{ + uint32_t addr; + +#if defined(_MSC_VER) + if (!inet_pton(AF_INET, cp, &addr)) { + return 0; + } +#else + addr = inet_addr(cp); +#endif + if (addr == 0xffffffff) { + return 0; + } + ia->s_addr = addr; + return 1; +} +#endif +#endif + bool bx_slirp_pktmover_c::parse_slirp_conf(const char *conf) { FILE *fd = NULL; @@ -187,18 +478,18 @@ bool bx_slirp_pktmover_c::parse_slirp_conf(const char *conf) len2 = strip_whitespace(val); if ((len1 == 0) || (len2 == 0)) continue; if (!stricmp(param, "restricted")) { - restricted = atoi(val); + config.restricted = atoi(val); } else if (!stricmp(param, "hostname")) { if (len2 < 33) { - hostname = (char*)malloc(len2+1); - strcpy(hostname, val); + config.vhostname = (char*)malloc(len2+1); + strcpy((char*)config.vhostname, val); } else { BX_ERROR(("slirp: wrong format for 'hostname'")); } } else if (!stricmp(param, "bootfile")) { if (len2 < 128) { - bootfile = (char*)malloc(len2+1); - strcpy(bootfile, val); + config.bootfile = (char*)malloc(len2+1); + strcpy((char*)config.bootfile, val); } else { BX_ERROR(("slirp: wrong format for 'bootfile'")); } @@ -208,38 +499,38 @@ bool bx_slirp_pktmover_c::parse_slirp_conf(const char *conf) for (i = 0; i < len2; i++) { if (val[i] == ',') count++; } - dnssearch = (char**)malloc((count + 1) * sizeof(char*)); + config.vdnssearch = (const char**)malloc((count + 1) * sizeof(char*)); i = 0; tmp = strtok(val, ","); while (tmp != NULL) { len2 = strip_whitespace(tmp); - dnssearch[i] = (char*)malloc(len2+1); - strcpy(dnssearch[i], tmp); + config.vdnssearch[i] = (char*)malloc(len2+1); + strcpy((char*)config.vdnssearch[i], tmp); i++; tmp = strtok(NULL, ","); } - dnssearch[i] = NULL; + config.vdnssearch[i] = NULL; } else { BX_ERROR(("slirp: wrong format for 'dnssearch'")); } } else if (!stricmp(param, "net")) { - if (!inet_aton(val, &net)) { + if (!inet_aton(val, &config.vnetwork)) { BX_ERROR(("slirp: wrong format for 'net'")); } } else if (!stricmp(param, "mask")) { - if (!inet_aton(val, &mask)) { + if (!inet_aton(val, &config.vnetmask)) { BX_ERROR(("slirp: wrong format for 'mask'")); } } else if (!stricmp(param, "host")) { - if (!inet_aton(val, &host)) { + if (!inet_aton(val, &config.vhost)) { BX_ERROR(("slirp: wrong format for 'host'")); } } else if (!stricmp(param, "dhcpstart")) { - if (!inet_aton(val, &dhcp)) { + if (!inet_aton(val, &config.vdhcp_start)) { BX_ERROR(("slirp: wrong format for 'dhcpstart'")); } } else if (!stricmp(param, "dns")) { - if (!inet_aton(val, &dns)) { + if (!inet_aton(val, &config.vnameserver)) { BX_ERROR(("slirp: wrong format for 'dns'")); } #ifndef WIN32 @@ -274,6 +565,21 @@ bool bx_slirp_pktmover_c::parse_slirp_conf(const char *conf) } else { BX_ERROR(("slirp: wrong format for 'pktlog'")); } + } else if (!stricmp(param, "ipv6_enabled")) { + config.in6_enabled = (atoi(val) != 0); + } else if (!stricmp(param, "ipv6_prefix")) { + inet_pton(AF_INET6, val, &config.vprefix_addr6); + } else if (!stricmp(param, "tftp_srvname")) { + if (len2 < 33) { + config.tftp_server_name = (char*)malloc(len2+1); + strcpy((char*)config.tftp_server_name, val); + } else { + BX_ERROR(("slirp: wrong format for 'tftp_srvname'")); + } +#if !BX_HAVE_LIBSLIRP + } else if (!stricmp(param, "debug_switches")) { + debug_switches = atoi(val); +#endif } else { BX_ERROR(("slirp: unknown option '%s'", line)); } @@ -284,102 +590,6 @@ bool bx_slirp_pktmover_c::parse_slirp_conf(const char *conf) return 1; } -bx_slirp_pktmover_c::bx_slirp_pktmover_c(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - eth_rx_status_t rxstat, - logfunctions *netdev, - const char *script) -{ - logfunctions *slirplog; - char prefix[10]; - - restricted = 0; - slirp = NULL; - hostname = NULL; - bootfile = NULL; - dnssearch = NULL; - pktlog_fn = NULL; - n_hostfwd = 0; - /* default settings according to historic slirp */ - net.s_addr = htonl(0x0a000200); /* 10.0.2.0 */ - mask.s_addr = htonl(0xffffff00); /* 255.255.255.0 */ - host.s_addr = htonl(0x0a000202); /* 10.0.2.2 */ - dhcp.s_addr = htonl(0x0a00020f); /* 10.0.2.15 */ - dns.s_addr = htonl(0x0a000203); /* 10.0.2.3 */ -#ifndef WIN32 - smb_export = NULL; - smb_tmpdir = NULL; - smb_srv.s_addr = 0; -#endif - - this->netdev = netdev; - if (sizeof(struct arphdr) != 28) { - BX_FATAL(("system error: invalid ARP header structure size")); - } - BX_INFO(("slirp network driver")); - - this->rxh = rxh; - this->rxstat = rxstat; - Bit32u status = this->rxstat(this->netdev) & BX_NETDEV_SPEED; - this->netdev_speed = (status == BX_NETDEV_1GBIT) ? 1000 : - (status == BX_NETDEV_100MBIT) ? 100 : 10; - if (bx_slirp_instances == 0) { - rx_timer_index = - DEV_register_timer(this, this->rx_timer_handler, 1000, 1, 1, - "eth_slirp"); -#ifndef WIN32 - signal(SIGPIPE, SIG_IGN); -#endif - } - - if ((strlen(script) > 0) && (strcmp(script, "none"))) { - if (!parse_slirp_conf(script)) { - BX_ERROR(("reading slirp config failed")); - } - } - slirplog = new logfunctions(); - sprintf(prefix, "SLIRP%d", bx_slirp_instances); - slirplog->put(prefix); - slirp = slirp_init(restricted, net, mask, host, hostname, netif, bootfile, dhcp, dns, - (const char**)dnssearch, this, slirplog); - if (n_hostfwd > 0) { - for (int i = 0; i < n_hostfwd; i++) { - slirp_hostfwd(slirp, hostfwd[i], 0); - } - } -#ifndef WIN32 - if (smb_export != NULL) { - smb_tmpdir = (char*)malloc(128); - if (slirp_smb(slirp, smb_tmpdir, smb_export, smb_srv) < 0) { - BX_ERROR(("failed to initialize SMB support")); - } - } -#endif - if (pktlog_fn != NULL) { - pktlog_txt = fopen(pktlog_fn, "wb"); - slirp_logging = (pktlog_txt != NULL); - if (slirp_logging) { - fprintf(pktlog_txt, "slirp packetmover readable log file\n"); - if (strlen(netif) > 0) { - fprintf(pktlog_txt, "TFTP root = %s\n", netif); - } else { - fprintf(pktlog_txt, "TFTP service disabled\n"); - } - fprintf(pktlog_txt, "guest MAC address = "); - int i; - for (i=0; i<6; i++) - fprintf(pktlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "\n"); - fprintf(pktlog_txt, "--\n"); - fflush(pktlog_txt); - } - free(pktlog_fn); - } else { - slirp_logging = 0; - } - bx_slirp_instances++; -} - void bx_slirp_pktmover_c::sendpkt(void *buf, unsigned io_len) { if (slirp_logging) { @@ -389,6 +599,37 @@ void bx_slirp_pktmover_c::sendpkt(void *buf, unsigned io_len) } void bx_slirp_pktmover_c::rx_timer_handler(void *this_ptr) +{ + ((bx_slirp_pktmover_c*)this_ptr)->rx_timer(); +} + + +static int add_poll_cb(int fd, int events, void *opaque) +{ + if (events & SLIRP_POLL_IN) + FD_SET(fd, &rfds); + if (events & SLIRP_POLL_OUT) + FD_SET(fd, &wfds); + if (events & SLIRP_POLL_PRI) + FD_SET(fd, &xfds); + if (nfds < fd) + nfds = fd; + return fd; +} + +static int get_revents_cb(int idx, void *opaque) +{ + int event = 0; + if (FD_ISSET(idx, &rfds)) + event |= SLIRP_POLL_IN; + if (FD_ISSET(idx, &wfds)) + event |= SLIRP_POLL_OUT; + if (FD_ISSET(idx, &xfds)) + event |= SLIRP_POLL_PRI; + return event; +} + +void bx_slirp_pktmover_c::rx_timer(void) { Bit32u timeout = 0; int ret; @@ -402,41 +643,247 @@ void bx_slirp_pktmover_c::rx_timer_handler(void *this_ptr) FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&xfds); - slirp_select_fill(&nfds, &rfds, &wfds, &xfds, &timeout); + slirp_pollfds_fill(slirp, &timeout, add_poll_cb, this); tv.tv_sec = 0; tv.tv_usec = 0; ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); - slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0)); + slirp_pollfds_poll(slirp, (ret < 0), get_revents_cb, this); } -int slirp_can_output(void *this_ptr) +slirp_ssize_t bx_slirp_pktmover_c::receive(void *pkt, unsigned pkt_len) { - bx_slirp_pktmover_c *class_ptr = (bx_slirp_pktmover_c *)this_ptr; - return class_ptr->can_receive(); + if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) { + if (pkt_len < MIN_RX_PACKET_LEN) pkt_len = MIN_RX_PACKET_LEN; + if (slirp_logging) { + write_pktlog_txt(pktlog_txt, (const Bit8u*)pkt, pkt_len, 1); + } + this->rxh(this->netdev, pkt, pkt_len); + return pkt_len; + } else { + BX_ERROR(("device not ready to receive data")); + return -1; + } } -int bx_slirp_pktmover_c::can_receive() +#if !defined(_WIN32) && !defined(__CYGWIN__) + +#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd" + +#include + +/* automatic user mode samba server configuration */ +int bx_slirp_pktmover_c::slirp_smb(Slirp *s, char *smb_tmpdir, const char *exported_dir, + struct in_addr vserver_addr) { - return ((this->rxstat(this->netdev) & BX_NETDEV_RXREADY) != 0); + static int instance; + int i; + char smb_conf[128], smb_cmdline[150]; + char share[64], error_msg[256]; + struct passwd *passwd; + FILE *f; + + passwd = getpwuid(geteuid()); + if (!passwd) { + BX_ERROR(("failed to retrieve user name")); + return -1; + } + + if (access(CONFIG_SMBD_COMMAND, F_OK)) { + BX_ERROR(("could not find '%s', please install it", CONFIG_SMBD_COMMAND)); + return -1; + } + + if (access(exported_dir, R_OK | X_OK)) { + snprintf(error_msg, sizeof(error_msg), "error accessing shared directory '%s': %s", + exported_dir, strerror(errno)); + BX_ERROR(("%s", error_msg)); + return -1; + } + + i = strlen(exported_dir) - 2; + while ((i > 0) && (exported_dir[i] != '/')) i--; + snprintf(share, sizeof(share), "%s", &exported_dir[i+1]); + if (share[strlen(share)-1] == '/') share[strlen(share)-1] = '\0'; + + snprintf(smb_tmpdir, 128, "/tmp/bochs-smb.%ld-%d", + (long)getpid(), instance++); + if (mkdir(smb_tmpdir, 0700) < 0) { + snprintf(error_msg, sizeof(error_msg), "could not create samba server dir '%s'", + smb_tmpdir); + BX_ERROR(("%s", error_msg)); + return -1; + } + snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_tmpdir, "smb.conf"); + + f = fopen(smb_conf, "w"); + if (!f) { + slirp_smb_cleanup(s, smb_tmpdir); + snprintf(error_msg, sizeof(error_msg), "could not create samba server configuration file '%s'", + smb_conf); + BX_ERROR(("%s", error_msg)); + return -1; + } + fprintf(f, + "[global]\n" + "private dir=%s\n" + "interfaces=127.0.0.1\n" + "bind interfaces only=yes\n" + "pid directory=%s\n" + "lock directory=%s\n" + "state directory=%s\n" + "cache directory=%s\n" + "ncalrpc dir=%s/ncalrpc\n" + "log file=%s/log.smbd\n" + "smb passwd file=%s/smbpasswd\n" + "security = user\n" + "map to guest = Bad User\n" + "[%s]\n" + "path=%s\n" + "read only=no\n" + "guest ok=yes\n" + "force user=%s\n", + smb_tmpdir, + smb_tmpdir, + smb_tmpdir, + smb_tmpdir, + smb_tmpdir, + smb_tmpdir, + smb_tmpdir, + smb_tmpdir, + share, + exported_dir, + passwd->pw_name + ); + fclose(f); + + snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s", + CONFIG_SMBD_COMMAND, smb_conf); + + if ((slirp_add_exec(s, smb_cmdline, &vserver_addr, 139) < 0) || + (slirp_add_exec(s, smb_cmdline, &vserver_addr, 445) < 0)) { + slirp_smb_cleanup(s, smb_tmpdir); + BX_ERROR(("conflicting/invalid smbserver address")); + return -1; + } + return 0; } -void slirp_output(void *this_ptr, const Bit8u *pkt, int pkt_len) +void bx_slirp_pktmover_c::slirp_smb_cleanup(Slirp *s, char *smb_tmpdir) { - bx_slirp_pktmover_c *class_ptr = (bx_slirp_pktmover_c *)this_ptr; - class_ptr->receive((void*)pkt, pkt_len); + char cmd[128]; + char error_msg[256]; + int ret; + + if (smb_tmpdir[0] != '\0') { + snprintf(cmd, sizeof(cmd), "rm -rf %s", smb_tmpdir); + ret = system(cmd); + if (ret == -1 || !WIFEXITED(ret)) { + snprintf(error_msg, sizeof(error_msg), "'%s' failed.", cmd); + BX_ERROR(("%s", error_msg)); + } else if (WEXITSTATUS(ret)) { + snprintf(error_msg, sizeof(error_msg), "'%s' failed. Error code: %d", + cmd, WEXITSTATUS(ret)); + BX_ERROR(("%s", error_msg)); + } + smb_tmpdir[0] = '\0'; + } } +#endif -void bx_slirp_pktmover_c::receive(void *pkt, unsigned pkt_len) +static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) { - if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) { - if (pkt_len < MIN_RX_PACKET_LEN) pkt_len = MIN_RX_PACKET_LEN; - if (slirp_logging) { - write_pktlog_txt(pktlog_txt, (const Bit8u*)pkt, pkt_len, 1); + const char *p, *p1; + int len; + p = *pp; + p1 = strchr(p, sep); + if (!p1) + return -1; + len = (int)(p1 - p); + p1++; + if (buf_size > 0) { + if (len > buf_size - 1) + len = buf_size - 1; + memcpy(buf, p, len); + buf[len] = '\0'; } - this->rxh(this->netdev, pkt, pkt_len); - } else { - BX_ERROR(("device not ready to receive data")); - } + *pp = p1; + return 0; +} + +int bx_slirp_pktmover_c::slirp_hostfwd(Slirp *s, const char *redir_str, int legacy_format) +{ + struct in_addr host_addr; + struct in_addr guest_addr; + int host_port, guest_port; + const char *p; + char buf[256]; + int is_udp; + char *end; + + host_addr.s_addr = INADDR_ANY; + guest_addr.s_addr = 0; + 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 (!legacy_format) { + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { + goto fail_syntax; + } + if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) { + goto fail_syntax; + } + } + + if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 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; + } + if (buf[0] != '\0' && !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_add_hostfwd(s, is_udp, host_addr, host_port, guest_addr, + guest_port) < 0) { + BX_ERROR(("could not set up host forwarding rule '%s'", redir_str)); + return -1; + } + return 0; + + fail_syntax: + BX_ERROR(("invalid host forwarding rule '%s'", redir_str)); + return -1; +} + +#undef LOG_THIS +#define LOG_THIS slirplog-> + +void bx_slirp_pktmover_c::slirp_msg(bool error, const char *msg) +{ + if (error) + BX_ERROR(("%s", msg)); + else + BX_INFO(("%s", msg)); } #endif /* if BX_NETWORKING && BX_NETMOD_SLIRP */ diff --git a/bochs/iodev/network/slirp/arp_table.cc b/bochs/iodev/network/slirp/arp_table.cc index ae52b7ffd0..254308508b 100644 --- a/bochs/iodev/network/slirp/arp_table.cc +++ b/bochs/iodev/network/slirp/arp_table.cc @@ -1,6 +1,4 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: MIT */ /* * ARP table * @@ -29,25 +27,25 @@ #if BX_NETWORKING && BX_NETMOD_SLIRP -void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]) +#include + +void arp_table_add(Slirp *slirp, uint32_t ip_addr, + const uint8_t ethaddr[ETH_ALEN]) { const uint32_t broadcast_addr = ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr; ArpTable *arptbl = &slirp->arp_table; int i; + char ethaddr_str[ETH_ADDRSTRLEN]; + char addr[INET_ADDRSTRLEN]; DEBUG_CALL("arp_table_add"); - DEBUG_ARG("ip = 0x%x", ip_addr); - DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n", - ethaddr[0], ethaddr[1], ethaddr[2], - ethaddr[3], ethaddr[4], ethaddr[5])); + DEBUG_ARG("ip = %s", inet_ntop(AF_INET, &ip_addr, + addr, sizeof(addr))); + DEBUG_ARG("hw addr = %s", slirp_ether_ntoa(ethaddr, ethaddr_str, + sizeof(ethaddr_str))); - /* Check 0.0.0.0/8 invalid source-only addresses */ - if ((ip_addr & htonl(~(0xfU << 28))) == 0) { - return; - } - - if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) { + if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) { /* Do not register broadcast addresses */ return; } @@ -63,7 +61,7 @@ void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]) /* No entry found, create a new one */ arptbl->table[arptbl->next_victim].ar_sip = ip_addr; - memcpy(arptbl->table[arptbl->next_victim].ar_sha, ethaddr, ETH_ALEN); + memcpy(arptbl->table[arptbl->next_victim].ar_sha, ethaddr, ETH_ALEN); arptbl->next_victim = (arptbl->next_victim + 1) % ARP_TABLE_SIZE; } @@ -74,15 +72,15 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr, ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr; ArpTable *arptbl = &slirp->arp_table; int i; + char ethaddr_str[ETH_ADDRSTRLEN]; + char addr[INET_ADDRSTRLEN]; DEBUG_CALL("arp_table_search"); - DEBUG_ARG("ip = 0x%x", ip_addr); - - /* Check 0.0.0.0/8 invalid source-only addresses */ - assert((ip_addr & htonl(~(0xfU << 28))) != 0); + DEBUG_ARG("ip = %s", inet_ntop(AF_INET, &ip_addr, + addr, sizeof(addr))); /* If broadcast address */ - if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) { + if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) { /* return Ethernet broadcast address */ memset(out_ethaddr, 0xff, ETH_ALEN); return 1; @@ -90,10 +88,10 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr, for (i = 0; i < ARP_TABLE_SIZE; i++) { if (arptbl->table[i].ar_sip == ip_addr) { - memcpy(out_ethaddr, arptbl->table[i].ar_sha, ETH_ALEN); - DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n", - out_ethaddr[0], out_ethaddr[1], out_ethaddr[2], - out_ethaddr[3], out_ethaddr[4], out_ethaddr[5])); + memcpy(out_ethaddr, arptbl->table[i].ar_sha, ETH_ALEN); + DEBUG_ARG("found hw addr = %s", + slirp_ether_ntoa(out_ethaddr, ethaddr_str, + sizeof(ethaddr_str))); return 1; } } diff --git a/bochs/iodev/network/slirp/bootp.cc b/bochs/iodev/network/slirp/bootp.cc index 22b989f299..2943fb9b3d 100644 --- a/bochs/iodev/network/slirp/bootp.cc +++ b/bochs/iodev/network/slirp/bootp.cc @@ -1,8 +1,6 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: MIT */ /* - * BOOTP/DHCP server (ported from Qemu) + * QEMU BOOTP/DHCP server * Bochs additions: parameter list and some other options * * Copyright (c) 2004 Fabrice Bellard @@ -25,11 +23,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ - #include "slirp.h" #if BX_NETWORKING && BX_NETMOD_SLIRP +#if defined(_WIN32) +/* Windows ntohl() returns an u_long value. + * Add a type cast to match the format strings. */ +#define ntohl(n) ((uint32_t)ntohl(n)) +#endif + /* XXX: only DHCP is supported */ #define LEASE_TIME (24 * 3600) @@ -44,14 +47,11 @@ typedef struct { uint32_t lease_time; } dhcp_options_t; +#define UEFI_HTTP_VENDOR_CLASS_ID "HTTPClient" + static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; -#ifdef DEBUG -#define DPRINTF(fmt, ...) \ -do if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## __VA_ARGS__); fflush(dfd); } while (0) -#else -#define DPRINTF(fmt, ...) do{}while(0) -#endif +#define DPRINTF(...) DEBUG_RAW_CALL(__VA_ARGS__) static BOOTPClient *get_new_addr(Slirp *slirp, struct in_addr *paddr, const uint8_t *macaddr) @@ -79,8 +79,7 @@ static BOOTPClient *request_addr(Slirp *slirp, const struct in_addr *paddr, uint32_t dhcp_addr = ntohl(slirp->vdhcp_startaddr.s_addr); BOOTPClient *bc; - if (req_addr >= dhcp_addr && - req_addr < (dhcp_addr + NB_BOOTP_CLIENTS)) { + if (req_addr >= dhcp_addr && req_addr < (dhcp_addr + NB_BOOTP_CLIENTS)) { bc = &slirp->bootp_clients[req_addr - dhcp_addr]; if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) { bc->allocated = 1; @@ -108,21 +107,21 @@ static BOOTPClient *find_addr(Slirp *slirp, struct in_addr *paddr, return bc; } -static void dhcp_decode(Slirp *slirp, const struct bootp_t *bp, dhcp_options_t *opts) +static void dhcp_decode(Slirp *slirp, const struct bootp_t *bp, + const uint8_t *bp_end, + dhcp_options_t *opts) { - const uint8_t *p, *p_end; + const uint8_t *p; uint16_t defsize, maxsize; int len, tag; - char msg[80]; memset(opts, 0, sizeof(dhcp_options_t)); p = bp->bp_vend; - p_end = p + DHCP_OPT_LEN; if (memcmp(p, rfc1533_cookie, 4) != 0) return; p += 4; - while (p < p_end) { + while (p < bp_end) { tag = p[0]; if (tag == RFC1533_PAD) { p++; @@ -130,10 +129,13 @@ static void dhcp_decode(Slirp *slirp, const struct bootp_t *bp, dhcp_options_t * break; } else { p++; - if (p >= p_end) + if (p >= bp_end) break; len = *p++; - DPRINTF("dhcp: tag=%d len=%d\n", tag, len); + if (p + len > bp_end) { + break; + } + DPRINTF("dhcp: tag=%d len=%d", tag, len); switch(tag) { case RFC2132_MSG_TYPE: @@ -174,16 +176,14 @@ static void dhcp_decode(Slirp *slirp, const struct bootp_t *bp, dhcp_options_t * case RFC2132_MAX_SIZE: if (len == 2) { memcpy(&maxsize, p, len); - defsize = sizeof(struct bootp_t) - sizeof(struct ip) - sizeof(struct udphdr); + defsize = sizeof(struct bootp_t) + DHCP_OPT_LEN - sizeof(struct ip) - sizeof(struct udphdr); if (ntohs(maxsize) < defsize) { - sprintf(msg, "DHCP server: RFB2132_MAX_SIZE=%u not supported yet", ntohs(maxsize)); - slirp_warning(slirp, msg); + slirplog_error("DHCP server: RFB2132_MAX_SIZE=%u not supported yet", ntohs(maxsize)); } } break; default: - sprintf(msg, "DHCP server: option %d not supported yet", tag); - slirp_warning(slirp, msg); + slirplog_error("DHCP server: option %d not supported yet", tag); break; } p += len; @@ -195,7 +195,9 @@ static void dhcp_decode(Slirp *slirp, const struct bootp_t *bp, dhcp_options_t * } } -static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) +static void bootp_reply(Slirp *slirp, + const struct bootp_t *bp, + const uint8_t *bp_end) { BOOTPClient *bc = NULL; struct mbuf *m; @@ -203,19 +205,16 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) struct sockaddr_in saddr, daddr; struct in_addr bcast_addr; int val; - uint8_t *q, *pp, plen; + uint8_t *q, *end, *pp, plen; uint8_t client_ethaddr[ETH_ALEN]; dhcp_options_t dhcp_opts; - size_t spaceleft; - char msg[80]; /* extract exact DHCP msg type */ - dhcp_decode(slirp, bp, &dhcp_opts); + dhcp_decode(slirp, bp, bp_end, &dhcp_opts); DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_opts.msg_type); - if (dhcp_opts.req_addr.s_addr != htonl(0L)) - DPRINTF(" req_addr=%08x\n", ntohl(dhcp_opts.req_addr.s_addr)); - else - DPRINTF("\n"); + if (dhcp_opts.req_addr.s_addr != htonl(0L)) { + DPRINTF(" req_addr=%08x", ntohl(dhcp_opts.req_addr.s_addr)); + } if (dhcp_opts.msg_type == 0) dhcp_opts.msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */ @@ -232,9 +231,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) return; } m->m_data += IF_MAXLINKHDR; + m_inc(m, sizeof(struct bootp_t) + DHCP_OPT_LEN); rbp = (struct bootp_t *)m->m_data; m->m_data += sizeof(struct udpiphdr); - memset(rbp, 0, sizeof(struct bootp_t)); + memset(rbp, 0, sizeof(struct bootp_t) + DHCP_OPT_LEN); if (dhcp_opts.msg_type == DHCPDISCOVER) { if (dhcp_opts.req_addr.s_addr != htonl(0L)) { @@ -247,7 +247,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) new_addr: bc = get_new_addr(slirp, &daddr.sin_addr, client_ethaddr); if (!bc) { - DPRINTF("no address left\n"); + DPRINTF("no address left"); return; } } @@ -288,11 +288,12 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ q = rbp->bp_vend; + end = rbp->bp_vend + DHCP_OPT_LEN; memcpy(q, rfc1533_cookie, 4); q += 4; if (bc) { - DPRINTF("%s addr=%08x\n", + DPRINTF("%s addr=%08x", (dhcp_opts.msg_type == DHCPDISCOVER) ? "offered" : "ack'ed", ntohl(daddr.sin_addr.s_addr)); @@ -327,7 +328,6 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) memcpy(q, &val, 4); } q += 4; - dhcp_opts.lease_time = 0; if (*slirp->client_hostname || (dhcp_opts.hostname != NULL)) { val = 0; if (*slirp->client_hostname) { @@ -353,8 +353,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) pp = dhcp_opts.params; plen = dhcp_opts.params_len; while (plen-- > 0) { - spaceleft = sizeof(rbp->bp_vend) - (q - rbp->bp_vend); - if (spaceleft < 6) break; + if (q + 6 >= end) break; switch (*pp++) { case RFC1533_NETMASK: *q++ = RFC1533_NETMASK; @@ -378,6 +377,19 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) q += 4; } break; + case RFC1533_DOMAINNAME: + if (slirp->vdomainname) { + val = strlen(slirp->vdomainname); + if (q + val + 2 >= end) { + slirplog_error("DHCP packet size exceeded, omitting domain name option."); + } else { + *q++ = RFC1533_DOMAINNAME; + *q++ = val; + memcpy(q, slirp->vdomainname, val); + q += val; + } + } + break; case RFC1533_INTBROADCAST: *q++ = RFC1533_INTBROADCAST; *q++ = 4; @@ -399,27 +411,62 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) memcpy(q, &val, 4); q += 4; break; + case RFC2132_TFTP_SERVER_NAME: + if (slirp->tftp_server_name) { + val = strlen(slirp->tftp_server_name); + if (q + val + 2 >= end) { + slirplog_error("DHCP packet size exceeded, omitting tftp-server-name option."); + } else { + *q++ = RFC2132_TFTP_SERVER_NAME; + *q++ = val; + memcpy(q, slirp->tftp_server_name, val); + q += val; + } + } + break; + case RFC1533_HOSTNAME: + case RFC2132_LEASE_TIME: + // Already handled on top of reply + break; default: - sprintf(msg, "DHCP server: requested parameter %u not supported yet", - *(pp-1)); - slirp_warning(slirp, msg); + slirplog_error("DHCP server: requested parameter %u not supported yet", + *(pp-1)); } } if (slirp->vdnssearch) { - spaceleft = sizeof(rbp->bp_vend) - (q - rbp->bp_vend); val = slirp->vdnssearch_len; - if (val + 1 > (int)spaceleft) { - slirp_warning(slirp, "DHCP packet size exceeded, omitting domain-search option."); + if (q + val >= end) { + slirplog_error("DHCP packet size exceeded, omitting domain-search option."); } else { memcpy(q, slirp->vdnssearch, val); q += val; } } + + /* this allows to support UEFI HTTP boot: according to the UEFI + specification, DHCP server must send vendor class identifier option + set to "HTTPClient" string, when responding to DHCP requests as part + of the UEFI HTTP boot + + we assume that, if the bootfile parameter was configured as an http + URL, the user intends to perform UEFI HTTP boot, so send this option + automatically */ + if (slirp->bootp_filename && !strncmp(slirp->bootp_filename, "http://", 7)) { + val = strlen(UEFI_HTTP_VENDOR_CLASS_ID); + if (q + val + 2 >= end) { + slirplog_error("DHCP packet size exceeded, omitting vendor class id option."); + } else { + *q++ = RFC2132_VENDOR_CLASS_ID; + *q++ = val; + memcpy(q, UEFI_HTTP_VENDOR_CLASS_ID, val); + q += val; + } + } } else { static const char nak_msg[] = "requested address not available"; - DPRINTF("nak'ed addr=%08x\n", ntohl(dhcp_opts.req_addr.s_addr)); + DPRINTF("nak'ed addr=%08x", ntohl(dhcp_opts.req_addr.s_addr)); *q++ = RFC2132_MSG_TYPE; *q++ = 1; @@ -436,17 +483,16 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) if (dhcp_opts.params != NULL) free(dhcp_opts.params); - m->m_len = sizeof(struct bootp_t) - - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + m->m_len = sizeof(struct bootp_t) + (end - rbp->bp_vend) - sizeof(struct ip) - sizeof(struct udphdr); + udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); } void bootp_input(struct mbuf *m) { - struct bootp_t *bp = mtod(m, struct bootp_t *); + struct bootp_t *bp = (struct bootp_t *)mtod_check(m, sizeof(struct bootp_t)); - if (bp->bp_op == BOOTP_REQUEST) { - bootp_reply(m->slirp, bp); + if (!m->slirp->disable_dhcp && bp && bp->bp_op == BOOTP_REQUEST) { + bootp_reply(m->slirp, bp, (uint8_t*)m_end(m)); } } diff --git a/bochs/iodev/network/slirp/bootp.h b/bochs/iodev/network/slirp/bootp.h index dc421d99a5..c5ece8f804 100644 --- a/bochs/iodev/network/slirp/bootp.h +++ b/bochs/iodev/network/slirp/bootp.h @@ -1,102 +1,102 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// - +/* SPDX-License-Identifier: BSD-3-Clause */ /* bootp/dhcp defines */ + #ifndef SLIRP_BOOTP_H -#define SLIRP_BOOTP_H 1 +#define SLIRP_BOOTP_H -#define BOOTP_SERVER 67 -#define BOOTP_CLIENT 68 +#define BOOTP_SERVER 67 +#define BOOTP_CLIENT 68 -#define BOOTP_REQUEST 1 -#define BOOTP_REPLY 2 +#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_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 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_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_MESSAGE 56 -#define RFC2132_MAX_SIZE 57 +#define RFC2132_MSG_TYPE 53 +#define RFC2132_SRV_ID 54 +#define RFC2132_PARAM_LIST 55 +#define RFC2132_MESSAGE 56 +#define RFC2132_MAX_SIZE 57 #define RFC2132_RENEWAL_TIME 58 #define RFC2132_REBIND_TIME 59 +#define RFC2132_VENDOR_CLASS_ID 60 +#define RFC2132_TFTP_SERVER_NAME 66 -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPACK 5 -#define DHCPNAK 6 +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPACK 5 +#define DHCPNAK 6 -#define RFC1533_VENDOR_MAJOR 0 -#define RFC1533_VENDOR_MINOR 0 +#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_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_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 +#define RFC1533_END 255 +#define BOOTP_VENDOR_LEN 64 +#define DHCP_OPT_LEN 312 struct bootp_t { struct ip ip; @@ -114,8 +114,8 @@ struct bootp_t { 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]; + char bp_file[128]; + uint8_t bp_vend[]; }; typedef struct { @@ -125,6 +125,7 @@ typedef struct { #define NB_BOOTP_CLIENTS 16 +/* Process a bootp packet from the guest */ void bootp_input(struct mbuf *m); #endif diff --git a/bochs/iodev/network/slirp/cksum.cc b/bochs/iodev/network/slirp/cksum.cc index 8ba8c5a08f..e40541cc52 100644 --- a/bochs/iodev/network/slirp/cksum.cc +++ b/bochs/iodev/network/slirp/cksum.cc @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1988, 1992, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,11 +27,10 @@ * 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 8.1 (Berkeley) 6/10/93 * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp */ -// NOTE: included in slirp.h #include "slirp.h" #if BX_NETWORKING && BX_NETMOD_SLIRP @@ -48,100 +45,139 @@ */ #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) -#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; \ - (void)ADDCARRY(sum);} +#define REDUCE \ + { \ + l_util.l = sum; \ + sum = l_util.s[0] + l_util.s[1]; \ + ADDCARRY(sum); \ + } int cksum(struct mbuf *m, int len) { - uint16_t *w; - int sum = 0; - int mlen = 0; - int byte_swapped = 0; - - union { - uint8_t c[2]; - uint16_t s; - } s_util; - union { - uint16_t s[2]; - uint32_t l; - } l_util; - - if (m->m_len == 0) - goto cont; - w = mtod(m, uint16_t *); - - mlen = m->m_len; - - if (len < mlen) - mlen = len; -#ifdef DEBUG - len -= mlen; -#endif - /* - * Force to even boundary. - */ - if ((1 & (uintptr_t)w) && (mlen > 0)) { - REDUCE; - sum <<= 8; - s_util.c[0] = *(uint8_t *)w; - w = (uint16_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; - if (mlen == -1) { - s_util.c[1] = *(uint8_t *)w; - sum += s_util.s; - mlen = 0; - } else - - mlen = -1; - } else if (mlen == -1) - s_util.c[0] = *(uint8_t *)w; + uint16_t *w; + int sum = 0; + int mlen = 0; + int byte_swapped = 0; + + union { + uint8_t c[2]; + uint16_t s; + } s_util; + union { + uint16_t s[2]; + uint32_t l; + } l_util; + + if (m->m_len == 0) + goto cont; + w = mtod(m, uint16_t *); + + mlen = m->m_len; + + if (len < mlen) + mlen = len; + len -= mlen; + /* + * Force to even boundary. + */ + if ((1 & (uintptr_t)w) && (mlen > 0)) { + REDUCE; + sum <<= 8; + s_util.c[0] = *(uint8_t *)w; + w = (uint16_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; + if (mlen == -1) { + s_util.c[1] = *(uint8_t *)w; + sum += s_util.s; + mlen = 0; + } else + + mlen = -1; + } else if (mlen == -1) + s_util.c[0] = *(uint8_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); + if (len) { + DEBUG_ERROR("cksum: out of data"); + DEBUG_ERROR(" len = %d", len); + } + 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); +} + +int ip6_cksum(struct mbuf *m) +{ + /* TODO: Optimize this by being able to pass the ip6_pseudohdr to cksum + * separately from the mbuf */ + struct ip6 save_ip, *ip = mtod(m, struct ip6 *); + struct ip6_pseudohdr *ih = mtod(m, struct ip6_pseudohdr *); + int sum; + + save_ip = *ip; + + ih->ih_src = save_ip.ip_src; + ih->ih_dst = save_ip.ip_dst; + ih->ih_pl = htonl((uint32_t)ntohs(save_ip.ip_pl)); + ih->ih_zero_hi = 0; + ih->ih_zero_lo = 0; + ih->ih_nh = save_ip.ip_nh; + + sum = cksum(m, ((int)sizeof(struct ip6_pseudohdr)) + ntohl(ih->ih_pl)); + + *ip = save_ip; + + return sum; } #endif diff --git a/bochs/iodev/network/slirp/compat.cc b/bochs/iodev/network/slirp/compat.cc deleted file mode 100644 index 59aea49b9a..0000000000 --- a/bochs/iodev/network/slirp/compat.cc +++ /dev/null @@ -1,357 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// -/* - * QEMU compatibility functions - * - * Copyright (c) 2003-2008 Fabrice Bellard - * Copyright (C) 2014-2021 The Bochs Project - * - * 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 "slirp.h" - -#ifndef WEXITSTATUS -# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) -#endif -#ifndef WIFEXITED -# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) -#endif - -#if BX_NETWORKING && BX_NETMOD_SLIRP - -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 qemu_set_nonblock(int fd) -{ -#ifndef _WIN32 - int f; - f = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, f | O_NONBLOCK); -#elif !defined(_MSC_VER) - ULONG opt = 1; - ioctlsocket(fd, FIONBIO, &opt); -#endif -} - -#ifndef HAVE_INET_ATON -int inet_aton(const char *cp, struct in_addr *ia) -{ - uint32_t addr; - -#if defined(_MSC_VER) - if (!inet_pton(AF_INET, cp, &addr)) { - return 0; - } -#else - addr = inet_addr(cp); -#endif - if (addr == 0xffffffff) { - return 0; - } - ia->s_addr = addr; - return 1; -} -#endif - -int socket_set_fast_reuse(int fd) -{ -#ifndef _WIN32 - int val = 1, ret; - - ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (const char *)&val, sizeof(val)); - - assert(ret == 0); - - return ret; -#else - return 0; -#endif -} - -int socket_set_nodelay(int fd) -{ - int v = 1; - return qemu_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); -} - -void qemu_set_cloexec(int fd) -{ -#ifndef _WIN32 - int f; - f = fcntl(fd, F_GETFD); - fcntl(fd, F_SETFD, f | FD_CLOEXEC); -#endif -} - -/* - * Opens a socket with FD_CLOEXEC set - */ -int qemu_socket(int domain, int type, int protocol) -{ - int ret; - -#ifdef SOCK_CLOEXEC - ret = socket(domain, type | SOCK_CLOEXEC, protocol); - if (ret != -1 || errno != EINVAL) { - return ret; - } -#endif - ret = socket(domain, type, protocol); - if (ret >= 0) { - qemu_set_cloexec(ret); - } - - return ret; -} - -#if !defined(_WIN32) && !defined(__CYGWIN__) - -#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd" - -#include - -/* automatic user mode samba server configuration */ -void slirp_smb_cleanup(Slirp *s, char *smb_tmpdir) -{ - char cmd[128]; - char error_msg[256]; - int ret; - - if (smb_tmpdir[0] != '\0') { - snprintf(cmd, sizeof(cmd), "rm -rf %s", smb_tmpdir); - ret = system(cmd); - if (ret == -1 || !WIFEXITED(ret)) { - snprintf(error_msg, sizeof(error_msg), "'%s' failed.", cmd); - slirp_warning(s, error_msg); - } else if (WEXITSTATUS(ret)) { - snprintf(error_msg, sizeof(error_msg), "'%s' failed. Error code: %d", - cmd, WEXITSTATUS(ret)); - slirp_warning(s, error_msg); - } - smb_tmpdir[0] = '\0'; - } -} - -int slirp_smb(Slirp *s, char *smb_tmpdir, const char *exported_dir, - struct in_addr vserver_addr) -{ - static int instance; - int i; - char smb_conf[128], smb_cmdline[150]; - char share[64], error_msg[256]; - struct passwd *passwd; - FILE *f; - - passwd = getpwuid(geteuid()); - if (!passwd) { - sprintf(error_msg, "failed to retrieve user name"); - slirp_warning(s, error_msg); - return -1; - } - - if (access(CONFIG_SMBD_COMMAND, F_OK)) { - sprintf(error_msg, "could not find '%s', please install it", - CONFIG_SMBD_COMMAND); - slirp_warning(s, error_msg); - return -1; - } - - if (access(exported_dir, R_OK | X_OK)) { - snprintf(error_msg, sizeof(error_msg), "error accessing shared directory '%s': %s", - exported_dir, strerror(errno)); - slirp_warning(s, error_msg); - return -1; - } - - i = strlen(exported_dir) - 2; - while ((i > 0) && (exported_dir[i] != '/')) i--; - snprintf(share, sizeof(share), "%s", &exported_dir[i+1]); - if (share[strlen(share)-1] == '/') share[strlen(share)-1] = '\0'; - - snprintf(smb_tmpdir, 128, "/tmp/bochs-smb.%ld-%d", - (long)getpid(), instance++); - if (mkdir(smb_tmpdir, 0700) < 0) { - snprintf(error_msg, sizeof(error_msg), "could not create samba server dir '%s'", - smb_tmpdir); - slirp_warning(s, error_msg); - return -1; - } - snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_tmpdir, "smb.conf"); - - f = fopen(smb_conf, "w"); - if (!f) { - slirp_smb_cleanup(s, smb_tmpdir); - snprintf(error_msg, sizeof(error_msg), "could not create samba server configuration file '%s'", - smb_conf); - slirp_warning(s, error_msg); - return -1; - } - fprintf(f, - "[global]\n" - "private dir=%s\n" - "interfaces=127.0.0.1\n" - "bind interfaces only=yes\n" - "pid directory=%s\n" - "lock directory=%s\n" - "state directory=%s\n" - "cache directory=%s\n" - "ncalrpc dir=%s/ncalrpc\n" - "log file=%s/log.smbd\n" - "smb passwd file=%s/smbpasswd\n" - "security = user\n" - "map to guest = Bad User\n" - "[%s]\n" - "path=%s\n" - "read only=no\n" - "guest ok=yes\n" - "force user=%s\n", - smb_tmpdir, - smb_tmpdir, - smb_tmpdir, - smb_tmpdir, - smb_tmpdir, - smb_tmpdir, - smb_tmpdir, - smb_tmpdir, - share, - exported_dir, - passwd->pw_name - ); - fclose(f); - - snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s", - CONFIG_SMBD_COMMAND, smb_conf); - - if (slirp_add_exec(s, 0, smb_cmdline, &vserver_addr, 139) < 0 || - slirp_add_exec(s, 0, smb_cmdline, &vserver_addr, 445) < 0) { - slirp_smb_cleanup(s, smb_tmpdir); - sprintf(error_msg, "conflicting/invalid smbserver address"); - slirp_warning(s, error_msg); - return -1; - } - return 0; -} -#endif - -static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) -{ - const char *p, *p1; - int len; - p = *pp; - p1 = strchr(p, sep); - if (!p1) - return -1; - len = p1 - p; - p1++; - if (buf_size > 0) { - if (len > buf_size - 1) - len = buf_size - 1; - memcpy(buf, p, len); - buf[len] = '\0'; - } - *pp = p1; - return 0; -} - -int slirp_hostfwd(Slirp *s, const char *redir_str, int legacy_format) -{ - struct in_addr host_addr; - struct in_addr guest_addr; - int host_port, guest_port; - const char *p; - char buf[256], error_msg[256]; - int is_udp; - char *end; - - host_addr.s_addr = INADDR_ANY; - guest_addr.s_addr = 0; - 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 (!legacy_format) { - if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { - goto fail_syntax; - } - if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) { - goto fail_syntax; - } - } - - if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 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; - } - if (buf[0] != '\0' && !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_add_hostfwd(s, is_udp, host_addr, host_port, guest_addr, - guest_port) < 0) { - sprintf(error_msg, "could not set up host forwarding rule '%s'", redir_str); - slirp_warning(s, error_msg); - return -1; - } - return 0; - - fail_syntax: - sprintf(error_msg, "invalid host forwarding rule '%s'", redir_str); - slirp_warning(s, error_msg); - return -1; -} - -#endif diff --git a/bochs/iodev/network/slirp/compat.h b/bochs/iodev/network/slirp/compat.h index 23157e2c6c..7679969351 100644 --- a/bochs/iodev/network/slirp/compat.h +++ b/bochs/iodev/network/slirp/compat.h @@ -15,91 +15,32 @@ #include #include -#include "qemu-queue.h" - #if defined(_MSC_VER) #include -typedef Bit8s int8_t; -typedef Bit16s int16_t; -typedef Bit8u uint8_t; -typedef Bit16u uint16_t; -typedef Bit32u uint32_t; -typedef Bit64u uint64_t; -typedef Bit64s ssize_t; -#ifndef BX_OSDEP_H -#define snprintf _snprintf #define strdup _strdup #define open _open #define close _close #define lseek _lseeki64 #define read _read #define write _write -#endif #define strcasecmp _stricmp #endif -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#endif +#define SLIRP_N_ELEMENTS(x) (sizeof(x) / sizeof((x)[0])) + +#define slirp_rand_int_range(min, max) ((rand() % (max - min)) + min) +#define slirp_warn_if_fail(cond) if (!(cond)) slirplog_error("condition " #cond " failed") +#define slirp_return_if_fail(cond) if (!(cond)) return +#define slirp_return_val_if_fail(cond, retval) if (!(cond)) return retval #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif - -/* Workaround for older versions of MinGW. */ -#ifndef ECONNREFUSED -# define ECONNREFUSED WSAECONNREFUSED -#endif -#ifndef EINPROGRESS -# define EINPROGRESS WSAEINPROGRESS -#endif -#ifndef EHOSTUNREACH -# define EHOSTUNREACH WSAEHOSTUNREACH -#endif -#ifndef EINTR -# define EINTR WSAEINTR -#endif -#ifndef EINPROGRESS -# define EINPROGRESS WSAEINPROGRESS -#endif -#ifndef ENETUNREACH -# define ENETUNREACH WSAENETUNREACH -#endif -#ifndef ENOTCONN -# define ENOTCONN WSAENOTCONN -#endif -#if defined(__CYGWIN__) && defined(EWOULDBLOCK) -# undef EWOULDBLOCK -# define EWOULDBLOCK WSAEWOULDBLOCK -#endif -#ifndef EWOULDBLOCK -# define EWOULDBLOCK WSAEWOULDBLOCK +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif -#ifdef _WIN32 -struct iovec { - void *iov_base; - size_t iov_len; -}; -#endif - -// missing functions -void pstrcpy(char *buf, int buf_size, const char *str); -int qemu_socket(int domain, int type, int protocol); -#ifndef HAVE_INET_ATON -int inet_aton(const char *cp, struct in_addr *ia); -#endif -#ifdef _WIN32 -#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \ - setsockopt(sockfd, level, optname, (const char *)optval, optlen) -#define qemu_recv(a,b,c,d) recv(a,(char*)b,c,d) -#else -#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \ - setsockopt(sockfd, level, optname, (const void *)optval, optlen) -#define qemu_recv(a,b,c,d) recv(a,b,c,d) -#endif -int socket_set_fast_reuse(int fd); -int socket_set_nodelay(int fd); -void qemu_set_nonblock(int fd); +#define BX_STATIC_ASSERT(s) \ + static_assert (s, "Invalid structure size"); #endif diff --git a/bochs/iodev/network/slirp/debug.h b/bochs/iodev/network/slirp/debug.h index 9050bd2f8e..58b54e090a 100644 --- a/bochs/iodev/network/slirp/debug.h +++ b/bochs/iodev/network/slirp/debug.h @@ -1,37 +1,66 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ -//#define DEBUG 1 +#ifndef DEBUG_H_ +#define DEBUG_H_ -#ifdef DEBUG +#define DBG_CALL (1 << 0) +#define DBG_MISC (1 << 1) +#define DBG_ERROR (1 << 2) +#define DBG_TFTP (1 << 3) +#define DBG_VERBOSE_CALL (1 << 4) -#define DBG_CALL 0x1 -#define DBG_MISC 0x2 -#define DBG_ERROR 0x4 +extern int slirp_debug; -#define dfd stderr +#define DEBUG_CALL(name) \ + do { \ + if (unlikely(slirp_debug & DBG_CALL)) { \ + slirplog_debug(name "..."); \ + } \ + } while (0) -extern int slirp_debug; +#define DEBUG_VERBOSE_CALL(name) \ + do { \ + if (unlikely(slirp_debug & DBG_VERBOSE_CALL)) { \ + slirplog_debug(name "..."); \ + } \ + } while (0) + +#define DEBUG_RAW_CALL(...) \ + do { \ + if (unlikely(slirp_debug & DBG_CALL)) { \ + slirplog_debug(__VA_ARGS__); \ + } \ + } while (0) + +#define DEBUG_ARG(...) \ + do { \ + if (unlikely(slirp_debug & DBG_CALL)) { \ + slirplog_debug(" " __VA_ARGS__); \ + } \ + } while (0) -#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); } +#define DEBUG_MISC(...) \ + do { \ + if (unlikely(slirp_debug & DBG_MISC)) { \ + slirplog_debug(__VA_ARGS__); \ + } \ + } while (0) -#else +#define DEBUG_ERROR(...) \ + do { \ + if (unlikely(slirp_debug & DBG_ERROR)) { \ + slirplog_debug(__VA_ARGS__); \ + } \ + } while (0) -#define DEBUG_CALL(x) -#define DEBUG_ARG(x, y) -#define DEBUG_ARGS(x) -#define DEBUG_MISC(x) -#define DEBUG_ERROR(x) +#define DEBUG_TFTP(...) \ + do { \ + if (unlikely(slirp_debug & DBG_TFTP)) { \ + slirplog_debug(__VA_ARGS__); \ + } \ + } while (0) #endif diff --git a/bochs/iodev/network/slirp/dhcpv6.cc b/bochs/iodev/network/slirp/dhcpv6.cc new file mode 100644 index 0000000000..8ad38d7205 --- /dev/null +++ b/bochs/iodev/network/slirp/dhcpv6.cc @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * SLIRP stateless DHCPv6 + * + * We only support stateless DHCPv6, e.g. for network booting. + * See RFC 3315, RFC 3736, RFC 3646 and RFC 5970 for details. + * + * Copyright 2016 Thomas Huth, Red Hat Inc. + * + * 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 copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "slirp.h" +#include "dhcpv6.h" + +#if BX_NETWORKING && BX_NETMOD_SLIRP + +/* DHCPv6 message types */ +#define MSGTYPE_REPLY 7 +#define MSGTYPE_INFO_REQUEST 11 + +/* DHCPv6 option types */ +#define OPTION_CLIENTID 1 +#define OPTION_IAADDR 5 +#define OPTION_ORO 6 +#define OPTION_DNS_SERVERS 23 +#define OPTION_BOOTFILE_URL 59 + +struct requested_infos { + uint8_t *client_id; + int client_id_len; + bool want_dns; + bool want_boot_url; +}; + +/** + * Analyze the info request message sent by the client to see what data it + * provided and what it wants to have. The information is gathered in the + * "requested_infos" struct. Note that client_id (if provided) points into + * the odata region, thus the caller must keep odata valid as long as it + * needs to access the requested_infos struct. + */ +static int dhcpv6_parse_info_request(Slirp *slirp, uint8_t *odata, int olen, + struct requested_infos *ri) +{ + int i, req_opt; + + while (olen > 4) { + /* Parse one option */ + int option = odata[0] << 8 | odata[1]; + int len = odata[2] << 8 | odata[3]; + + if (len + 4 > olen) { + slirp->cb->guest_error("Guest sent bad DHCPv6 packet!", + slirp->opaque); + return -E2BIG; + } + + switch (option) { + case OPTION_IAADDR: + /* According to RFC3315, we must discard requests with IA option */ + return -EINVAL; + case OPTION_CLIENTID: + if (len > 256) { + /* Avoid very long IDs which could cause problems later */ + return -E2BIG; + } + ri->client_id = odata + 4; + ri->client_id_len = len; + break; + case OPTION_ORO: /* Option request option */ + if (len & 1) { + return -EINVAL; + } + /* Check which options the client wants to have */ + for (i = 0; i < len; i += 2) { + req_opt = odata[4 + i] << 8 | odata[4 + i + 1]; + switch (req_opt) { + case OPTION_DNS_SERVERS: + ri->want_dns = true; + break; + case OPTION_BOOTFILE_URL: + ri->want_boot_url = true; + break; + default: + DEBUG_MISC("dhcpv6: Unsupported option request %d", + req_opt); + } + } + break; + default: + DEBUG_MISC("dhcpv6 info req: Unsupported option %d, len=%d", option, + len); + } + + odata += len + 4; + olen -= len + 4; + } + + return 0; +} + + +/** + * Handle information request messages + */ +static void dhcpv6_info_request(Slirp *slirp, struct sockaddr_in6 *srcsas, + uint32_t xid, uint8_t *odata, int olen) +{ + struct requested_infos ri = { NULL }; + struct sockaddr_in6 sa6, da6; + struct mbuf *m; + uint8_t *resp; + + if (dhcpv6_parse_info_request(slirp, odata, olen, &ri) < 0) { + return; + } + + m = m_get(slirp); + if (!m) { + return; + } + memset(m->m_data, 0, m->m_size); + m->m_data += IF_MAXLINKHDR; + resp = (uint8_t *)m->m_data + sizeof(struct ip6) + sizeof(struct udphdr); + + /* Fill in response */ + *resp++ = MSGTYPE_REPLY; + *resp++ = (uint8_t)(xid >> 16); + *resp++ = (uint8_t)(xid >> 8); + *resp++ = (uint8_t)xid; + + if (ri.client_id) { + *resp++ = OPTION_CLIENTID >> 8; /* option-code high byte */ + *resp++ = OPTION_CLIENTID; /* option-code low byte */ + *resp++ = ri.client_id_len >> 8; /* option-len high byte */ + *resp++ = ri.client_id_len; /* option-len low byte */ + memcpy(resp, ri.client_id, ri.client_id_len); + resp += ri.client_id_len; + } + if (ri.want_dns) { + *resp++ = OPTION_DNS_SERVERS >> 8; /* option-code high byte */ + *resp++ = OPTION_DNS_SERVERS; /* option-code low byte */ + *resp++ = 0; /* option-len high byte */ + *resp++ = 16; /* option-len low byte */ + memcpy(resp, &slirp->vnameserver_addr6, 16); + resp += 16; + } + if (ri.want_boot_url) { + uint8_t *sa = slirp->vhost_addr6.s6_addr; + int slen, smaxlen; + + *resp++ = OPTION_BOOTFILE_URL >> 8; /* option-code high byte */ + *resp++ = OPTION_BOOTFILE_URL; /* option-code low byte */ + smaxlen = (uint8_t *)m->m_data + slirp->if_mtu - (resp + 2); + slen = slirp_fmt((char *)resp + 2, smaxlen, + "tftp://[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" + "%02x%02x:%02x%02x:%02x%02x:%02x%02x]/%s", + sa[0], sa[1], sa[2], sa[3], sa[4], sa[5], sa[6], sa[7], + sa[8], sa[9], sa[10], sa[11], sa[12], sa[13], sa[14], + sa[15], slirp->bootp_filename); + *resp++ = slen >> 8; /* option-len high byte */ + *resp++ = slen; /* option-len low byte */ + resp += slen; + } + + sa6.sin6_addr = slirp->vhost_addr6; + sa6.sin6_port = DHCPV6_SERVER_PORT; + da6.sin6_addr = srcsas->sin6_addr; + da6.sin6_port = srcsas->sin6_port; + m->m_data += sizeof(struct ip6) + sizeof(struct udphdr); + m->m_len = resp - (uint8_t *)m->m_data; + udp6_output(NULL, m, &sa6, &da6); +} + +/** + * Handle DHCPv6 messages sent by the client + */ +void dhcpv6_input(struct sockaddr_in6 *srcsas, struct mbuf *m) +{ + uint8_t *data = (uint8_t *)m->m_data + sizeof(struct udphdr); + int data_len = m->m_len - sizeof(struct udphdr); + uint32_t xid; + + if (data_len < 4) { + return; + } + + xid = ntohl(*(uint32_t *)data) & 0xffffff; + + switch (data[0]) { + case MSGTYPE_INFO_REQUEST: + dhcpv6_info_request(m->slirp, srcsas, xid, &data[4], data_len - 4); + break; + default: + DEBUG_MISC("dhcpv6_input: Unsupported message type 0x%x", data[0]); + } +} + +#endif diff --git a/bochs/iodev/network/slirp/dhcpv6.h b/bochs/iodev/network/slirp/dhcpv6.h new file mode 100644 index 0000000000..35916c06ba --- /dev/null +++ b/bochs/iodev/network/slirp/dhcpv6.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Definitions and prototypes for SLIRP stateless DHCPv6 + * + * Copyright 2016 Thomas Huth, Red Hat Inc. + * + * 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 copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SLIRP_DHCPV6_H +#define SLIRP_DHCPV6_H + +#define DHCPV6_SERVER_PORT 547 + +const struct in6_addr ALLDHCP_MULTICAST \ + { \ + 0xff, \ + 0x02, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x01, \ + 0x00, \ + 0x02 \ + }; + +#define in6_dhcp_multicast(a) in6_equal(a, &ALLDHCP_MULTICAST) + +/* Process a DHCPv6 packet from the guest */ +void dhcpv6_input(struct sockaddr_in6 *srcsas, struct mbuf *m); + +#endif diff --git a/bochs/iodev/network/slirp/dnssearch.cc b/bochs/iodev/network/slirp/dnssearch.cc index d8f418d2f3..6ce0075e4b 100644 --- a/bochs/iodev/network/slirp/dnssearch.cc +++ b/bochs/iodev/network/slirp/dnssearch.cc @@ -1,6 +1,4 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: MIT */ /* * Domain search option for DHCP (RFC 3397) * @@ -26,9 +24,6 @@ */ #include "slirp.h" -#include -#include -#include #if BX_NETWORKING && BX_NETMOD_SLIRP @@ -47,15 +42,16 @@ typedef struct compact_domain { size_t common_octets; } CompactDomain; -static size_t -domain_suffix_diffoff(const CompactDomain *a, const CompactDomain *b) +static size_t domain_suffix_diffoff(const CompactDomain *a, + const CompactDomain *b) { size_t la = a->len, lb = b->len; uint8_t *da = a->labels + la, *db = b->labels + lb; size_t i, lm = (la < lb) ? la : lb; for (i = 0; i < lm; i++) { - da--; db--; + da--; + db--; if (*da != *db) { break; } @@ -63,7 +59,7 @@ domain_suffix_diffoff(const CompactDomain *a, const CompactDomain *b) return i; } -static int CDECL domain_suffix_ord(const void *cva, const void *cvb) +static int domain_suffix_ord(const void *cva, const void *cvb) { const CompactDomain *a = (const CompactDomain*)cva, *b = (const CompactDomain*)cvb; size_t la = a->len, lb = b->len; @@ -119,14 +115,13 @@ static void domain_fixup_order(CompactDomain *cd, size_t n) } } -static void domain_mklabels(Slirp *s, CompactDomain *cd, const char *input) +static void domain_mklabels(CompactDomain *cd, const char *input) { uint8_t *len_marker = cd->labels; uint8_t *output = len_marker; /* pre-incremented */ const char *in = input; char cur_chr; size_t len = 0; - char msg[80]; if (cd->len == 0) { goto fail; @@ -158,13 +153,12 @@ static void domain_mklabels(Slirp *s, CompactDomain *cd, const char *input) return; fail: - sprintf(msg, "failed to parse domain name '%s'\n", input); - slirp_warning(s, msg); + slirplog_error("failed to parse domain name '%s'", input); cd->len = 0; } -static void -domain_mkxrefs(CompactDomain *doms, CompactDomain *last, size_t depth) +static void domain_mkxrefs(CompactDomain *doms, CompactDomain *last, + size_t depth) { CompactDomain *i = doms, *target = doms; @@ -223,8 +217,7 @@ static size_t domain_compactify(CompactDomain *domains, size_t n) CompactDomain *rd = cd->refdom; if (rd != NULL) { - size_t moff = (rd->labels - start) - + (rd->len - cd->common_octets); + size_t moff = (rd->labels - start) + (rd->len - cd->common_octets); if (moff < 0x3FFFu) { cd->len -= cd->common_octets - 2; cd->labels[cd->len - 1] = moff & 0xFFu; @@ -270,22 +263,22 @@ int translate_dnssearch(Slirp *s, const char **names) } /* reserve extra 2 header bytes for each 255 bytes of output */ - memreq += ((memreq + MAX_OPT_LEN - 1) / MAX_OPT_LEN) * OPT_HEADER_LEN; + memreq += DIV_ROUND_UP(memreq, MAX_OPT_LEN) * OPT_HEADER_LEN; result = (uint8_t*)malloc(memreq * sizeof(*result)); outptr = result; for (i = 0; i < num_domains; i++) { domains[i].labels = outptr; - domain_mklabels(s, domains + i, names[i]); + domain_mklabels(domains + i, names[i]); + if (domains[i].len == 0) { + /* Bogus entry, reject it all */ + free(domains); + free(result); + return -1; + } outptr += domains[i].len; } - if (outptr == result) { - free(domains); - free(result); - return -1; - } - qsort(domains, num_domains, sizeof(*domains), domain_suffix_ord); domain_fixup_order(domains, num_domains); @@ -297,7 +290,7 @@ int translate_dnssearch(Slirp *s, const char **names) domain_mkxrefs(domains, domains + num_domains - 1, 0); memreq = domain_compactify(domains, num_domains); - blocks = (memreq + MAX_OPT_LEN - 1) / MAX_OPT_LEN; + blocks = DIV_ROUND_UP(memreq, MAX_OPT_LEN); bsrc_end = memreq; bsrc_start = (blocks - 1) * MAX_OPT_LEN; bdst_start = bsrc_start + blocks * OPT_HEADER_LEN; diff --git a/bochs/iodev/network/slirp/if.cc b/bochs/iodev/network/slirp/if.cc index 624ec25105..974d91dfe4 100644 --- a/bochs/iodev/network/slirp/if.cc +++ b/bochs/iodev/network/slirp/if.cc @@ -1,42 +1,24 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ -#define BX_PLUGGABLE - #include "slirp.h" -#include "iodev.h" #if BX_NETWORKING && BX_NETMOD_SLIRP -static void -ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) -{ - ifm->ifs_next = ifmhead->ifs_next; - ifmhead->ifs_next = ifm; - ifm->ifs_prev = ifmhead; - ifm->ifs_next->ifs_prev = ifm; -} - -static void -ifs_remque(struct mbuf *ifm) +static void ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) { - ifm->ifs_prev->ifs_next = ifm->ifs_next; - ifm->ifs_next->ifs_prev = ifm->ifs_prev; + ifm->m_nextpkt = ifmhead->m_nextpkt; + ifmhead->m_nextpkt = ifm; + ifm->m_prevpkt = ifmhead; + ifm->m_nextpkt->m_prevpkt = ifm; } -void -if_init(Slirp *slirp) +void if_init(Slirp *slirp) { - slirp->if_fastq.ifq_next = slirp->if_fastq.ifq_prev = &slirp->if_fastq; - slirp->if_batchq.ifq_next = slirp->if_batchq.ifq_prev = &slirp->if_batchq; - slirp->next_m = &slirp->if_batchq; + slirp->if_fastq.qh_link = slirp->if_fastq.qh_rlink = &slirp->if_fastq; + slirp->if_batchq.qh_link = slirp->if_batchq.qh_rlink = &slirp->if_batchq; } /* @@ -52,198 +34,166 @@ if_init(Slirp *slirp) * 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(struct socket *so, struct mbuf *ifm) +void if_output(struct socket *so, struct mbuf *ifm) { - Slirp *slirp = ifm->slirp; - 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 = slirp->if_batchq.ifq_prev; ifq != &slirp->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 = slirp->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 = slirp->if_batchq.ifq_prev; - /* Set next_m if the queue was empty so far */ - if (slirp->next_m == &slirp->if_batchq) { - slirp->next_m = ifm; - } + Slirp *slirp = ifm->slirp; + M_DUP_DEBUG(slirp, ifm, 0, 0); + + struct mbuf *ifq; + int on_fastq = 1; + + DEBUG_CALL("if_output"); + DEBUG_ARG("so = %p", so); + DEBUG_ARG("ifm = %p", 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) { + slirp_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? + */ + if (so) { + for (ifq = (struct mbuf *)slirp->if_batchq.qh_rlink; + (struct slirp_quehead *)ifq != &slirp->if_batchq; + ifq = ifq->m_prev) { + if (so == ifq->m_so) { + /* A match! */ + ifm->m_so = so; + ifs_insque(ifm, ifq->m_prevpkt); + goto diddit; + } } + } - /* Create a new doubly linked list for this session */ - ifm->ifq_so = so; - ifs_init(ifm); - insque(ifm, ifq); + /* No match, check which queue to put it on */ + if (so && (so->so_iptos & IPTOS_LOWDELAY)) { + ifq = (struct mbuf *)slirp->if_fastq.qh_rlink; + on_fastq = 1; + /* + * Check if this packet is a part of the last + * packet's session + */ + if (ifq->m_so == so) { + ifm->m_so = so; + ifs_insque(ifm, ifq->m_prevpkt); + goto diddit; + } + } else { + ifq = (struct mbuf *)slirp->if_batchq.qh_rlink; + } + + /* Create a new doubly linked list for this session */ + ifm->m_so = so; + ifs_init(ifm); + slirp_insque(ifm, ifq); diddit: - 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, &slirp->if_batchq); - } - } - -#ifndef FULL_BOLT - /* - * This prevents us from malloc()ing too many mbufs - */ - if_start(ifm->slirp); -#endif + 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... */ + slirp_remque(ifm->m_nextpkt); + + /* ...And insert in the new. That'll teach ya! */ + slirp_insque(ifm->m_nextpkt, &slirp->if_batchq); + } + } + + /* + * This prevents us from malloc()ing too many mbufs + */ + if_start(ifm->slirp); } -/* - * Send a packet - * We choose a packet based on its 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(Slirp *slirp) { - uint64_t now = bx_pc_system.time_usec() * 1000ULL; - bool from_batchq, next_from_batchq; + uint64_t now = slirp->cb->clock_get_ns(slirp->opaque); + bool from_batchq = false; struct mbuf *ifm, *ifm_next, *ifqt; -// DEBUG_CALL("if_start"); // Disabled to avoid flooding output + DEBUG_VERBOSE_CALL("if_start"); if (slirp->if_start_busy) { return; } slirp->if_start_busy = true; - if (slirp->if_fastq.ifq_next != &slirp->if_fastq) { - ifm_next = slirp->if_fastq.ifq_next; - next_from_batchq = false; - } else if (slirp->next_m != &slirp->if_batchq) { - /* Nothing on fastq, pick up from batchq via next_m */ - ifm_next = slirp->next_m; - next_from_batchq = true; - } else { - ifm_next = NULL; + struct mbuf *batch_head = NULL; + if (slirp->if_batchq.qh_link != &slirp->if_batchq) { + batch_head = (struct mbuf *)slirp->if_batchq.qh_link; } - if (ifm_next) { - DEBUG_CALL("if_start"); // Report only if something's to do + if (slirp->if_fastq.qh_link != &slirp->if_fastq) { + ifm_next = (struct mbuf *)slirp->if_fastq.qh_link; + } else if (batch_head) { + /* Nothing on fastq, pick up from batchq */ + ifm_next = batch_head; + from_batchq = true; + } else { + ifm_next = NULL; } while (ifm_next) { - /* check if we can really output */ - if (!slirp_can_output(slirp->opaque)) { - break; - } - ifm = ifm_next; - from_batchq = next_from_batchq; - ifm_next = ifm->ifq_next; - if (ifm_next == &slirp->if_fastq) { + ifm_next = ifm->m_next; + if ((struct slirp_quehead *)ifm_next == &slirp->if_fastq) { /* No more packets in fastq, switch to batchq */ - ifm_next = slirp->next_m; - next_from_batchq = true; + ifm_next = batch_head; + from_batchq = true; } - if (ifm_next == &slirp->if_batchq) { + if ((struct slirp_quehead *)ifm_next == &slirp->if_batchq) { /* end of batchq */ ifm_next = NULL; } /* Try to send packet unless it already expired */ if (ifm->expiration_date >= now && !if_encap(slirp, ifm)) { - /* Packet is delayed due to pending ARP resolution */ + /* Packet is delayed due to pending ARP or NDP resolution */ continue; } - if (ifm == slirp->next_m) { - /* Set which packet to send on next iteration */ - slirp->next_m = ifm->ifq_next; - } - /* Remove it from the queue */ - ifqt = ifm->ifq_prev; - remque(ifm); + ifqt = ifm->m_prev; + slirp_remque(ifm); /* If there are more packets for this session, re-queue them */ - if (ifm->ifs_next != ifm) { - struct mbuf *next = ifm->ifs_next; + if (ifm->m_nextpkt != ifm) { + struct mbuf *next = ifm->m_nextpkt; - insque(next, ifqt); + slirp_insque(next, ifqt); ifs_remque(ifm); - if (!from_batchq) { - /* Next packet in fastq is from the same session */ ifm_next = next; - next_from_batchq = false; - } else if (slirp->next_m == &slirp->if_batchq) { - /* Set next_m and ifm_next if the session packet is now the - * only one on batchq */ - slirp->next_m = ifm_next = next; } } /* Update so_queued */ - if (ifm->ifq_so && --ifm->ifq_so->so_queued == 0) { + if (ifm->m_so && --ifm->m_so->so_queued == 0) { /* If there's no more queued, reset nqueued */ - ifm->ifq_so->so_nqueued = 0; + ifm->m_so->so_nqueued = 0; } m_free(ifm); diff --git a/bochs/iodev/network/slirp/if.h b/bochs/iodev/network/slirp/if.h index 419afc10c6..c4260b36b5 100644 --- a/bochs/iodev/network/slirp/if.h +++ b/bochs/iodev/network/slirp/if.h @@ -1,26 +1,25 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ -#ifndef _IF_H_ -#define _IF_H_ +#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 */ +#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 */ -#define IF_MTU 1500 -#define IF_MRU 1500 -#define IF_COMP IF_AUTOCOMP /* Flags for compression */ +#define IF_MTU_DEFAULT 1500 +#define IF_MTU_MIN 68 +#define IF_MTU_MAX 65521 +#define IF_MRU_DEFAULT 1500 +#define IF_MRU_MIN 68 +#define IF_MRU_MAX 65521 +#define IF_COMP IF_AUTOCOMP /* Flags for compression */ -/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ -#define IF_MAXLINKHDR (2 + 14 + 40) +/* 2 for alignment, 14 for ethernet */ +#define IF_MAXLINKHDR (2 + ETH_HLEN) #endif diff --git a/bochs/iodev/network/slirp/ip.h b/bochs/iodev/network/slirp/ip.h index eba661dd43..850eb1f37c 100644 --- a/bochs/iodev/network/slirp/ip.h +++ b/bochs/iodev/network/slirp/ip.h @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,12 +27,12 @@ * 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 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_ +#ifndef IP_H +#define IP_H #ifndef BX_LITTLE_ENDIAN # undef NTOHL @@ -66,195 +64,173 @@ typedef uint32_t n_long; /* long as received from the net */ * Definitions for internet protocol version 4. * Per RFC 791, September 1981. */ -#define IPVERSION 4 - -#if defined(_MSC_VER) -#pragma pack(push, 1) -#endif +#define IPVERSION 4 /* * Structure of an internet header, naked of options. */ +SLIRP_PACKED_BEGIN struct ip { #ifndef BX_LITTLE_ENDIAN - uint8_t ip_v:4, /* version */ - ip_hl:4; /* header length */ + uint8_t ip_v:4, /* version */ + ip_hl:4; /* header length */ #else - uint8_t ip_hl:4, /* header length */ - ip_v:4; /* version */ + uint8_t ip_hl:4, /* header length */ + ip_v:4; /* version */ #endif - uint8_t ip_tos; /* type of service */ - uint16_t ip_len; /* total length */ - uint16_t ip_id; /* identification */ - uint16_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 */ - uint8_t ip_ttl; /* time to live */ - uint8_t ip_p; /* protocol */ - uint16_t ip_sum; /* checksum */ - struct in_addr ip_src,ip_dst; /* source and dest address */ -} GCC_ATTRIBUTE((packed)); - -#define IP_MAXPACKET 65535 /* maximum packet size */ + uint8_t ip_tos; /* type of service */ + uint16_t ip_len; /* total length */ + uint16_t ip_id; /* identification */ + uint16_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 */ + uint8_t ip_ttl; /* time to live */ + uint8_t ip_p; /* protocol */ + uint16_t ip_sum; /* checksum */ + struct in_addr ip_src,ip_dst; /* source and dest address */ +} SLIRP_PACKED_END; + +#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 +#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_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_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_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 */ +#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 */ +#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. */ -struct ip_timestamp { - uint8_t ipt_code; /* IPOPT_TS */ - uint8_t ipt_len; /* size of structure (variable) */ - uint8_t ipt_ptr; /* index of current entry */ +SLIRP_PACKED_BEGIN +struct ip_timestamp { + uint8_t ipt_code; /* IPOPT_TS */ + uint8_t ipt_len; /* size of structure (variable) */ + uint8_t ipt_ptr; /* index of current entry */ #ifndef BX_LITTLE_ENDIAN - uint8_t ipt_oflw:4, /* overflow counter */ - ipt_flg:4; /* flags, see below */ + uint8_t ipt_oflw:4, /* overflow counter */ + ipt_flg:4; /* flags, see below */ #else - uint8_t ipt_flg:4, /* flags, see below */ - ipt_oflw:4; /* overflow counter */ + uint8_t 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; -} GCC_ATTRIBUTE((packed)); + 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; +} SLIRP_PACKED_END; /* 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 */ +#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 +#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 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 */ +#define IP_MSS 576 /* default maximum segment size */ -#if SIZEOF_CHAR_P == 4 +#if SIZEOF_INT_P == 4 +SLIRP_PACKED_BEGIN struct mbuf_ptr { - struct mbuf *mptr; - uint32_t dummy; -} GCC_ATTRIBUTE((packed)); + struct mbuf *mptr; + uint32_t dummy; +} SLIRP_PACKED_END; #else +SLIRP_PACKED_BEGIN struct mbuf_ptr { - struct mbuf *mptr; -} GCC_ATTRIBUTE((packed)); + struct mbuf *mptr; +} SLIRP_PACKED_END; #endif struct qlink { - void *next, *prev; + void *next, *prev; }; /* * Overlay for ip header used by other protocols (tcp, udp). */ +SLIRP_PACKED_BEGIN struct ipovly { - struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */ - uint8_t ih_x1; /* (unused) */ - uint8_t ih_pr; /* protocol */ - uint16_t ih_len; /* protocol length */ - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ -} GCC_ATTRIBUTE((packed)); + struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */ + uint8_t ih_x1; /* (unused) */ + uint8_t ih_pr; /* protocol */ + uint16_t ih_len; /* protocol length */ + struct in_addr ih_src; /* source internet address */ + struct in_addr ih_dst; /* destination internet address */ +} SLIRP_PACKED_END; /* * 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 { - struct qlink frag_link; /* to ip headers of fragments */ - struct qlink ip_link; /* to other reass headers */ - uint8_t ipq_ttl; /* time for reass q to live */ - uint8_t ipq_p; /* protocol of this fragment */ - uint16_t ipq_id; /* sequence id for reassembly */ - struct in_addr ipq_src,ipq_dst; -} GCC_ATTRIBUTE((packed)); + struct qlink ip_link; /* to other reass headers */ + uint8_t ipq_ttl; /* time for reass q to live */ + uint8_t ipq_p; /* protocol of this fragment */ + uint16_t ipq_id; /* sequence id for reassembly */ + struct in_addr ipq_src,ipq_dst; +}; -/* - * Ip header, when holding a fragment. - * - * Note: ipf_link must be at same offset as frag_link above - */ -struct ipasfrag { - struct qlink ipf_link; - struct ip ipf_ip; -} GCC_ATTRIBUTE((packed)); +struct ipas { + struct qlink link; + union { + struct ipq ipq; + struct ip ipf_ip; + }; +}; #define ipf_off ipf_ip.ip_off #define ipf_tos ipf_ip.ip_tos #define ipf_len ipf_ip.ip_len -#define ipf_next ipf_link.next -#define ipf_prev ipf_link.prev - -/* - * 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 */ -} GCC_ATTRIBUTE((packed)); - -#if defined(_MSC_VER) -#pragma pack(pop) -#endif #endif diff --git a/bochs/iodev/network/slirp/ip6.h b/bochs/iodev/network/slirp/ip6.h new file mode 100644 index 0000000000..c8825957f6 --- /dev/null +++ b/bochs/iodev/network/slirp/ip6.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2013 + * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. + */ + +#ifndef SLIRP_IP6_H +#define SLIRP_IP6_H + +#include + +#include "util.h" + +const struct in6_addr ALLNODES_MULTICAST = \ + { \ + 0xff, \ + 0x02, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x01 \ + }; + +const struct in6_addr SOLICITED_NODE_PREFIX \ + { \ + 0xff, \ + 0x02, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x01, \ + 0xff, \ + 0x00, \ + 0x00, \ + 0x00 \ + }; + +const struct in6_addr LINKLOCAL_ADDR \ + { \ + 0xfe, \ + 0x80, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x02 \ + }; + +const struct in6_addr ZERO_ADDR = \ + { \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00, \ + 0x00 \ + }; + +/* Check that two IPv6 addresses are equal */ +static inline bool in6_equal(const struct in6_addr *a, const struct in6_addr *b) +{ + return memcmp(a, b, sizeof(*a)) == 0; +} + +/* Check that two IPv6 addresses are equal in their network part */ +static inline bool in6_equal_net(const struct in6_addr *a, + const struct in6_addr *b, int prefix_len) +{ + if (memcmp(a, b, prefix_len / 8) != 0) { + return 0; + } + + if (prefix_len % 8 == 0) { + return 1; + } + + return a->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8)) == + b->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8)); +} + +/* Check that two IPv6 addresses are equal in their machine part */ +static inline bool in6_equal_mach(const struct in6_addr *a, + const struct in6_addr *b, int prefix_len) +{ + if (memcmp(&(a->s6_addr[DIV_ROUND_UP(prefix_len, 8)]), + &(b->s6_addr[DIV_ROUND_UP(prefix_len, 8)]), + 16 - DIV_ROUND_UP(prefix_len, 8)) != 0) { + return 0; + } + + if (prefix_len % 8 == 0) { + return 1; + } + + return (a->s6_addr[prefix_len / 8] & + ((1U << (8 - (prefix_len % 8))) - 1)) == + (b->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len % 8))) - 1)); +} + +/* Check that the IPv6 is equal to the virtual router */ +#define in6_equal_router(a) \ + ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len) && \ + in6_equal_mach(a, &slirp->vhost_addr6, slirp->vprefix_len)) || \ + (in6_equal_net(a, &LINKLOCAL_ADDR, 64) && \ + in6_equal_mach(a, &slirp->vhost_addr6, 64))) + +/* Check that the IPv6 is equal to the virtual DNS server */ +#define in6_equal_dns(a) \ + ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len) && \ + in6_equal_mach(a, &slirp->vnameserver_addr6, slirp->vprefix_len)) || \ + (in6_equal_net(a, &LINKLOCAL_ADDR, 64) && \ + in6_equal_mach(a, &slirp->vnameserver_addr6, 64))) + +/* Check that the IPv6 is equal to the host */ +#define in6_equal_host(a) (in6_equal_router(a) || in6_equal_dns(a)) + +/* Check that the IPv6 is within the sollicited node multicast network */ +#define in6_solicitednode_multicast(a) \ + (in6_equal_net(a, &SOLICITED_NODE_PREFIX, 104)) + +/* Check that the IPv6 is zero */ +#define in6_zero(a) (in6_equal(a, &ZERO_ADDR)) + +/* Compute emulated host MAC address from its ipv6 address */ +static inline void in6_compute_ethaddr(struct in6_addr ip, + uint8_t eth[ETH_ALEN]) +{ + eth[0] = 0x52; + eth[1] = 0x56; + memcpy(ð[2], &ip.s6_addr[16 - (ETH_ALEN - 2)], ETH_ALEN - 2); +} + +/* + * Definitions for internet protocol version 6. + * Per RFC 2460, December 1998. + */ +#define IP6VERSION 6 +#define IP6_HOP_LIMIT 255 + +/* + * Structure of an internet header, naked of options. + */ +struct ip6 { +#if defined(BX_BIG_ENDIAN) && !defined(_MSC_VER) + uint8_t ip_v : 4, /* version */ + ip_tc_hi : 4; /* traffic class */ + uint8_t ip_tc_lo : 4, ip_fl_hi : 4; /* flow label */ +#else + uint8_t ip_tc_hi : 4, ip_v : 4; + uint8_t ip_fl_hi : 4, ip_tc_lo : 4; +#endif + uint16_t ip_fl_lo; + uint16_t ip_pl; /* payload length */ + uint8_t ip_nh; /* next header */ + uint8_t ip_hl; /* hop limit */ + struct in6_addr ip_src, ip_dst; /* source and dest address */ +}; + +/* + * IPv6 pseudo-header used by upper-layer protocols + */ +struct ip6_pseudohdr { + struct in6_addr ih_src; /* source internet address */ + struct in6_addr ih_dst; /* destination internet address */ + uint32_t ih_pl; /* upper-layer packet length */ + uint16_t ih_zero_hi; /* zero */ + uint8_t ih_zero_lo; /* zero */ + uint8_t ih_nh; /* next header */ +}; + +/* + * We don't want to mark these ip6 structs as packed as they are naturally + * correctly aligned; instead assert that there is no stray padding. + * If we marked the struct as packed then we would be unable to take + * the address of any of the fields in it. + */ +BX_STATIC_ASSERT(sizeof(struct ip6) == 40); +BX_STATIC_ASSERT(sizeof(struct ip6_pseudohdr) == 40); + +#endif diff --git a/bochs/iodev/network/slirp/ip6_icmp.cc b/bochs/iodev/network/slirp/ip6_icmp.cc new file mode 100644 index 0000000000..546084098d --- /dev/null +++ b/bochs/iodev/network/slirp/ip6_icmp.cc @@ -0,0 +1,656 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2013 + * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. + */ + +#include "slirp.h" +#include "ip6_icmp.h" + +#if BX_NETWORKING && BX_NETMOD_SLIRP + +#define NDP_Interval \ + slirp_rand_int_range(NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval) + +/* The message sent when emulating PING */ +/* Be nice and tell them it's just a pseudo-ping packet */ +static const char icmp6_ping_msg[] = + "This is a pseudo-PING packet used by Slirp to emulate ICMPV6 ECHO-REQUEST " + "packets.\n"; + +void icmp6_post_init(Slirp *slirp) +{ + if (!slirp->in6_enabled) { + return; + } + + slirp->ra_timer = + slirp_timer_new(slirp, SLIRP_TIMER_RA, NULL); + slirp->cb->timer_mod(slirp->ra_timer, + slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS + + NDP_Interval, + slirp->opaque); +} + +void icmp6_cleanup(Slirp *slirp) +{ + if (!slirp->in6_enabled) { + return; + } + + slirp->cb->timer_free(slirp->ra_timer, slirp->opaque); +} + +/* Send ICMP packet to the Internet, and save it to so_m */ +static int icmp6_send(struct socket *so, struct mbuf *m, int hlen) +{ + Slirp *slirp = m->slirp; + + struct sockaddr_in6 addr; + + /* + * The behavior of reading SOCK_DGRAM+IPPROTO_ICMP sockets is inconsistent + * between host OSes. On Linux, only the ICMP header and payload is + * included. On macOS/Darwin, the socket acts like a raw socket and + * includes the IP header as well. On other BSDs, SOCK_DGRAM+IPPROTO_ICMP + * sockets aren't supported at all, so we treat them like raw sockets. It + * isn't possible to detect this difference at runtime, so we must use an + * #ifdef to determine if we need to remove the IP header. + */ +#if defined(BSD) && !defined(__GNU__) + so->so_type = IPPROTO_IPV6; +#else + so->so_type = IPPROTO_ICMPV6; +#endif + + so->s = slirp_socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); + if (so->s == -1) { + if (errno == EAFNOSUPPORT + || errno == EPROTONOSUPPORT + || errno == EACCES) { + /* Kernel doesn't support or allow ping sockets. */ + so->so_type = IPPROTO_IPV6; + so->s = slirp_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + } + } + if (so->s == -1) { + return -1; + } + so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque); + + if (slirp_bind_outbound(so, AF_INET6) != 0) { + // bind failed - close socket + closesocket(so->s); + so->s = -1; + return -1; + } + + M_DUP_DEBUG(slirp, m, 0, 0); + struct ip6 *ip = mtod(m, struct ip6 *); + + so->so_m = m; + so->so_faddr6 = ip->ip_dst; + so->so_laddr6 = ip->ip_src; + so->so_state = SS_ISFCONNECTED; + so->so_expire = curtime + SO_EXPIRE; + + addr.sin6_family = AF_INET6; + addr.sin6_addr = so->so_faddr6; + + slirp_insque(so, &so->slirp->icmp); + + if (sendto(so->s, m->m_data + hlen, m->m_len - hlen, 0, + (struct sockaddr *)&addr, sizeof(addr)) == -1) { + DEBUG_MISC("icmp6_input icmp sendto tx errno = %d-%s", errno, + strerror(errno)); + icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE); + icmp_detach(so); + } + + return 0; +} + +static void icmp6_send_echoreply(struct mbuf *m, Slirp *slirp, struct ip6 *ip, + struct icmp6 *icmp) +{ + struct mbuf *t = m_get(slirp); + t->m_len = sizeof(struct ip6) + ntohs(ip->ip_pl); + memcpy(t->m_data, m->m_data, t->m_len); + + /* IPv6 Packet */ + struct ip6 *rip = mtod(t, struct ip6 *); + rip->ip_dst = ip->ip_src; + rip->ip_src = ip->ip_dst; + + /* ICMPv6 packet */ + t->m_data += sizeof(struct ip6); + struct icmp6 *ricmp = mtod(t, struct icmp6 *); + ricmp->icmp6_type = ICMP6_ECHO_REPLY; + ricmp->icmp6_cksum = 0; + + /* Checksum */ + t->m_data -= sizeof(struct ip6); + ricmp->icmp6_cksum = ip6_cksum(t); + + ip6_output(NULL, t, 0); +} + +void icmp6_forward_error(struct mbuf *m, uint8_t type, uint8_t code, struct in6_addr *src) +{ + Slirp *slirp = m->slirp; + struct mbuf *t; + struct ip6 *ip = mtod(m, struct ip6 *); + char addrstr[INET6_ADDRSTRLEN]; + + DEBUG_CALL("icmp6_send_error"); + DEBUG_ARG("type = %d, code = %d", type, code); + + if (IN6_IS_ADDR_MULTICAST(&ip->ip_src) || in6_zero(&ip->ip_src)) { + /* TODO icmp error? */ + return; + } + + t = m_get(slirp); + + /* IPv6 packet */ + struct ip6 *rip = mtod(t, struct ip6 *); + rip->ip_src = *src; + rip->ip_dst = ip->ip_src; + inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN); + DEBUG_ARG("target = %s", addrstr); + + rip->ip_nh = IPPROTO_ICMPV6; + const int error_data_len = MIN( + m->m_len, (int)(slirp->if_mtu - (sizeof(struct ip6) + ICMP6_ERROR_MINLEN))); + rip->ip_pl = htons(ICMP6_ERROR_MINLEN + error_data_len); + t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl); + + /* ICMPv6 packet */ + t->m_data += sizeof(struct ip6); + struct icmp6 *ricmp = mtod(t, struct icmp6 *); + ricmp->icmp6_type = type; + ricmp->icmp6_code = code; + ricmp->icmp6_cksum = 0; + + switch (type) { + case ICMP6_UNREACH: + case ICMP6_TIMXCEED: + ricmp->icmp6_err.unused = 0; + break; + case ICMP6_TOOBIG: + ricmp->icmp6_err.mtu = htonl(slirp->if_mtu); + break; + case ICMP6_PARAMPROB: + /* TODO: Handle this case */ + break; + default: + slirplog_error("Unknown ICMP code"); + } + t->m_data += ICMP6_ERROR_MINLEN; + memcpy(t->m_data, m->m_data, error_data_len); + + /* Checksum */ + t->m_data -= ICMP6_ERROR_MINLEN; + t->m_data -= sizeof(struct ip6); + ricmp->icmp6_cksum = ip6_cksum(t); + + ip6_output(NULL, t, 0); +} + +void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code) +{ + struct in6_addr src = LINKLOCAL_ADDR; + icmp6_forward_error(m, type, code, &src); +} + +/* + * Reflect the ip packet back to the source + */ +void icmp6_reflect(struct mbuf *m) +{ + struct ip6 *ip = mtod(m, struct ip6 *); + int hlen = sizeof(struct ip6); + struct icmp6 *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 icmp6 *); + + icp->icmp6_type = ICMP6_ECHO_REPLY; + + m->m_data -= hlen; + m->m_len += hlen; + + icp->icmp6_cksum = 0; + icp->icmp6_cksum = ip6_cksum(m); + + ip->ip_hl = MAXTTL; + { /* swap */ + struct in6_addr icmp_dst; + icmp_dst = ip->ip_dst; + ip->ip_dst = ip->ip_src; + ip->ip_src = icmp_dst; + } + + ip6_output((struct socket *)NULL, m, 0); +} + +void icmp6_receive(struct socket *so) +{ + struct mbuf *m = so->so_m; + int hlen = sizeof(struct ip6); + uint8_t error_code; + struct icmp6 *icp; + int id, seq, len; + + m->m_data += hlen; + m->m_len -= hlen; + icp = mtod(m, struct icmp6 *); + + id = icp->icmp6_id; + seq = icp->icmp6_seq; + len = recv(so->s, icp, M_ROOM(m), 0); + + icp->icmp6_id = id; + icp->icmp6_seq = seq; + + m->m_data -= hlen; + m->m_len += hlen; + + if (len == -1 || len == 0) { + if (errno == ENETUNREACH) { + error_code = ICMP6_UNREACH_NO_ROUTE; + } else { + error_code = ICMP6_UNREACH_ADDRESS; + } + DEBUG_MISC(" udp icmp rx errno = %d-%s", errno, strerror(errno)); + icmp6_send_error(so->so_m, ICMP_UNREACH, error_code); + } else { + icmp6_reflect(so->so_m); + so->so_m = NULL; /* Don't m_free() it again! */ + } + icmp_detach(so); +} + +/* + * Send NDP Router Advertisement + */ +static void ndp_send_ra(Slirp *slirp) +{ + DEBUG_CALL("ndp_send_ra"); + + /* Build IPv6 packet */ + struct mbuf *t = m_get(slirp); + struct ip6 *rip = mtod(t, struct ip6 *); + size_t pl_size = 0; + struct in6_addr addr; + uint32_t scope_id; + + rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR; + rip->ip_dst = (struct in6_addr)ALLNODES_MULTICAST; + rip->ip_nh = IPPROTO_ICMPV6; + + /* Build ICMPv6 packet */ + t->m_data += sizeof(struct ip6); + struct icmp6 *ricmp = mtod(t, struct icmp6 *); + ricmp->icmp6_type = ICMP6_NDP_RA; + ricmp->icmp6_code = 0; + ricmp->icmp6_cksum = 0; + + /* NDP */ + ricmp->icmp6_nra.chl = NDP_AdvCurHopLimit; + ricmp->icmp6_nra.M = NDP_AdvManagedFlag; + ricmp->icmp6_nra.O = NDP_AdvOtherConfigFlag; + ricmp->icmp6_nra.reserved = 0; + ricmp->icmp6_nra.lifetime = htons(NDP_AdvDefaultLifetime); + ricmp->icmp6_nra.reach_time = htonl(NDP_AdvReachableTime); + ricmp->icmp6_nra.retrans_time = htonl(NDP_AdvRetransTime); + t->m_data += ICMP6_NDP_RA_MINLEN; + pl_size += ICMP6_NDP_RA_MINLEN; + + /* Source link-layer address (NDP option) */ + struct ndpopt *opt = mtod(t, struct ndpopt *); + opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE; + opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8; + in6_compute_ethaddr(rip->ip_src, opt->ndpopt_linklayer); + t->m_data += NDPOPT_LINKLAYER_LEN; + pl_size += NDPOPT_LINKLAYER_LEN; + + /* Prefix information (NDP option) */ + struct ndpopt *opt2 = mtod(t, struct ndpopt *); + opt2->ndpopt_type = NDPOPT_PREFIX_INFO; + opt2->ndpopt_len = NDPOPT_PREFIXINFO_LEN / 8; + opt2->ndpopt_prefixinfo.prefix_length = slirp->vprefix_len; + opt2->ndpopt_prefixinfo.L = 1; + opt2->ndpopt_prefixinfo.A = 1; + opt2->ndpopt_prefixinfo.reserved1 = 0; + opt2->ndpopt_prefixinfo.valid_lt = htonl(NDP_AdvValidLifetime); + opt2->ndpopt_prefixinfo.pref_lt = htonl(NDP_AdvPrefLifetime); + opt2->ndpopt_prefixinfo.reserved2 = 0; + opt2->ndpopt_prefixinfo.prefix = slirp->vprefix_addr6; + t->m_data += NDPOPT_PREFIXINFO_LEN; + pl_size += NDPOPT_PREFIXINFO_LEN; + + /* Prefix information (NDP option) */ + if (get_dns6_addr(&addr, &scope_id) >= 0) { + /* Host system does have an IPv6 DNS server, announce our proxy. */ + struct ndpopt *opt3 = mtod(t, struct ndpopt *); + opt3->ndpopt_type = NDPOPT_RDNSS; + opt3->ndpopt_len = NDPOPT_RDNSS_LEN / 8; + opt3->ndpopt_rdnss.reserved = 0; + opt3->ndpopt_rdnss.lifetime = htonl(2 * NDP_MaxRtrAdvInterval); + opt3->ndpopt_rdnss.addr = slirp->vnameserver_addr6; + t->m_data += NDPOPT_RDNSS_LEN; + pl_size += NDPOPT_RDNSS_LEN; + } + + rip->ip_pl = htons(pl_size); + t->m_data -= sizeof(struct ip6) + pl_size; + t->m_len = sizeof(struct ip6) + pl_size; + + /* ICMPv6 Checksum */ + ricmp->icmp6_cksum = ip6_cksum(t); + + ip6_output(NULL, t, 0); +} + +void ra_timer_handler(Slirp *slirp, void *unused) +{ + slirp->cb->timer_mod(slirp->ra_timer, + slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS + + NDP_Interval, + slirp->opaque); + ndp_send_ra(slirp); +} + +/* + * Send NDP Neighbor Solitication + */ +void ndp_send_ns(Slirp *slirp, struct in6_addr addr) +{ + char addrstr[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET6, &addr, addrstr, INET6_ADDRSTRLEN); + + DEBUG_CALL("ndp_send_ns"); + DEBUG_ARG("target = %s", addrstr); + + /* Build IPv6 packet */ + struct mbuf *t = m_get(slirp); + struct ip6 *rip = mtod(t, struct ip6 *); + rip->ip_src = slirp->vhost_addr6; + rip->ip_dst = (struct in6_addr)SOLICITED_NODE_PREFIX; + memcpy(&rip->ip_dst.s6_addr[13], &addr.s6_addr[13], 3); + rip->ip_nh = IPPROTO_ICMPV6; + rip->ip_pl = htons(ICMP6_NDP_NS_MINLEN + NDPOPT_LINKLAYER_LEN); + t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl); + + /* Build ICMPv6 packet */ + t->m_data += sizeof(struct ip6); + struct icmp6 *ricmp = mtod(t, struct icmp6 *); + ricmp->icmp6_type = ICMP6_NDP_NS; + ricmp->icmp6_code = 0; + ricmp->icmp6_cksum = 0; + + /* NDP */ + ricmp->icmp6_nns.reserved = 0; + ricmp->icmp6_nns.target = addr; + + /* Build NDP option */ + t->m_data += ICMP6_NDP_NS_MINLEN; + struct ndpopt *opt = mtod(t, struct ndpopt *); + opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE; + opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8; + in6_compute_ethaddr(slirp->vhost_addr6, opt->ndpopt_linklayer); + + /* ICMPv6 Checksum */ + t->m_data -= ICMP6_NDP_NA_MINLEN; + t->m_data -= sizeof(struct ip6); + ricmp->icmp6_cksum = ip6_cksum(t); + + ip6_output(NULL, t, 1); +} + +/* + * Send NDP Neighbor Advertisement + */ +static void ndp_send_na(Slirp *slirp, struct ip6 *ip, struct icmp6 *icmp) +{ + /* Build IPv6 packet */ + struct mbuf *t = m_get(slirp); + struct ip6 *rip = mtod(t, struct ip6 *); + rip->ip_src = icmp->icmp6_nns.target; + if (in6_zero(&ip->ip_src)) { + rip->ip_dst = (struct in6_addr)ALLNODES_MULTICAST; + } else { + rip->ip_dst = ip->ip_src; + } + rip->ip_nh = IPPROTO_ICMPV6; + rip->ip_pl = htons(ICMP6_NDP_NA_MINLEN + NDPOPT_LINKLAYER_LEN); + t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl); + + /* Build ICMPv6 packet */ + t->m_data += sizeof(struct ip6); + struct icmp6 *ricmp = mtod(t, struct icmp6 *); + ricmp->icmp6_type = ICMP6_NDP_NA; + ricmp->icmp6_code = 0; + ricmp->icmp6_cksum = 0; + + /* NDP */ + ricmp->icmp6_nna.R = NDP_IsRouter; + ricmp->icmp6_nna.S = !IN6_IS_ADDR_MULTICAST(&rip->ip_dst); + ricmp->icmp6_nna.O = 1; + ricmp->icmp6_nna.reserved_1 = 0; + ricmp->icmp6_nna.reserved_2 = 0; + ricmp->icmp6_nna.reserved_3 = 0; + ricmp->icmp6_nna.target = icmp->icmp6_nns.target; + + /* Build NDP option */ + t->m_data += ICMP6_NDP_NA_MINLEN; + struct ndpopt *opt = mtod(t, struct ndpopt *); + opt->ndpopt_type = NDPOPT_LINKLAYER_TARGET; + opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8; + in6_compute_ethaddr(ricmp->icmp6_nna.target, opt->ndpopt_linklayer); + + /* ICMPv6 Checksum */ + t->m_data -= ICMP6_NDP_NA_MINLEN; + t->m_data -= sizeof(struct ip6); + ricmp->icmp6_cksum = ip6_cksum(t); + + ip6_output(NULL, t, 0); +} + +/* + * Process a NDP message + */ +static void ndp_input(struct mbuf *m, Slirp *slirp, struct ip6 *ip, + struct icmp6 *icmp) +{ + assert(M_ROOMBEFORE(m) >= ETH_HLEN); + + m->m_len += ETH_HLEN; + m->m_data -= ETH_HLEN; + struct ethhdr *eth = mtod(m, struct ethhdr *); + m->m_len -= ETH_HLEN; + m->m_data += ETH_HLEN; + + switch (icmp->icmp6_type) { + case ICMP6_NDP_RS: + DEBUG_CALL(" type = Router Solicitation"); + if (ip->ip_hl == 255 && icmp->icmp6_code == 0 && + ntohs(ip->ip_pl) >= ICMP6_NDP_RS_MINLEN) { + /* Gratuitous NDP */ + ndp_table_add(slirp, ip->ip_src, eth->h_source); + + ndp_send_ra(slirp); + } + break; + + case ICMP6_NDP_RA: + DEBUG_CALL(" type = Router Advertisement"); + slirp->cb->guest_error("Warning: guest sent NDP RA, but shouldn't", + slirp->opaque); + break; + + case ICMP6_NDP_NS: + DEBUG_CALL(" type = Neighbor Solicitation"); + if (ip->ip_hl == 255 && icmp->icmp6_code == 0 && + !IN6_IS_ADDR_MULTICAST(&icmp->icmp6_nns.target) && + ntohs(ip->ip_pl) >= ICMP6_NDP_NS_MINLEN && + (!in6_zero(&ip->ip_src) || + in6_solicitednode_multicast(&ip->ip_dst))) { + if (in6_equal_host(&icmp->icmp6_nns.target)) { + /* Gratuitous NDP */ + ndp_table_add(slirp, ip->ip_src, eth->h_source); + ndp_send_na(slirp, ip, icmp); + } + } + break; + + case ICMP6_NDP_NA: + DEBUG_CALL(" type = Neighbor Advertisement"); + if (ip->ip_hl == 255 && icmp->icmp6_code == 0 && + ntohs(ip->ip_pl) >= ICMP6_NDP_NA_MINLEN && + !IN6_IS_ADDR_MULTICAST(&icmp->icmp6_nna.target) && + (!IN6_IS_ADDR_MULTICAST(&ip->ip_dst) || icmp->icmp6_nna.S == 0)) { + ndp_table_add(slirp, icmp->icmp6_nna.target, eth->h_source); + } + break; + + case ICMP6_NDP_REDIRECT: + DEBUG_CALL(" type = Redirect"); + slirp->cb->guest_error( + "Warning: guest sent NDP REDIRECT, but shouldn't", slirp->opaque); + break; + } +} + +/* + * Process a received ICMPv6 message. + */ +void icmp6_input(struct mbuf *m) +{ + Slirp *slirp = m->slirp; + /* NDP reads the ethernet header for gratuitous NDP */ + M_DUP_DEBUG(slirp, m, 1, ETH_HLEN); + + struct icmp6 *icmp; + struct ip6 *ip = mtod(m, struct ip6 *); + int hlen = sizeof(struct ip6); + + DEBUG_CALL("icmp6_input"); + DEBUG_ARG("m = %p", m); + DEBUG_ARG("m_len = %d", m->m_len); + + if (ntohs(ip->ip_pl) < ICMP6_MINLEN) { + freeit: + m_free(m); + goto end_error; + } + + if (ip6_cksum(m)) { + goto freeit; + } + + m->m_len -= hlen; + m->m_data += hlen; + icmp = mtod(m, struct icmp6 *); + m->m_len += hlen; + m->m_data -= hlen; + + DEBUG_ARG("icmp6_type = %d", icmp->icmp6_type); + switch (icmp->icmp6_type) { + case ICMP6_ECHO_REQUEST: + if (in6_equal_host(&ip->ip_dst)) { + icmp6_send_echoreply(m, slirp, ip, icmp); + } else if (slirp->restricted) { + goto freeit; + } else { + struct socket *so; + struct sockaddr_storage addr; + int ttl; + + so = socreate(slirp, IPPROTO_ICMPV6); + if (icmp6_send(so, m, hlen) == 0) { + /* We could send this as ICMP, good! */ + return; + } + + /* We could not send this as ICMP, try to send it on UDP echo + * service (7), wishfully hoping that it is open there. */ + + if (udp_attach(so, AF_INET6) == -1) { + DEBUG_MISC("icmp6_input udp_attach errno = %d-%s", errno, + strerror(errno)); + sofree(so); + m_free(m); + goto end_error; + } + so->so_m = m; + so->so_ffamily = AF_INET6; + so->so_faddr6 = ip->ip_dst; + so->so_fport = htons(7); + so->so_lfamily = AF_INET6; + so->so_laddr6 = ip->ip_src; + so->so_lport = htons(9); + so->so_state = SS_ISFCONNECTED; + + /* Send the packet */ + addr = so->fhost.ss; + if (sotranslate_out(so, &addr) < 0) { + icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE); + udp_detach(so); + return; + } + + /* + * Check for TTL + */ + ttl = ip->ip_hl-1; + if (ttl <= 0) { + DEBUG_MISC("udp ttl exceeded"); + icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS); + udp_detach(so); + break; + } + setsockopt(so->s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); + + if (sendto(so->s, icmp6_ping_msg, strlen(icmp6_ping_msg), 0, + (struct sockaddr *)&addr, sockaddr_size(&addr)) == -1) { + DEBUG_MISC("icmp6_input udp sendto tx errno = %d-%s", errno, + strerror(errno)); + icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE); + udp_detach(so); + } + } /* if (in6_equal_host(&ip->ip_dst)) */ + break; + + case ICMP6_NDP_RS: + case ICMP6_NDP_RA: + case ICMP6_NDP_NS: + case ICMP6_NDP_NA: + case ICMP6_NDP_REDIRECT: + ndp_input(m, slirp, ip, icmp); + m_free(m); + break; + + case ICMP6_UNREACH: + case ICMP6_TOOBIG: + case ICMP6_TIMXCEED: + case ICMP6_PARAMPROB: + /* XXX? report error? close socket? */ + default: + m_free(m); + break; + } + +end_error: + /* m is m_free()'d xor put in a socket xor or given to ip_send */ + return; +} + +#endif diff --git a/bochs/iodev/network/slirp/ip6_icmp.h b/bochs/iodev/network/slirp/ip6_icmp.h new file mode 100644 index 0000000000..a461911a1b --- /dev/null +++ b/bochs/iodev/network/slirp/ip6_icmp.h @@ -0,0 +1,246 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2013 + * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. + */ + +#ifndef SLIRP_IP6_ICMP_H +#define SLIRP_IP6_ICMP_H + +/* + * Interface Control Message Protocol version 6 Definitions. + * Per RFC 4443, March 2006. + * + * Network Discover Protocol Definitions. + * Per RFC 4861, September 2007. + */ + +struct icmp6_echo { /* Echo Messages */ + uint16_t id; + uint16_t seq_num; +}; + +union icmp6_error_body { + uint32_t unused; + uint32_t pointer; + uint32_t mtu; +}; + +/* + * NDP Messages + */ +struct ndp_rs { /* Router Solicitation Message */ + uint32_t reserved; +}; + +struct ndp_ra { /* Router Advertisement Message */ + uint8_t chl; /* Cur Hop Limit */ +#if defined(BX_BIG_ENDIAN) && !defined(_MSC_VER) + uint8_t M : 1, O : 1, reserved : 6; +#else + uint8_t reserved : 6, O : 1, M : 1; +#endif + uint16_t lifetime; /* Router Lifetime */ + uint32_t reach_time; /* Reachable Time */ + uint32_t retrans_time; /* Retrans Timer */ +}; + +BX_STATIC_ASSERT(sizeof(struct ndp_ra) == 12); + +struct ndp_ns { /* Neighbor Solicitation Message */ + uint32_t reserved; + struct in6_addr target; /* Target Address */ +}; + +BX_STATIC_ASSERT(sizeof(struct ndp_ns) == 20); + +struct ndp_na { /* Neighbor Advertisement Message */ +#if defined(BX_BIG_ENDIAN) && !defined(_MSC_VER) + uint8_t R : 1, /* Router Flag */ + S : 1, /* Solicited Flag */ + O : 1, /* Override Flag */ + reserved_1 : 5; +#else + uint8_t reserved_1 : 5, O : 1, S : 1, R : 1; +#endif + uint8_t reserved_2; + uint16_t reserved_3; + struct in6_addr target; /* Target Address */ +}; + +BX_STATIC_ASSERT(sizeof(struct ndp_na) == 20); + +struct ndp_redirect { + uint32_t reserved; + struct in6_addr target; /* Target Address */ + struct in6_addr dest; /* Destination Address */ +}; + +BX_STATIC_ASSERT(sizeof(struct ndp_redirect) == 36); + +/* + * Structure of an icmpv6 header. + */ +struct icmp6 { + uint8_t icmp6_type; /* type of message, see below */ + uint8_t icmp6_code; /* type sub code */ + uint16_t icmp6_cksum; /* ones complement cksum of struct */ + union { + union icmp6_error_body error_body; + struct icmp6_echo echo; + struct ndp_rs ndp_rs; + struct ndp_ra ndp_ra; + struct ndp_ns ndp_ns; + struct ndp_na ndp_na; + struct ndp_redirect ndp_redirect; + } icmp6_body; +#define icmp6_err icmp6_body.error_body +#define icmp6_echo icmp6_body.echo +#define icmp6_id icmp6_body.echo.id +#define icmp6_seq icmp6_body.echo.seq_num +#define icmp6_nrs icmp6_body.ndp_rs +#define icmp6_nra icmp6_body.ndp_ra +#define icmp6_nns icmp6_body.ndp_ns +#define icmp6_nna icmp6_body.ndp_na +#define icmp6_redirect icmp6_body.ndp_redirect +}; + +BX_STATIC_ASSERT(sizeof(struct icmp6) == 40); + +#define ICMP6_MINLEN 4 +#define ICMP6_ERROR_MINLEN 8 +#define ICMP6_ECHO_MINLEN 8 +#define ICMP6_NDP_RS_MINLEN 8 +#define ICMP6_NDP_RA_MINLEN 16 +#define ICMP6_NDP_NS_MINLEN 24 +#define ICMP6_NDP_NA_MINLEN 24 +#define ICMP6_NDP_REDIRECT_MINLEN 40 + +/* + * NDP Options + */ +SLIRP_PACKED_BEGIN +struct ndpopt { + uint8_t ndpopt_type; /* Option type */ + uint8_t ndpopt_len; /* /!\ In units of 8 octets */ + union { + unsigned char linklayer_addr[6]; /* Source/Target Link-layer */ +#define ndpopt_linklayer ndpopt_body.linklayer_addr + SLIRP_PACKED_BEGIN + struct prefixinfo { /* Prefix Information */ + uint8_t prefix_length; +#if defined(BX_BIG_ENDIAN) && !defined(_MSC_VER) + uint8_t L : 1, A : 1, reserved1 : 6; +#else + uint8_t reserved1 : 6, A : 1, L : 1; +#endif + uint32_t valid_lt; /* Valid Lifetime */ + uint32_t pref_lt; /* Preferred Lifetime */ + uint32_t reserved2; + struct in6_addr prefix; + } SLIRP_PACKED_END prefixinfo; +#define ndpopt_prefixinfo ndpopt_body.prefixinfo + SLIRP_PACKED_BEGIN + struct rdnss { + uint16_t reserved; + uint32_t lifetime; + struct in6_addr addr; + } SLIRP_PACKED_END rdnss; +#define ndpopt_rdnss ndpopt_body.rdnss + } ndpopt_body; +} SLIRP_PACKED_END; + +/* NDP options type */ +#define NDPOPT_LINKLAYER_SOURCE 1 /* Source Link-Layer Address */ +#define NDPOPT_LINKLAYER_TARGET 2 /* Target Link-Layer Address */ +#define NDPOPT_PREFIX_INFO 3 /* Prefix Information */ +#define NDPOPT_RDNSS 25 /* Recursive DNS Server Address */ + +/* NDP options size, in octets. */ +#define NDPOPT_LINKLAYER_LEN 8 +#define NDPOPT_PREFIXINFO_LEN 32 +#define NDPOPT_RDNSS_LEN 24 + +/* + * Definition of type and code field values. + * Per https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml + * Last Updated 2012-11-12 + */ + +/* Errors */ +#define ICMP6_UNREACH 1 /* Destination Unreachable */ +#define ICMP6_UNREACH_NO_ROUTE 0 /* no route to dest */ +#define ICMP6_UNREACH_DEST_PROHIB 1 /* com with dest prohibited */ +#define ICMP6_UNREACH_SCOPE 2 /* beyond scope of src addr */ +#define ICMP6_UNREACH_ADDRESS 3 /* address unreachable */ +#define ICMP6_UNREACH_PORT 4 /* port unreachable */ +#define ICMP6_UNREACH_SRC_FAIL 5 /* src addr failed */ +#define ICMP6_UNREACH_REJECT_ROUTE 6 /* reject route to dest */ +#define ICMP6_UNREACH_SRC_HDR_ERROR 7 /* error in src routing header */ +#define ICMP6_TOOBIG 2 /* Packet Too Big */ +#define ICMP6_TIMXCEED 3 /* Time Exceeded */ +#define ICMP6_TIMXCEED_INTRANS 0 /* hop limit exceeded in transit */ +#define ICMP6_TIMXCEED_REASS 1 /* ttl=0 in reass */ +#define ICMP6_PARAMPROB 4 /* Parameter Problem */ +#define ICMP6_PARAMPROB_HDR_FIELD 0 /* err header field */ +#define ICMP6_PARAMPROB_NXTHDR_TYPE 1 /* unrecognized Next Header type */ +#define ICMP6_PARAMPROB_IPV6_OPT 2 /* unrecognized IPv6 option */ + +/* Informational Messages */ +#define ICMP6_ECHO_REQUEST 128 /* Echo Request */ +#define ICMP6_ECHO_REPLY 129 /* Echo Reply */ +#define ICMP6_NDP_RS 133 /* Router Solicitation (NDP) */ +#define ICMP6_NDP_RA 134 /* Router Advertisement (NDP) */ +#define ICMP6_NDP_NS 135 /* Neighbor Solicitation (NDP) */ +#define ICMP6_NDP_NA 136 /* Neighbor Advertisement (NDP) */ +#define ICMP6_NDP_REDIRECT 137 /* Redirect Message (NDP) */ + +/* + * Router Configuration Variables (rfc4861#section-6) + */ +#define NDP_IsRouter 1 +#define NDP_AdvSendAdvertisements 1 +#define NDP_MaxRtrAdvInterval 600000 +#define NDP_MinRtrAdvInterval \ + ((NDP_MaxRtrAdvInterval >= 9) ? NDP_MaxRtrAdvInterval / 3 : \ + NDP_MaxRtrAdvInterval) +#define NDP_AdvManagedFlag 0 +#define NDP_AdvOtherConfigFlag 0 +#define NDP_AdvLinkMTU 0 +#define NDP_AdvReachableTime 0 +#define NDP_AdvRetransTime 0 +#define NDP_AdvCurHopLimit 64 +#define NDP_AdvDefaultLifetime ((3 * NDP_MaxRtrAdvInterval) / 1000) +#define NDP_AdvValidLifetime 86400 +#define NDP_AdvOnLinkFlag 1 +#define NDP_AdvPrefLifetime 14400 +#define NDP_AdvAutonomousFlag 1 + +/* Called from slirp_new, but after other initialization */ +void icmp6_post_init(Slirp *slirp); + +/* Called from slirp_cleanup */ +void icmp6_cleanup(Slirp *slirp); + +/* Process an ICMPv6 packet from the guest */ +void icmp6_input(struct mbuf *); + +/* Send an ICMPv6 error related to the given packet, using the given ICMPv6 type and code, using the given source */ +void icmp6_forward_error(struct mbuf *m, uint8_t type, uint8_t code, struct in6_addr *src); + +/* Similar to icmp6_forward_error, but use the link-local address as source */ +void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code); + +/* Forward the ICMP packet to the guest (probably a ping reply) */ +void icmp6_reflect(struct mbuf *); + +/* Handle ICMP data from the ICMP socket, and forward it to the guest (using so_m as reference) */ +void icmp6_receive(struct socket *so); + +/* Send a neighbour sollicitation, to resolve the given IPV6 address */ +void ndp_send_ns(Slirp *slirp, struct in6_addr addr); + +/* Timer handler for router advertisement, to send it and reschedule the timer */ +void ra_timer_handler(Slirp *slirp, void *unused); + +#endif diff --git a/bochs/iodev/network/slirp/ip6_input.cc b/bochs/iodev/network/slirp/ip6_input.cc new file mode 100644 index 0000000000..4e66bcf502 --- /dev/null +++ b/bochs/iodev/network/slirp/ip6_input.cc @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2013 + * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. + */ + +#include "slirp.h" +#include "ip6_icmp.h" + +#if BX_NETWORKING && BX_NETMOD_SLIRP + +/* + * IP initialization: fill in IP protocol switch table. + * All protocols not implemented in kernel go to raw IP protocol handler. + */ +void ip6_post_init(Slirp *slirp) +{ + icmp6_post_init(slirp); +} + +void ip6_cleanup(Slirp *slirp) +{ + icmp6_cleanup(slirp); +} + +void ip6_input(struct mbuf *m) +{ + Slirp *slirp = m->slirp; + /* NDP reads the ethernet header for gratuitous NDP */ + M_DUP_DEBUG(slirp, m, 1, TCPIPHDR_DELTA + 2 + ETH_HLEN); + + struct ip6 *ip6; + + if (!slirp->in6_enabled) { + goto bad; + } + + DEBUG_CALL("ip6_input"); + DEBUG_ARG("m = %p", m); + DEBUG_ARG("m_len = %d", m->m_len); + + if (m->m_len < (int)sizeof(struct ip6)) { + goto bad; + } + + ip6 = mtod(m, struct ip6 *); + + if (ip6->ip_v != IP6VERSION) { + goto bad; + } + + if (ntohs(ip6->ip_pl) + sizeof(struct ip6) > (unsigned)slirp->if_mtu) { + icmp6_send_error(m, ICMP6_TOOBIG, 0); + goto bad; + } + + // Check if the message size is big enough to hold what's + // set in the payload length header. If not this is an invalid + // packet + if (m->m_len < (int)(ntohs(ip6->ip_pl) + sizeof(struct ip6))) { + goto bad; + } + + /* check ip_ttl for a correct ICMP reply */ + if (ip6->ip_hl == 0) { + icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS); + goto bad; + } + + /* + * Switch out to protocol's input routine. + */ + switch (ip6->ip_nh) { + case IPPROTO_TCP: + NTOHS(ip6->ip_pl); + tcp_input(m, sizeof(struct ip6), (struct socket *)NULL, AF_INET6); + break; + case IPPROTO_UDP: + udp6_input(m); + break; + case IPPROTO_ICMPV6: + icmp6_input(m); + break; + default: + m_free(m); + } + return; +bad: + m_free(m); +} + +#endif diff --git a/bochs/iodev/network/slirp/ip6_output.cc b/bochs/iodev/network/slirp/ip6_output.cc new file mode 100644 index 0000000000..79ba902527 --- /dev/null +++ b/bochs/iodev/network/slirp/ip6_output.cc @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2013 + * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. + */ + +#include "slirp.h" + +#if BX_NETWORKING && BX_NETMOD_SLIRP + +/* Number of packets queued before we start sending + * (to prevent allocing too many mbufs) */ +#define IF6_THRESH 10 + +/* + * IPv6 output. The packet in mbuf chain m contains a IP header + */ +int ip6_output(struct socket *so, struct mbuf *m, int fast) +{ + Slirp *slirp = m->slirp; + M_DUP_DEBUG(slirp, m, 0, 0); + + struct ip6 *ip = mtod(m, struct ip6 *); + + DEBUG_CALL("ip6_output"); + DEBUG_ARG("so = %p", so); + DEBUG_ARG("m = %p", m); + + /* Fill IPv6 header */ + ip->ip_v = IP6VERSION; + ip->ip_hl = IP6_HOP_LIMIT; + ip->ip_tc_hi = 0; + ip->ip_tc_lo = 0; + ip->ip_fl_hi = 0; + ip->ip_fl_lo = 0; + + if (fast) { + /* We cannot fast-send non-multicast, we'd need a NDP NS */ + assert(IN6_IS_ADDR_MULTICAST(&ip->ip_dst)); + if_encap(m->slirp, m); + m_free(m); + } else { + if_output(so, m); + } + + return 0; +} + +#endif diff --git a/bochs/iodev/network/slirp/ip_icmp.cc b/bochs/iodev/network/slirp/ip_icmp.cc index 4987ce3eab..a286dfdd16 100644 --- a/bochs/iodev/network/slirp/ip_icmp.cc +++ b/bochs/iodev/network/slirp/ip_icmp.cc @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,7 +27,7 @@ * 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 8.2 (Berkeley) 1/4/94 * ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp */ @@ -38,20 +36,30 @@ #if BX_NETWORKING && BX_NETMOD_SLIRP +#ifndef _WIN32 +#include +#endif + +#ifndef WITH_ICMP_ERROR_MSG +#define WITH_ICMP_ERROR_MSG 0 +#endif + /* The message sent when emulating PING */ /* Be nice and tell them it's just a pseudo-ping packet */ -static const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; +static const char icmp_ping_msg[] = + "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST " + "packets.\n"; -/* list of actions for icmp_error() on RX of an icmp message */ +/* list of actions for icmp_send_error() on RX of an icmp message */ static const int icmp_flush[19] = { /* ECHO REPLY (0) */ 0, - 1, - 1, + 1, + 1, /* DEST UNREACH (3) */ 1, /* SOURCE QUENCH (4)*/ 1, /* REDIRECT (5) */ 1, - 1, - 1, + 1, + 1, /* ECHO (8) */ 0, /* ROUTERADVERT (9) */ 1, /* ROUTERSOLICIT (10) */ 1, @@ -73,39 +81,78 @@ void icmp_init(Slirp *slirp) void icmp_cleanup(Slirp *slirp) { - while (slirp->icmp.so_next != &slirp->icmp) { - icmp_detach(slirp->icmp.so_next); + struct socket *so, *so_next; + + for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) { + so_next = so->so_next; + icmp_detach(so); } } +/* Send ICMP packet to the Internet, and save it to so_m */ static int icmp_send(struct socket *so, struct mbuf *m, int hlen) { - struct ip *ip = mtod(m, struct ip *); + Slirp *slirp = m->slirp; + struct sockaddr_in addr; - so->s = qemu_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); + /* + * The behavior of reading SOCK_DGRAM+IPPROTO_ICMP sockets is inconsistent + * between host OSes. On Linux, only the ICMP header and payload is + * included. On macOS/Darwin, the socket acts like a raw socket and + * includes the IP header as well. On other BSDs, SOCK_DGRAM+IPPROTO_ICMP + * sockets aren't supported at all, so we treat them like raw sockets. It + * isn't possible to detect this difference at runtime, so we must use an + * #ifdef to determine if we need to remove the IP header. + */ +#if defined(BSD) && !defined(__GNU__) + so->so_type = IPPROTO_IP; +#else + so->so_type = IPPROTO_ICMP; +#endif + + so->s = slirp_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); + if (so->s == -1) { + if (errno == EAFNOSUPPORT + || errno == EPROTONOSUPPORT + || errno == EACCES) { + /* Kernel doesn't support or allow ping sockets. */ + so->so_type = IPPROTO_IP; + so->s = slirp_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + } + } if (so->s == -1) { return -1; } + so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque); + + if (slirp_bind_outbound(so, AF_INET) != 0) { + // bind failed - close socket + closesocket(so->s); + so->s = -1; + return -1; + } + + M_DUP_DEBUG(slirp, m, 0, 0); + struct ip *ip = mtod(m, struct ip *); so->so_m = m; so->so_faddr = ip->ip_dst; so->so_laddr = ip->ip_src; so->so_iptos = ip->ip_tos; - so->so_type = IPPROTO_ICMP; so->so_state = SS_ISFCONNECTED; so->so_expire = curtime + SO_EXPIRE; addr.sin_family = AF_INET; addr.sin_addr = so->so_faddr; - insque(so, &so->slirp->icmp); + slirp_insque(so, &so->slirp->icmp); if (sendto(so->s, m->m_data + hlen, m->m_len - hlen, 0, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - DEBUG_MISC((dfd, "icmp_input icmp sendto tx errno = %d-%s\n", - errno, strerror(errno))); - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno)); + DEBUG_MISC("icmp_input icmp sendto tx errno = %d-%s", errno, + strerror(errno)); + icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno)); icmp_detach(so); } @@ -114,6 +161,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen) void icmp_detach(struct socket *so) { + so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); closesocket(so->s); sofree(so); } @@ -121,121 +169,138 @@ void icmp_detach(struct socket *so) /* * Process a received ICMP message. */ -void -icmp_input(struct mbuf *m, int hlen) +void icmp_input(struct mbuf *m, int hlen) { - struct icmp *icp; - struct ip *ip=mtod(m, struct ip *); - int icmplen=ip->ip_len; - Slirp *slirp = m->slirp; - - DEBUG_CALL("icmp_input"); - DEBUG_ARG("m = %lx", (long )m); - DEBUG_ARG("m_len = %d", m->m_len); - - /* - * 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 */ - freeit: - m_free(m); - goto end_error; - } - - m->m_len -= hlen; - m->m_data += hlen; - icp = mtod(m, struct icmp *); - if (cksum(m, icmplen)) { - goto freeit; - } - m->m_len += hlen; - m->m_data -= hlen; - - DEBUG_ARG("icmp_type = %d", icp->icmp_type); - switch (icp->icmp_type) { - case ICMP_ECHO: - ip->ip_len += hlen; /* since ip_input subtracts this */ - if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) { - icmp_reflect(m); - } else if (slirp->restricted) { + Slirp *slirp = m->slirp; + M_DUP_DEBUG(slirp, m, 0, 0); + + struct icmp *icp; + struct ip *ip = mtod(m, struct ip *); + int icmplen=ip->ip_len; + + DEBUG_CALL("icmp_input"); + DEBUG_ARG("m = %p", m); + DEBUG_ARG("m_len = %d", m->m_len); + + /* + * 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 */ + freeit: + m_free(m); + goto end_error; + } + + m->m_len -= hlen; + m->m_data += hlen; + icp = mtod(m, struct icmp *); + if (cksum(m, icmplen)) { goto freeit; - } else { - struct socket *so; - struct sockaddr_in addr; - if ((so = socreate(slirp)) == NULL) goto freeit; - if (icmp_send(so, m, hlen) == 0) { - return; - } - 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 & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { - /* It's an alias */ - if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { - if (get_dns_addr(&addr.sin_addr) < 0) - addr.sin_addr = loopback_addr; - } else { - addr.sin_addr = loopback_addr; - } - } 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: - m_free(m); - break; - - default: - m_free(m); - } /* swith */ + } + m->m_len += hlen; + m->m_data -= hlen; + + DEBUG_ARG("icmp_type = %d", icp->icmp_type); + switch (icp->icmp_type) { + case ICMP_ECHO: + ip->ip_len += hlen; /* since ip_input subtracts this */ + if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr || + ip->ip_dst.s_addr == slirp->vnameserver_addr.s_addr) { + icmp_reflect(m); + } else if (slirp->restricted) { + goto freeit; + } else { + struct socket *so; + struct sockaddr_storage addr; + int ttl; + + so = socreate(slirp, IPPROTO_ICMP); + if (icmp_send(so, m, hlen) == 0) { + /* We could send this as ICMP, good! */ + return; + } + + /* We could not send this as ICMP, try to send it on UDP echo + * service (7), wishfully hoping that it is open there. */ + + if (udp_attach(so, AF_INET) == -1) { + DEBUG_MISC("icmp_input udp_attach errno = %d-%s", errno, + strerror(errno)); + sofree(so); + m_free(m); + goto end_error; + } + so->so_m = m; + so->so_ffamily = AF_INET; + so->so_faddr = ip->ip_dst; + so->so_fport = htons(7); + so->so_lfamily = AF_INET; + so->so_laddr = ip->ip_src; + so->so_lport = htons(9); + so->so_iptos = ip->ip_tos; + so->so_state = SS_ISFCONNECTED; + + /* Send the packet */ + addr = so->fhost.ss; + if (sotranslate_out(so, &addr) < 0) { + icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, + strerror(errno)); + udp_detach(so); + return; + } + + /* + * Check for TTL + */ + ttl = ip->ip_ttl-1; + if (ttl <= 0) { + DEBUG_MISC("udp ttl exceeded"); + icmp_send_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, + NULL); + udp_detach(so); + break; + } + setsockopt(so->s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); + + if (sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0, + (struct sockaddr *)&addr, sockaddr_size(&addr)) == -1) { + DEBUG_MISC("icmp_input udp sendto tx errno = %d-%s", errno, + strerror(errno)); + icmp_send_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: + m_free(m); + break; + + default: + m_free(m); + } /* switch */ end_error: - /* m is m_free()'d xor put in a socket xor or given to ip_send */ - return; + /* 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 + * 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. + * 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. @@ -247,175 +312,187 @@ icmp_input(struct mbuf *m, int hlen) */ #define ICMP_MAXDATALEN (IP_MSS-28) -void -icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize, - const char *message) +void icmp_forward_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize, + const char *message, struct in_addr *src) { - unsigned hlen, shlen, s_ip_len; - struct ip *ip; - struct icmp *icp; - 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 *); -#ifdef DEBUG - { char bufa[20], bufb[20]; - strcpy(bufa, inet_ntoa(ip->ip_src)); - strcpy(bufb, inet_ntoa(ip->ip_dst)); - DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb)); - } -#endif - if(ip->ip_off & IP_OFFMASK) goto end_error; /* Only reply to fragment 0 */ + unsigned hlen, shlen, s_ip_len; + struct ip *ip; + struct icmp *icp; + struct mbuf *m; + + DEBUG_CALL("icmp_send_error"); + DEBUG_ARG("msrc = %p", 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 (slirp_debug & DBG_MISC) { + char addr_src[INET_ADDRSTRLEN]; + char addr_dst[INET_ADDRSTRLEN]; + + inet_ntop(AF_INET, &ip->ip_src, addr_src, sizeof(addr_src)); + inet_ntop(AF_INET, &ip->ip_dst, addr_dst, sizeof(addr_dst)); + DEBUG_MISC(" %.16s to %.16s", addr_src, addr_dst); + } + if(ip->ip_off & IP_OFFMASK) + goto end_error; /* Only reply to fragment 0 */ - /* Do not reply to source-only IPs */ - if ((ip->ip_src.s_addr & htonl(~(0xf << 28))) == 0) { - goto end_error; - } + /* Do not reply to source-only IPs */ + if ((ip->ip_src.s_addr & htonl(~(0xf << 28))) == 0) { + goto end_error; + } - 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 */ - m = m_get(msrc->slirp); - if (!m) { - goto end_error; - } - - { 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); - -#ifdef 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 + 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 */ + m = m_get(msrc->slirp); + if (!m) { + goto end_error; + } + + { + 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->icmp_cksum = 0; - icp->icmp_cksum = cksum(m, m->m_len); + icp = mtod(m, struct icmp *); - m->m_data -= hlen; - m->m_len += hlen; + 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 (message && WITH_ICMP_ERROR_MSG) { /* 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; + } - /* fill in ip */ - ip->ip_hl = hlen >> 2; - ip->ip_len = m->m_len; + icp->icmp_cksum = 0; + icp->icmp_cksum = cksum(m, m->m_len); - ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */ + m->m_data -= hlen; + m->m_len += hlen; - ip->ip_ttl = MAXTTL; - ip->ip_p = IPPROTO_ICMP; - ip->ip_dst = ip->ip_src; /* ip addresses */ - ip->ip_src = m->slirp->vhost_addr; + /* fill in ip */ + ip->ip_hl = hlen >> 2; + ip->ip_len = 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 addresses */ + ip->ip_src = *src; - (void ) ip_output((struct socket *)NULL, m); + ip_output((struct socket *)NULL, m); end_error: return; } #undef ICMP_MAXDATALEN +void icmp_send_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize, + const char *message) +{ + icmp_forward_error(msrc, type, code, minsize, message, &msrc->slirp->vhost_addr); +} + /* * Reflect the ip packet back to the source */ -void -icmp_reflect(struct mbuf *m) +void icmp_reflect(struct mbuf *m) { - struct ip *ip = mtod(m, struct ip *); - int hlen = ip->ip_hl << 2; - int optlen = hlen - sizeof(struct ip ); - 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_type = ICMP_ECHOREPLY; - 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) { + struct ip *ip = mtod(m, struct ip *); + int hlen = ip->ip_hl << 2; + int optlen = hlen - sizeof(struct ip ); + struct icmp *icp; + /* - * Strip out original options by copying rest of first - * mbuf's data back, and adjust the IP length. + * Send an icmp packet back to the ip level, + * after supplying a checksum. */ - 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); + m->m_data += hlen; + m->m_len -= hlen; + icp = mtod(m, struct icmp *); + + icp->icmp_type = ICMP_ECHOREPLY; + 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((char *)(ip + 1), (char *)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; + } + + ip_output((struct socket *)NULL, m); } void icmp_receive(struct socket *so) @@ -423,7 +500,7 @@ void icmp_receive(struct socket *so) struct mbuf *m = so->so_m; struct ip *ip = mtod(m, struct ip *); int hlen = ip->ip_hl << 2; - u_char error_code; + uint8_t error_code; struct icmp *icp; int id, len; @@ -432,7 +509,25 @@ void icmp_receive(struct socket *so) icp = mtod(m, struct icmp *); id = icp->icmp_id; - len = qemu_recv(so->s, icp, m->m_len, 0); + len = recv(so->s, icp, M_ROOM(m), 0); + + if (so->so_type == IPPROTO_IP) { + if (len >= (int)sizeof(struct ip)) { + struct ip *inner_ip = mtod(m, struct ip *); + int inner_hlen = inner_ip->ip_hl << 2; + if (inner_hlen > len) { + len = -1; + errno = -EINVAL; + } else { + len -= inner_hlen; + memmove(icp, (unsigned char *)icp + inner_hlen, len); + } + } else { + len = -1; + errno = -EINVAL; + } + } + icp->icmp_id = id; m->m_data -= hlen; @@ -444,9 +539,8 @@ void icmp_receive(struct socket *so) } else { error_code = ICMP_UNREACH_HOST; } - DEBUG_MISC((dfd, " udp icmp rx errno = %d-%s\n", errno, - strerror(errno))); - icmp_error(so->so_m, ICMP_UNREACH, error_code, 0, strerror(errno)); + DEBUG_MISC(" udp icmp rx errno = %d-%s", errno, strerror(errno)); + icmp_send_error(so->so_m, ICMP_UNREACH, error_code, 0, strerror(errno)); } else { icmp_reflect(so->so_m); so->so_m = NULL; /* Don't m_free() it again! */ diff --git a/bochs/iodev/network/slirp/ip_icmp.h b/bochs/iodev/network/slirp/ip_icmp.h index fc9002bf04..3fb7291c69 100644 --- a/bochs/iodev/network/slirp/ip_icmp.h +++ b/bochs/iodev/network/slirp/ip_icmp.h @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,12 +27,12 @@ * 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 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_ +#ifndef NETINET_IP_ICMP_H +#define NETINET_IP_ICMP_H /* * Interface Control Message Protocol Definitions. @@ -47,50 +45,50 @@ typedef uint32_t n_time; * Structure of an icmp header. */ 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 + uint8_t icmp_type; /* type of message, see below */ + uint8_t icmp_code; /* type sub code */ + uint16_t icmp_cksum; /* ones complement cksum of struct */ + union { + uint8_t ih_pptr; /* ICMP_PARAMPROB */ + struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ + struct ih_idseq { + uint16_t icd_id; + uint16_t icd_seq; + } ih_idseq; + int ih_void; + + /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ + struct ih_pmtu { + uint16_t ipm_void; + uint16_t 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 }; /* @@ -101,68 +99,85 @@ struct icmp { * 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 */ +#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) +#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) +/* Called from slirp_new */ void icmp_init(Slirp *slirp); + +/* Called from slirp_cleanup */ void icmp_cleanup(Slirp *slirp); + +/* Process an ICMP packet from the guest */ void icmp_input(struct mbuf *, int); -void icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize, - const char *message); + +/* Send an ICMP error related to the given packet, using the given ICMP type and code, appending the given message (if enabled at compilation), and using the given source. If minsize is sent, send only header + 8B of the given packet, otherwise send it all */ +void icmp_forward_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize, + const char *message, struct in_addr *src); + +/* Similar to icmp_forward_error, but use the virtual host address as source */ +void icmp_send_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize, + const char *message); + +/* Forward the ICMP packet to the guest (probably a ping reply) */ void icmp_reflect(struct mbuf *); + +/* Handle ICMP data from the ICMP socket, and forward it to the guest (using so_m as reference) */ void icmp_receive(struct socket *so); + +/* Forget about this pending ICMP request */ void icmp_detach(struct socket *so); #endif diff --git a/bochs/iodev/network/slirp/ip_input.cc b/bochs/iodev/network/slirp/ip_input.cc index 6a4260a1be..97872fdfaf 100644 --- a/bochs/iodev/network/slirp/ip_input.cc +++ b/bochs/iodev/network/slirp/ip_input.cc @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,16 +27,13 @@ * 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 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 "slirp.h" @@ -48,9 +43,8 @@ static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp); static void ip_freef(Slirp *slirp, struct ipq *fp); -static void ip_enq(struct ipasfrag *p, - struct ipasfrag *prev); -static void ip_deq(struct ipasfrag *p); +static void ip_enq(struct ipas *p, struct ipas *prev); +static void ip_deq(struct ipas *p); /* * IP initialization: fill in IP protocol switch table. @@ -71,608 +65,390 @@ void ip_cleanup(Slirp *slirp) icmp_cleanup(slirp); } -static inline struct ipq *container_of_ip_link(void *ptr) -{ - return reinterpret_cast(static_cast(ptr) - - reinterpret_cast(&(static_cast(0)->ip_link))); -} - /* * Ip input routine. Checksum and byte swap header. If fragmented * try to reassemble. Process options. Pass to next level. */ void ip_input(struct mbuf *m) { - Slirp *slirp = m->slirp; - struct ip *ip; - int hlen; - - DEBUG_CALL("ip_input"); - DEBUG_ARG("m = %lx", (long)m); - DEBUG_ARG("m_len = %d", m->m_len); - - if (m->m_len < (int)sizeof(struct ip)) { - return; - } - - ip = mtod(m, struct ip *); - - if (ip->ip_v != IPVERSION) { - goto bad; - } - - hlen = ip->ip_hl << 2; - if (hlen < (int)sizeof(struct ip) || hlen>m->m_len) {/* min header length */ - goto bad; /* or packet too short */ - } - - /* keep ip header intact for ICMP reply - * ip->ip_sum = cksum(m, hlen); - * if (ip->ip_sum) { - */ - if(cksum(m,hlen)) { - goto bad; - } - - /* - * Convert fields to host representation. - */ - NTOHS(ip->ip_len); - if (ip->ip_len < hlen) { - 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) { - 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) { - icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); - goto bad; - } - - /* - * 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) { - struct ipq *fp; - struct qlink *l; - /* - * Look for queue of fragments - * of this datagram. - */ - for (l = (qlink*)slirp->ipq.ip_link.next; l != &slirp->ipq.ip_link; - l = (qlink*)l->next) { - fp = container_of_ip_link(l); - 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; + Slirp *slirp = m->slirp; + M_DUP_DEBUG(slirp, m, 0, TCPIPHDR_DELTA); + + struct ip *ip; + int hlen; + + if (!slirp->in_enabled) { + goto bad; + } + + DEBUG_CALL("ip_input"); + DEBUG_ARG("m = %p", m); + DEBUG_ARG("m_len = %d", m->m_len); + + if (m->m_len < (int)sizeof(struct ip)) { + goto bad; + } + + ip = mtod(m, struct ip *); + + if (ip->ip_v != IPVERSION) { + goto bad; + } + + hlen = ip->ip_hl << 2; + if (hlen < (int)sizeof(struct ip) || hlen>m->m_len) { /* min header length */ + goto bad; /* or packet too short */ + } + + /* keep ip header intact for ICMP reply + * ip->ip_sum = cksum(m, hlen); + * if (ip->ip_sum) { + */ + if (cksum(m, hlen)) { + goto bad; + } + + /* + * Convert fields to host representation. + */ + NTOHS(ip->ip_len); + if (ip->ip_len < hlen) { + 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) { + 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) { + icmp_send_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); + goto bad; + } + + /* + * 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) { + struct ipq *q; + struct qlink *l; + /* + * Look for queue of fragments + * of this datagram. + */ + for (l = (qlink*)slirp->ipq.ip_link.next; l != &slirp->ipq.ip_link; + l = (qlink*)l->next) { + q = container_of(l, struct ipq, ip_link); + if (ip->ip_id == q->ipq_id && + ip->ip_src.s_addr == q->ipq_src.s_addr && + ip->ip_dst.s_addr == q->ipq_dst.s_addr && + ip->ip_p == q->ipq_p) + goto found; } - fp = NULL; - 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) - ip->ip_tos |= 1; - else - ip->ip_tos &= ~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 (ip->ip_tos & 1 || ip->ip_off) { - ip = ip_reass(slirp, ip, fp); - if (ip == NULL) - return; - m = dtom(slirp, ip); - } else - if (fp) - ip_freef(slirp, fp); - - } else - ip->ip_len -= hlen; - - /* - * Switch out to protocol's input routine. - */ - 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: - m_free(m); - } - return; + q = NULL; + 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) + ip->ip_tos |= 1; + else + ip->ip_tos &= ~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 (ip->ip_tos & 1 || ip->ip_off) { + ip = ip_reass(slirp, ip, q); + if (ip == NULL) + return; + m = dtom(slirp, ip); + } else if (q) + ip_freef(slirp, q); + + } else + ip->ip_len -= hlen; + + /* + * Switch out to protocol's input routine. + */ + switch (ip->ip_p) { + case IPPROTO_TCP: + tcp_input(m, hlen, (struct socket *)NULL, AF_INET); + break; + case IPPROTO_UDP: + udp_input(m, hlen); + break; + case IPPROTO_ICMP: + icmp_input(m, hlen); + break; + default: + m_free(m); + } + return; bad: - m_free(m); + m_free(m); } -#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink))) -#define fragtoip(P) ((struct ip*)(((char*)(P)) + sizeof(struct qlink))) +#define iptoas(P) container_of((P), struct ipas, ipf_ip) +#define astoip(P) (&(P)->ipf_ip) /* * 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. + * is given as q; otherwise have to make a chain. */ -static struct ip * -ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) +static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *q) { - struct mbuf *m = dtom(slirp, ip); - 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 == NULL) { - struct mbuf *t = m_get(slirp); - - if (t == NULL) { - goto dropfrag; - } - fp = mtod(t, struct ipq *); - insque(&fp->ip_link, &slirp->ipq.ip_link); - fp->ipq_ttl = IPFRAGTTL; - fp->ipq_p = ip->ip_p; - fp->ipq_id = ip->ip_id; - fp->frag_link.next = fp->frag_link.prev = &fp->frag_link; - fp->ipq_src = ip->ip_src; - fp->ipq_dst = ip->ip_dst; - q = (struct ipasfrag *)fp; - goto insert; - } - - /* - * Find a segment which begins after this one does. - */ - for (q = (struct ipasfrag *)fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; - q = (struct ipasfrag *)q->ipf_next) - if (q->ipf_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 != &fp->frag_link) { - struct ipasfrag *pq = (struct ipasfrag*)q->ipf_prev; - i = pq->ipf_off + pq->ipf_len - ip->ip_off; - if (i > 0) { - if (i >= ip->ip_len) - goto dropfrag; - m_adj(dtom(slirp, 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->frag_link && - ip->ip_off + ip->ip_len > q->ipf_off) { - i = (ip->ip_off + ip->ip_len) - q->ipf_off; - if (i < q->ipf_len) { - q->ipf_len -= i; - q->ipf_off += i; - m_adj(dtom(slirp, q), i); - break; - } - q = (struct ipasfrag*)q->ipf_next; - m_free(dtom(slirp, q->ipf_prev)); - ip_deq((struct ipasfrag*)q->ipf_prev); - } + struct mbuf *m = dtom(slirp, ip); + struct ipas *first = container_of(q, struct ipas, ipq); + struct ipas *cursor; + int hlen = ip->ip_hl << 2; + int delta, i, next; + + DEBUG_CALL("ip_reass"); + DEBUG_ARG("ip = %p", ip); + DEBUG_ARG("q = %p", q); + DEBUG_ARG("m = %p", 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 (q == NULL) { + struct mbuf *t = m_get(slirp); + + if (t == NULL) { + goto dropfrag; + } + first = mtod(t, struct ipas *); + q = &first->ipq; + slirp_insque(&q->ip_link, &slirp->ipq.ip_link); + q->ipq_ttl = IPFRAGTTL; + q->ipq_p = ip->ip_p; + q->ipq_id = ip->ip_id; + first->link.next = first->link.prev = first; + q->ipq_src = ip->ip_src; + q->ipq_dst = ip->ip_dst; + cursor = first; + goto insert; + } + + /* + * Find a segment which begins after this one does. + */ + for (cursor = (ipas*)first->link.next; cursor != first; cursor = (ipas*)cursor->link.next) + if (cursor->ipf_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 (cursor->link.prev != first) { + struct ipas *pq = (ipas*)cursor->link.prev; + i = pq->ipf_off + pq->ipf_len - ip->ip_off; + if (i > 0) { + if (i >= ip->ip_len) + goto dropfrag; + m_adj(dtom(slirp, 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 (cursor != first && ip->ip_off + ip->ip_len > cursor->ipf_off) { + struct ipas *prev; + i = (ip->ip_off + ip->ip_len) - cursor->ipf_off; + if (i < cursor->ipf_len) { + cursor->ipf_len -= i; + cursor->ipf_off += i; + m_adj(dtom(slirp, cursor), i); + break; + } + prev = cursor; + cursor = (ipas*)cursor->link.next; + ip_deq(prev); + m_free(dtom(slirp, prev)); + } insert: - /* - * Stick new segment in its place; - * check for complete reassembly. - */ - ip_enq(iptofrag(ip), (struct ipasfrag*)q->ipf_prev); - next = 0; - for (q = (struct ipasfrag*)fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; - q = (struct ipasfrag*)q->ipf_next) { - if (q->ipf_off != next) - return NULL; - next += q->ipf_len; - } - if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1) + /* + * Stick new segment in its place; + * check for complete reassembly. + */ + ip_enq(iptoas(ip), (ipas*)cursor->link.prev); + next = 0; + for (cursor = (ipas*)first->link.next; cursor != first; cursor = (ipas*)cursor->link.next) { + if (cursor->ipf_off != next) + return NULL; + next += cursor->ipf_len; + } + if (((struct ipas *)(cursor->link.prev))->ipf_tos & 1) return NULL; - /* - * Reassembly is complete; concatenate fragments. - */ - q = (struct ipasfrag *)fp->frag_link.next; - m = dtom(slirp, q); - - q = (struct ipasfrag *) q->ipf_next; - while (q != (struct ipasfrag*)&fp->frag_link) { - struct mbuf *t = dtom(slirp, 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. - */ - q = (struct ipasfrag *)fp->frag_link.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 = (char *)q - m->m_dat; - q = (struct ipasfrag *)(m->m_ext + delta); - } - - ip = fragtoip(q); - ip->ip_len = next; - ip->ip_tos &= ~1; - ip->ip_src = fp->ipq_src; - ip->ip_dst = fp->ipq_dst; - remque(&fp->ip_link); - (void) m_free(dtom(slirp, fp)); - m->m_len += (ip->ip_hl << 2); - m->m_data -= (ip->ip_hl << 2); - - return ip; + /* + * Reassembly is complete; concatenate fragments. + */ + cursor = (ipas*)first->link.next; + m = dtom(slirp, cursor); + delta = (char *)cursor - (m->m_flags & M_EXT ? m->m_ext : m->m_dat); + + cursor = (ipas*)cursor->link.next; + while (cursor != first) { + struct mbuf *t = dtom(slirp, cursor); + cursor = (ipas*)cursor->link.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. + */ + cursor = (ipas*)first->link.next; + + /* + * If the fragments concatenated to an mbuf that's bigger than the total + * size of the fragment and the mbuf was not already using an m_ext buffer, + * then an m_ext buffer was allocated. But q->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) { + cursor = (struct ipas *)(m->m_ext + delta); + } + + ip = astoip(cursor); + ip->ip_len = next; + ip->ip_tos &= ~1; + ip->ip_src = q->ipq_src; + ip->ip_dst = q->ipq_dst; + slirp_remque(&q->ip_link); + m_free(dtom(slirp, q)); + m->m_len += (ip->ip_hl << 2); + m->m_data -= (ip->ip_hl << 2); + + return ip; dropfrag: - m_free(m); - return NULL; + m_free(m); + return NULL; } /* * Free a fragment reassembly header and all * associated datagrams. */ -static void -ip_freef(Slirp *slirp, struct ipq *fp) +static void ip_freef(Slirp *slirp, struct ipq *q) { - struct ipasfrag *q, *p; - - for (q = (struct ipasfrag *)fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) { - p = (struct ipasfrag *)q->ipf_next; - ip_deq(q); - m_free(dtom(slirp, q)); - } - remque(&fp->ip_link); - (void) m_free(dtom(slirp, fp)); + struct ipas *first = container_of(q, struct ipas, ipq); + struct ipas *cursor, *next; + + for (cursor = (ipas*)first->link.next; cursor != first; cursor = next) { + next = (ipas*)cursor->link.next; + ip_deq(cursor); + m_free(dtom(slirp, cursor)); + } + slirp_remque(&q->ip_link); + m_free(dtom(slirp, q)); } /* * Put an ip fragment on a reassembly chain. - * Like insque, but pointers in middle of structure. + * Like slirp_insque, but pointers in middle of structure. */ -static void -ip_enq(struct ipasfrag *p, struct ipasfrag *prev) +static void ip_enq(struct ipas *p, struct ipas *prev) { - DEBUG_CALL("ip_enq"); - DEBUG_ARG("prev = %lx", (long)prev); - p->ipf_prev = prev; - p->ipf_next = prev->ipf_next; - ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p; - prev->ipf_next = p; + DEBUG_CALL("ip_enq"); + DEBUG_ARG("prev = %p", prev); + p->link.prev = prev; + p->link.next = prev->link.next; + ((struct ipas *)(prev->link.next))->link.prev = p; + prev->link.next = p; } /* - * To ip_enq as remque is to insque. + * To ip_enq as slirp_remque is to slirp_insque. */ -static void -ip_deq(struct ipasfrag *p) +static void ip_deq(struct ipas *p) { - ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; - ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; + ((struct ipas *)(p->link.prev))->link.next = p->link.next; + ((struct ipas *)(p->link.next))->link.prev = p->link.prev; } -/* - * IP timer processing; - * if a timer expires on a reassembly - * queue, discard it. - */ -void -ip_slowtimo(Slirp *slirp) +void ip_slowtimo(Slirp *slirp) { struct qlink *l; - DEBUG_CALL("ip_slowtimo"); + DEBUG_CALL("ip_slowtimo"); l = (struct qlink*)slirp->ipq.ip_link.next; - if (l == NULL) - return; + if (l == NULL) + return; while (l != &slirp->ipq.ip_link) { - struct ipq *fp = container_of_ip_link(l); + struct ipq *q = container_of(l, struct ipq, ip_link); l = (struct qlink*)l->next; - if (--fp->ipq_ttl == 0) { - ip_freef(slirp, fp); - } + if (--q->ipq_ttl == 0) { + ip_freef(slirp, q); + } } } -/* - * 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; -{ - struct ip *ip = mtod(m, struct ip *); - u_char *cp; - struct ip_timestamp *ipt; - struct in_ifaddr *ia; - int opt, optlen, cnt, off, code, type, forward = 0; - struct in_addr *sin, dst; -typedef uint32_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: - icmp_error(m, type, code, 0, 0); - - 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(struct mbuf *m, struct mbuf *mopt) +void ip_stripoptions(struct mbuf *m) { - int i; - struct ip *ip = mtod(m, struct ip *); - 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; + int i; + struct ip *ip = mtod(m, struct ip *); + char *opts; + int olen; + + olen = (ip->ip_hl<<2) - sizeof (struct ip); + opts = (char *)(ip + 1); + i = m->m_len - (sizeof (struct ip) + olen); + memmove(opts, opts + olen, (unsigned)i); + m->m_len -= olen; + + ip->ip_hl = sizeof(struct ip) >> 2; } #endif diff --git a/bochs/iodev/network/slirp/ip_output.cc b/bochs/iodev/network/slirp/ip_output.cc index a4510d3cce..cb39faffb2 100644 --- a/bochs/iodev/network/slirp/ip_output.cc +++ b/bochs/iodev/network/slirp/ip_output.cc @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,16 +27,13 @@ * 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 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 "slirp.h" @@ -55,126 +50,126 @@ * The mbuf chain containing the packet will be freed. * The mbuf opt, if present, will not be freed. */ -int -ip_output(struct socket *so, struct mbuf *m0) +int ip_output(struct socket *so, struct mbuf *m0) { - Slirp *slirp = m0->slirp; - struct ip *ip; - struct mbuf *m = m0; - int hlen = sizeof(struct ip ); - int len, off, error = 0; - - DEBUG_CALL("ip_output"); - DEBUG_ARG("so = %lx", (long)so); - DEBUG_ARG("m0 = %lx", (long)m0); - - ip = mtod(m, struct ip *); - /* - * Fill in IP header. - */ - ip->ip_v = IPVERSION; - ip->ip_off &= IP_DF; - slirp->ip_id++; - ip->ip_id = htons(slirp->ip_id); - ip->ip_hl = hlen >> 2; - - /* - * If small enough for interface, can just send directly. - */ - if ((uint16_t)ip->ip_len <= IF_MTU) { - ip->ip_len = htons((uint16_t)ip->ip_len); - ip->ip_off = htons((uint16_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; - goto bad; - } - - len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */ - if (len < 8) { - error = -1; - goto bad; - } + Slirp *slirp = m0->slirp; + M_DUP_DEBUG(slirp, m0, 0, 0); + + struct ip *ip; + struct mbuf *m = m0; + int hlen = sizeof(struct ip ); + int len, off, error = 0; + + DEBUG_CALL("ip_output"); + DEBUG_ARG("so = %p", so); + DEBUG_ARG("m0 = %p", m0); + + ip = mtod(m, struct ip *); + /* + * Fill in IP header. + */ + ip->ip_v = IPVERSION; + ip->ip_off &= IP_DF; + ip->ip_id = htons(slirp->ip_id++); + ip->ip_hl = hlen >> 2; + + /* + * If small enough for interface, can just send directly. + */ + if ((uint16_t)ip->ip_len <= slirp->if_mtu) { + ip->ip_len = htons((uint16_t)ip->ip_len); + ip->ip_off = htons((uint16_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; + goto bad; + } + + len = (slirp->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 < (uint16_t)ip->ip_len; off += len) { - struct ip *mhip; - m = m_get(slirp); - if (m == NULL) { - error = -1; - goto sendorfree; - } - m->m_data += IF_MAXLINKHDR; - mhip = mtod(m, struct ip *); - *mhip = *ip; - - 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 >= (uint16_t)ip->ip_len) - len = (uint16_t)ip->ip_len - off; - else - mhip->ip_off |= IP_MF; - mhip->ip_len = htons((uint16_t)(len + mhlen)); - - if (m_copy(m, m0, off, len) < 0) { - error = -1; - goto sendorfree; - } - - mhip->ip_off = htons((uint16_t)mhip->ip_off); - mhip->ip_sum = 0; - mhip->ip_sum = cksum(m, mhlen); - *mnext = m; - mnext = &m->m_nextpkt; - } - /* - * 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 - (uint16_t)ip->ip_len); - ip->ip_len = htons((uint16_t)m->m_len); - ip->ip_off = htons((uint16_t)(ip->ip_off | IP_MF)); - ip->ip_sum = 0; - ip->ip_sum = cksum(m, hlen); + 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 < (uint16_t)ip->ip_len; off += len) { + struct ip *mhip; + m = m_get(slirp); + if (m == NULL) { + error = -1; + goto sendorfree; + } + m->m_data += IF_MAXLINKHDR; + mhip = mtod(m, struct ip *); + *mhip = *ip; + + 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 >= (uint16_t)ip->ip_len) + len = (uint16_t)ip->ip_len - off; + else + mhip->ip_off |= IP_MF; + mhip->ip_len = htons((uint16_t)(len + mhlen)); + + if (m_copy(m, m0, off, len) < 0) { + error = -1; + goto sendorfree; + } + + mhip->ip_off = htons((uint16_t)mhip->ip_off); + mhip->ip_sum = 0; + mhip->ip_sum = cksum(m, mhlen); + *mnext = m; + mnext = &m->m_nextpkt; + } + /* + * 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 - (uint16_t)ip->ip_len); + ip->ip_len = htons((uint16_t)m->m_len); + ip->ip_off = htons((uint16_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 = NULL; - if (error == 0) - if_output(so, m); - else - m_free(m); - } + for (m = m0; m; m = m0) { + m0 = m->m_nextpkt; + m->m_nextpkt = NULL; + if (error == 0) + if_output(so, m); + else + m_free(m); + } } done: - return (error); + return (error); bad: - m_free(m0); - goto done; + m_free(m0); + goto done; } #endif diff --git a/bochs/iodev/network/slirp/libslirp.h b/bochs/iodev/network/slirp/libslirp.h index 45cb31c014..354dda58a9 100644 --- a/bochs/iodev/network/slirp/libslirp.h +++ b/bochs/iodev/network/slirp/libslirp.h @@ -1,48 +1,294 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ +#ifndef LIBSLIRP_H +#define LIBSLIRP_H -#ifndef _LIBSLIRP_H -#define _LIBSLIRP_H +#include +#include +#include -#include "compat.h" +#ifdef _WIN32 +#include +#include +#include +#include +typedef Bit64s slirp_ssize_t; +#else +#include +typedef ssize_t slirp_ssize_t; +#include +#include +#endif -struct Slirp; +/* Opaque structure containing the slirp state */ typedef struct Slirp Slirp; -int get_dns_addr(struct in_addr *pdns_addr); +/* Flags passed to SlirpAddPollCb and to be returned by SlirpGetREventsCb. */ +enum { + SLIRP_POLL_IN = 1 << 0, + SLIRP_POLL_OUT = 1 << 1, + SLIRP_POLL_PRI = 1 << 2, + SLIRP_POLL_ERR = 1 << 3, + SLIRP_POLL_HUP = 1 << 4, +}; + +/* Callback for application to get data from the guest */ +typedef slirp_ssize_t (*SlirpReadCb)(void *buf, size_t len, void *opaque); +/* Callback for application to send data to the guest */ +typedef slirp_ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque); +/* Timer callback */ +typedef void (*SlirpTimerCb)(void *opaque); +/* Callback for libslirp to register polling callbacks */ +typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque); +/* Callback for libslirp to get polling result */ +typedef int (*SlirpGetREventsCb)(int idx, void *opaque); + +/* For now libslirp creates only a timer for the IPv6 RA */ +typedef enum SlirpTimerId { + SLIRP_TIMER_RA, + SLIRP_TIMER_NUM, +} SlirpTimerId; + +/* + * Callbacks from slirp, to be set by the application. + * + * The opaque parameter is set to the opaque pointer given in the slirp_new / + * slirp_init call. + */ +typedef struct SlirpCb { + /* + * Send an ethernet frame to the guest network. The opaque parameter is the + * one given to slirp_init(). If the guest is not ready to receive a frame, + * the function can just drop the data. TCP will then handle retransmissions + * at a lower pace. + * <0 reports an IO error. + */ + SlirpWriteCb send_packet; + /* Print a message for an error due to guest misbehavior. */ + void (*guest_error)(const char *msg, void *opaque); + /* Return the virtual clock value in nanoseconds */ + int64_t (*clock_get_ns)(void *opaque); + /* Create a new timer with the given callback and opaque data. Not + * needed if timer_new_opaque is provided. */ + void *(*timer_new)(SlirpTimerCb cb, void *cb_opaque, void *opaque); + /* Remove and free a timer */ + void (*timer_free)(void *timer, void *opaque); + /* Modify a timer to expire at @expire_time (ms) */ + void (*timer_mod)(void *timer, int64_t expire_time, void *opaque); + /* Register a fd for future polling */ + void (*register_poll_fd)(int fd, void *opaque); + /* Unregister a fd */ + void (*unregister_poll_fd)(int fd, void *opaque); + /* Kick the io-thread, to signal that new events may be processed because some TCP buffer + * can now receive more data, i.e. slirp_socket_can_recv will return 1. */ + void (*notify)(void *opaque); + + /* + * Fields introduced in SlirpConfig version 4 begin + */ + + /* Initialization has completed and a Slirp* has been created. */ + void (*init_completed)(Slirp *slirp, void *opaque); + /* Create a new timer. When the timer fires, the application passes + * the SlirpTimerId and cb_opaque to slirp_handle_timer. */ + void *(*timer_new_opaque)(SlirpTimerId id, void *cb_opaque, void *opaque); +} SlirpCb; + +#define SLIRP_CONFIG_VERSION_MIN 1 +#define SLIRP_CONFIG_VERSION_MAX 5 + +typedef struct SlirpConfig { + /* Version must be provided */ + uint32_t version; + /* + * Fields introduced in SlirpConfig version 1 begin + */ + /* Whether to prevent the guest from accessing the Internet */ + int restricted; + /* Whether IPv4 is enabled */ + bool in_enabled; + /* Virtual network for the guest */ + struct in_addr vnetwork; + /* Mask for the virtual network for the guest */ + struct in_addr vnetmask; + /* Virtual address for the host exposed to the guest */ + struct in_addr vhost; + /* Whether IPv6 is enabled */ + bool in6_enabled; + /* Virtual IPv6 network for the guest */ + struct in6_addr vprefix_addr6; + /* Len of the virtual IPv6 network for the guest */ + uint8_t vprefix_len; + /* Virtual address for the host exposed to the guest */ + struct in6_addr vhost6; + /* Hostname exposed to the guest in DHCP hostname option */ + const char *vhostname; + /* Hostname exposed to the guest in the DHCP TFTP server name option */ + const char *tftp_server_name; + /* Path of the files served by TFTP */ + const char *tftp_path; + /* Boot file name exposed to the guest via DHCP */ + const char *bootfile; + /* Start of the DHCP range */ + struct in_addr vdhcp_start; + /* Virtual address for the DNS server exposed to the guest */ + struct in_addr vnameserver; + /* Virtual IPv6 address for the DNS server exposed to the guest */ + struct in6_addr vnameserver6; + /* DNS search names exposed to the guest via DHCP */ + const char **vdnssearch; + /* Domain name exposed to the guest via DHCP */ + const char *vdomainname; + /* MTU when sending packets to the guest */ + /* Default: IF_MTU_DEFAULT */ + size_t if_mtu; + /* MRU when receiving packets from the guest */ + /* Default: IF_MRU_DEFAULT */ + size_t if_mru; + /* Prohibit connecting to 127.0.0.1:* */ + bool disable_host_loopback; + /* + * Enable emulation code (*warning*: this code isn't safe, it is not + * recommended to enable it) + */ + bool enable_emu; + + /* + * Fields introduced in SlirpConfig version 2 begin + */ + /* Address to be used when sending data to the Internet */ + struct sockaddr_in *outbound_addr; + /* IPv6 Address to be used when sending data to the Internet */ + struct sockaddr_in6 *outbound_addr6; + + /* + * Fields introduced in SlirpConfig version 3 begin + */ + /* slirp will not redirect/serve any DNS packet */ + bool disable_dns; + + /* + * Fields introduced in SlirpConfig version 4 begin + */ + /* slirp will not reply to any DHCP requests */ + bool disable_dhcp; + + /* + * Fields introduced in SlirpConfig version 5 begin + */ + /* Manufacturer ID (IANA Private Enterprise number) */ + uint32_t mfr_id; + /* + * MAC address allocated for an out-of-band management controller, to be + * retrieved through NC-SI. + */ + uint8_t oob_eth_addr[6]; +} SlirpConfig; -Slirp *slirp_init(int restricted, struct in_addr vnetwork, +/* Create a new instance of a slirp stack */ +Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, + void *opaque); +/* slirp_init is deprecated in favor of slirp_new */ +Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork, struct in_addr vnetmask, struct in_addr vhost, - const char *vhostname, const char *tftp_path, - const char *bootfile, struct in_addr vdhcp_start, - struct in_addr vnameserver, const char **vdnssearch, - void *opaque, void *logfn); + bool in6_enabled, struct in6_addr vprefix_addr6, + uint8_t vprefix_len, struct in6_addr vhost6, + const char *vhostname, const char *tftp_server_name, + const char *tftp_path, const char *bootfile, + struct in_addr vdhcp_start, struct in_addr vnameserver, + struct in6_addr vnameserver6, const char **vdnssearch, + const char *vdomainname, const SlirpCb *callbacks, + void *opaque); +/* Shut down an instance of a slirp stack */ void slirp_cleanup(Slirp *slirp); -void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, - fd_set *xfds, uint32_t *timeout); +/* This is called by the application when it is about to sleep through poll(). + * *timeout is set to the amount of virtual time (in ms) that the application intends to + * wait (UINT32_MAX if infinite). slirp_pollfds_fill updates it according to + * e.g. TCP timers, so the application knows it should sleep a smaller amount of + * time. slirp_pollfds_fill calls add_poll for each file descriptor + * that should be monitored along the sleep. The opaque pointer is passed as + * such to add_poll, and add_poll returns an index. */ +void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout, + SlirpAddPollCb add_poll, void *opaque); -void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, - int select_error); +/* This is called by the application after sleeping, to report which file + * descriptors are available. slirp_pollfds_poll calls get_revents on each file + * descriptor, giving it the index that add_poll returned during the + * slirp_pollfds_fill call, to know whether the descriptor is available for + * read/write/etc. (SLIRP_POLL_*) + * select_error should be passed 1 if poll() returned an error. */ +void slirp_pollfds_poll(Slirp *slirp, int select_error, + SlirpGetREventsCb get_revents, void *opaque); +/* This is called by the application when the guest emits a packet on the + * guest network, to be interpreted by slirp. */ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len); -/* you must provide the following functions: */ -int slirp_can_output(void *opaque); -void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len); +/* This is called by the application when a timer expires, if it provides + * the timer_new_opaque callback. It is not needed if the application only + * uses timer_new. */ +void slirp_handle_timer(Slirp *slirp, SlirpTimerId id, void *cb_opaque); -int slirp_add_hostfwd(Slirp *slirp, int is_udp, - struct in_addr host_addr, int host_port, - struct in_addr guest_addr, int guest_port); -int slirp_remove_hostfwd(Slirp *slirp, int is_udp, - struct in_addr host_addr, int host_port); -int slirp_add_exec(Slirp *slirp, int do_pty, const void *args, +/* These set up / remove port forwarding between a host port in the real world + * and the guest network. + * Note: guest_addr must be in network order, while guest_port must be in host + * order. + */ +int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, + int host_port, struct in_addr guest_addr, int guest_port); +int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, + int host_port); + +#define SLIRP_HOSTFWD_UDP 1 +#define SLIRP_HOSTFWD_V6ONLY 2 +int slirp_add_hostxfwd(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + const struct sockaddr *gaddr, socklen_t gaddrlen, + int flags); +int slirp_remove_hostxfwd(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + int flags); + +/* Set up port forwarding between a port in the guest network and a + * command running on the host */ +int slirp_add_exec(Slirp *slirp, const char *cmdline, + struct in_addr *guest_addr, int guest_port); + +/* Set up port forwarding between a port in the guest network and a + * Unix port on the host */ +int slirp_add_unix(Slirp *slirp, const char *unixsock, struct in_addr *guest_addr, int guest_port); +/* Set up port forwarding between a port in the guest network and a + * callback that will receive the data coming from the port */ +int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque, + struct in_addr *guest_addr, int guest_port); + +/* TODO: rather identify a guestfwd through an opaque pointer instead of through + * the guest_addr */ -void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, - int guest_port, const uint8_t *buf, int size); +/* This is called by the application for a guestfwd, to determine how much data + * can be received by the forwarded port through a call to slirp_socket_recv. */ size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port); +/* This is called by the application for a guestfwd, to provide the data to be + * sent on the forwarded port */ +void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port, + const uint8_t *buf, int size); -#endif +/* Remove entries added by slirp_add_exec, slirp_add_unix or slirp_add_guestfwd */ +int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr, + int guest_port); + +/* Return a human-readable state of the slirp stack */ +char *slirp_connection_info(Slirp *slirp); + +/* Return a human-readable state of the NDP/ARP tables */ +char *slirp_neighbor_info(Slirp *slirp); + +/* Return the version of the slirp implementation */ +const char *slirp_version_string(void); + +/* Addition for Bochs logging */ +void slirp_set_logfn(void *slirp, void *logfn, uint8_t debug_switches); + +#endif /* LIBSLIRP_H */ diff --git a/bochs/iodev/network/slirp/main.h b/bochs/iodev/network/slirp/main.h index 91f92552f2..ca36277e0d 100644 --- a/bochs/iodev/network/slirp/main.h +++ b/bochs/iodev/network/slirp/main.h @@ -1,54 +1,23 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ -#ifndef SLIRP_MAIN_H -#define SLIRP_MAIN_H 1 - -#ifdef HAVE_SYS_SELECT_H -#include -#endif -#define TOWRITEMAX 512 +#ifndef SLIRP_MAIN_H +#define SLIRP_MAIN_H -extern int slirp_socket; -extern int slirp_socket_unit; -extern int slirp_socket_port; -extern uint32_t slirp_socket_addr; -extern char *slirp_socket_passwd; -extern int ctty_closed; +#include "libslirp.h" -/* - * 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; +/* The current guest virtual time */ +extern unsigned curtime; +/* Always equal to INADDR_LOOPBACK, in network order */ extern struct in_addr loopback_addr; +/* Always equal to IN_CLASSA_NET, in network order */ extern unsigned long loopback_mask; -extern char *username; -extern char *socket_path; -extern int towrite_max; -extern int ppp_exit; -extern int tcp_keepintvl; - -#define PROTO_SLIP 0x1 -#ifdef USE_PPP -#define PROTO_PPP 0x2 -#endif +/* Send a packet to the guest */ int if_encap(Slirp *slirp, struct mbuf *ifm); -ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags); +/* Send a frame to the guest. Flags are passed to the send() call */ +slirp_ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags); #endif diff --git a/bochs/iodev/network/slirp/mbuf.cc b/bochs/iodev/network/slirp/mbuf.cc index d5553d1b10..ba96897d96 100644 --- a/bochs/iodev/network/slirp/mbuf.cc +++ b/bochs/iodev/network/slirp/mbuf.cc @@ -1,11 +1,6 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ /* @@ -26,223 +21,275 @@ /* * Find a nice value for msize - * XXX if_maxlinkhdr already in mtu */ -#define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6) +#define SLIRP_MSIZE(mtu) \ + (offsetof(struct mbuf, m_dat) + IF_MAXLINKHDR + TCPIPHDR_DELTA + (mtu)) -void -m_init(Slirp *slirp) +void m_init(Slirp *slirp) { - slirp->m_freelist.m_next = slirp->m_freelist.m_prev = &slirp->m_freelist; - slirp->m_usedlist.m_next = slirp->m_usedlist.m_prev = &slirp->m_usedlist; + slirp->m_freelist.qh_link = slirp->m_freelist.qh_rlink = &slirp->m_freelist; + slirp->m_usedlist.qh_link = slirp->m_usedlist.qh_rlink = &slirp->m_usedlist; } -void m_cleanup(Slirp *slirp) +static void m_cleanup_list(struct slirp_quehead *list_head, bool pkts) { - struct mbuf *m, *next; + struct mbuf *m, *next, *next2; + bool last; - m = slirp->m_usedlist.m_next; - while (m != &slirp->m_usedlist) { - next = m->m_next; - if (m->m_flags & M_EXT) { - free(m->m_ext); - } - free(m); - m = next; - } - m = slirp->m_freelist.m_next; - while (m != &slirp->m_freelist) { + m = (struct mbuf *)list_head->qh_link; + while ((struct slirp_quehead *)m != list_head) { next = m->m_next; - free(m); + + last = false; + while (1) { + next2 = m->m_nextpkt; + + if (pkts) { + ifs_remque(m); + last = next2 == m; + } else { + last = true; + } + + if (m->m_flags & M_EXT) { + free(m->m_ext); + } + + free(m); + + if (last) + break; + m = next2; + }; + m = next; } + list_head->qh_link = list_head; + list_head->qh_rlink = list_head; +} + +void m_cleanup(Slirp *slirp) +{ + m_cleanup_list(&slirp->m_usedlist, false); + m_cleanup_list(&slirp->m_freelist, false); + m_cleanup_list(&slirp->if_batchq, true); + m_cleanup_list(&slirp->if_fastq, true); } /* * Get an mbuf from the free list, if there are none - * malloc one + * allocate 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(Slirp *slirp) +struct mbuf *m_get(Slirp *slirp) { - struct mbuf *m; - int flags = 0; - - DEBUG_CALL("m_get"); - - if (slirp->m_freelist.m_next == &slirp->m_freelist) { - m = (struct mbuf *)malloc(SLIRP_MSIZE); - if (m == NULL) goto end_error; - slirp->mbuf_alloced++; - if (slirp->mbuf_alloced > MBUF_THRESH) - flags = M_DOFREE; - m->slirp = slirp; - } else { - m = slirp->m_freelist.m_next; - remque(m); - } - - /* Insert it in the used list */ - insque(m,&slirp->m_usedlist); - m->m_flags = (flags | M_USEDLIST); - - /* Initialise it */ - m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat); - m->m_data = m->m_dat; - m->m_len = 0; - m->m_nextpkt = NULL; - m->m_prevpkt = NULL; - m->arp_requested = false; - m->expiration_date = (uint64_t)-1; -end_error: - DEBUG_ARG("m = %lx", (long )m); - return m; + struct mbuf *m; + int flags = 0; + + DEBUG_CALL("m_get"); + + if (MBUF_DEBUG || slirp->m_freelist.qh_link == &slirp->m_freelist) { + m = (struct mbuf *)malloc(SLIRP_MSIZE(slirp->if_mtu)); + slirp->mbuf_alloced++; + if (MBUF_DEBUG || slirp->mbuf_alloced > MBUF_THRESH) + flags = M_DOFREE; + m->slirp = slirp; + } else { + m = (struct mbuf *)slirp->m_freelist.qh_link; + slirp_remque(m); + } + + /* Insert it in the used list */ + slirp_insque(m,&slirp->m_usedlist); + m->m_flags = (flags | M_USEDLIST); + + /* Initialise it */ + m->m_size = SLIRP_MSIZE(slirp->if_mtu) - offsetof(struct mbuf, m_dat); + m->m_data = m->m_dat; + m->m_len = 0; + m->m_nextpkt = NULL; + m->m_prevpkt = NULL; + m->resolution_requested = false; + m->expiration_date = (uint64_t)-1; + DEBUG_ARG("m = %p", m); + return m; } -void -m_free(struct mbuf *m) +void m_free(struct mbuf *m) { + DEBUG_CALL("m_free"); + DEBUG_ARG("m = %p", m); + + if (m) { + /* Remove from m_usedlist */ + if (m->m_flags & M_USEDLIST) + slirp_remque(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) { - m->slirp->mbuf_alloced--; - free(m); - } else if ((m->m_flags & M_FREELIST) == 0) { - insque(m,&m->slirp->m_freelist); - m->m_flags = M_FREELIST; /* Clobber other flags */ - } - } /* if(m) */ + /* If it's M_EXT, free() it */ + if (m->m_flags & M_EXT) { + free(m->m_ext); + m->m_flags &= ~M_EXT; + } + /* + * Either free() it or put it on the free list + */ + if (m->m_flags & M_DOFREE) { + m->slirp->mbuf_alloced--; + free(m); + } else if ((m->m_flags & M_FREELIST) == 0) { + slirp_insque(m,&m->slirp->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() + * the other.. if result is too big for one mbuf, allocate * an M_EXT data segment */ -void -m_cat(struct mbuf *m, struct mbuf *n) +void m_cat(struct mbuf *m, struct mbuf *n) { - /* - * If there's no room, realloc - */ - if (M_FREEROOM(m) < n->m_len) - m_inc(m, m->m_len + n->m_len); + /* + * If there's no room, realloc + */ + if (M_FREEROOM(m) < n->m_len) + m_inc(m, m->m_len + n->m_len); - memcpy(m->m_data+m->m_len, n->m_data, n->m_len); - m->m_len += n->m_len; + memcpy(m->m_data+m->m_len, n->m_data, n->m_len); + m->m_len += n->m_len; - m_free(n); + m_free(n); } -/* make m size bytes large */ -void -m_inc(struct mbuf *m, int size) +/* make m 'size' bytes large from m_data */ +void m_inc(struct mbuf *m, int size) { - int datasize; - - /* some compiles throw up on gotos. This one we can fake. */ - if(m->m_size>size) return; + int gapsize; - if (m->m_flags & M_EXT) { - datasize = m->m_data - m->m_ext; - m->m_ext = (char *)realloc(m->m_ext, size + datasize); - m->m_data = m->m_ext + datasize; - } else { - char *dat; - datasize = m->m_data - m->m_dat; - dat = (char *)malloc(size + datasize); - memcpy(dat, m->m_dat, m->m_size); - - m->m_ext = dat; - m->m_data = m->m_ext + datasize; - m->m_flags |= M_EXT; - } + /* some compilers throw up on gotos. This one we can fake. */ + if (M_ROOM(m) >= size) { + return; + } - m->m_size = size + datasize; + if (m->m_flags & M_EXT) { + gapsize = m->m_data - m->m_ext; + m->m_ext = (char*)realloc(m->m_ext, size + gapsize); + } else { + gapsize = m->m_data - m->m_dat; + m->m_ext = (char*)malloc(size + gapsize); + memcpy(m->m_ext, m->m_dat, m->m_size); + m->m_flags |= M_EXT; + } + m->m_data = m->m_ext + gapsize; + m->m_size = size + gapsize; } - -void -m_adj(struct mbuf *m, int len) +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; - } + 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, int off, int len) +int m_copy(struct mbuf *n, struct mbuf *m, int off, int len) { - if (len > M_FREEROOM(n)) - return -1; + 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; + 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(Slirp *slirp, void *dat) +struct mbuf *dtom(Slirp *slirp, void *dat) +{ + struct mbuf *m; + + DEBUG_CALL("dtom"); + DEBUG_ARG("dat = %p", dat); + + /* bug corrected for M_EXT buffers */ + for (m = (struct mbuf *)slirp->m_usedlist.qh_link; + (struct slirp_quehead *)m != &slirp->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("dtom failed"); + + return (struct mbuf *)0; +} + +struct mbuf *m_dup(Slirp *slirp, struct mbuf *m, + bool copy_header, + size_t header_size) +{ + struct mbuf *n; + int mcopy_result; + + /* The previous mbuf was supposed to have it already, we can check it along + * the way */ + assert(M_ROOMBEFORE(m) >= (int)header_size); + + n = m_get(slirp); + m_inc(n, m->m_len + header_size); + + if (copy_header) { + m->m_len += header_size; + m->m_data -= header_size; + mcopy_result = m_copy(n, m, 0, m->m_len); + n->m_data += header_size; + n->m_len -= header_size; + m->m_len -= header_size; + m->m_data += header_size; + } else { + n->m_data += header_size; + mcopy_result = m_copy(n, m, 0, m->m_len); + } + assert(mcopy_result == 0); + + return n; +} + +void *mtod_check(struct mbuf *m, size_t len) +{ + if (m->m_len >= (int)len) { + return m->m_data; + } + + DEBUG_ERROR("mtod failed"); + + return NULL; +} + +void *m_end(struct mbuf *m) { - struct mbuf *m; - - DEBUG_CALL("dtom"); - DEBUG_ARG("dat = %lx", (long )dat); - - /* bug corrected for M_EXT buffers */ - for (m = slirp->m_usedlist.m_next; m != &slirp->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; + return m->m_data + m->m_len; } #endif diff --git a/bochs/iodev/network/slirp/mbuf.h b/bochs/iodev/network/slirp/mbuf.h index 921cfaaa79..0533402464 100644 --- a/bochs/iodev/network/slirp/mbuf.h +++ b/bochs/iodev/network/slirp/mbuf.h @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,20 +27,18 @@ * 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 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 MINCSIZE 4096 /* Amount to increase mbuf if too small */ +#ifndef MBUF_H +#define MBUF_H /* * Macros for type conversion - * mtod(m,t) - convert mbuf pointer to data pointer of correct type + * mtod(m,t) - convert mbuf pointer to data pointer of correct type */ -#define mtod(m,t) ((t)(m)->m_data) +#define mtod(m,t) ((t)(m)->m_data) /* XXX About mbufs for slirp: * Only one mbuf is ever used in a chain, for each "cell" of data. @@ -52,70 +48,178 @@ * free the m_ext. This is inefficient memory-wise, but who cares. */ +/* + * mbufs allow to have a gap between the start of the allocated buffer (m_ext if + * M_EXT is set, m_dat otherwise) and the in-use data: + * + * |--gapsize----->|---m_len-------> + * |----------m_size------------------------------> + * |----M_ROOM--------------------> + * |-M_FREEROOM--> + * + * ^ ^ ^ + * m_dat/m_ext m_data end of buffer + */ + /* * 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)) +#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 + +/* + * How much free room there is before m_data + */ +#define M_ROOMBEFORE(m) \ + (((m)->m_flags & M_EXT) ? (m)->m_data - (m)->m_ext \ + : (m)->m_data - (m)->m_dat) struct mbuf { - /* XXX should union some of these! */ - /* header at beginning of each mbuf: */ - struct mbuf *m_next; /* Linked list of mbufs */ - struct mbuf *m_prev; - struct mbuf *m_nextpkt; /* Next packet in queue/record */ - struct mbuf *m_prevpkt; /* Flags aren't used in the output queue */ - int m_flags; /* Misc flags */ - - int m_size; /* Size of data */ - struct socket *m_so; - - caddr_t m_data; /* Location of data */ - int m_len; /* Amount of data in this mbuf */ - - Slirp *slirp; - bool arp_requested; - uint64_t expiration_date; - /* start of dynamic buffer area, must be last element */ - union { - char m_dat[1]; /* ANSI don't like 0 sized arrays */ - char *m_ext; - }; + /* XXX should union some of these! */ + /* header at beginning of each mbuf: */ + struct mbuf *m_next; /* Linked list of mbufs */ + struct mbuf *m_prev; + struct mbuf *m_nextpkt; /* Next packet in queue/record */ + struct mbuf *m_prevpkt; /* Flags aren't used in the output queue */ + int m_flags; /* Misc flags */ + + int m_size; /* Size of mbuf, from m_dat or m_ext */ + struct socket *m_so; + + char *m_data; /* Current location of data */ + int m_len; /* Amount of data in this mbuf, from m_data */ + + Slirp *slirp; + bool resolution_requested; + uint64_t expiration_date; + char *m_ext; + /* start of dynamic buffer area, must be last element */ + char m_dat[]; }; -#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 +static inline void ifs_remque(struct mbuf *ifm) +{ + ifm->m_prevpkt->m_nextpkt = ifm->m_nextpkt; + ifm->m_nextpkt->m_prevpkt = ifm->m_prevpkt; +} -#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 */ +#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 */ +/* Called by slirp_new */ void m_init(Slirp *); + +/* Called by slirp_cleanup */ void m_cleanup(Slirp *slirp); -struct mbuf * m_get(Slirp *); + +/* Allocate an mbuf */ +struct mbuf *m_get(Slirp *); + +/* Release an mbuf (put possibly put it in allocation cache */ void m_free(struct mbuf *); + +/* Catenate the second buffer to the end of the first buffer, and release the second */ void m_cat(struct mbuf *, struct mbuf *); + +/* Grow the mbuf to the given size */ void m_inc(struct mbuf *, int); -void m_adj(struct mbuf *, int); -int m_copy(struct mbuf *, struct mbuf *, int, int); + +/* If len is positive, trim that amount from the head of the mbuf. If it is negative, trim it from the tail of the mbuf */ +void m_adj(struct mbuf *, int len); + +/* Copy len bytes from the first buffer at the given offset, to the end of the second buffer */ +int m_copy(struct mbuf *, struct mbuf *, int off, int len); + +/* + * Duplicate the mbuf + * + * copy_header specifies whether the bytes before m_data should also be copied. + * header_size specifies how many bytes are to be reserved before m_data. + */ +struct mbuf *m_dup(Slirp *slirp, struct mbuf *m, bool copy_header, size_t header_size); + +/* + * 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(Slirp *, void *); +/* Check that the mbuf contains at least len bytes, and return the data */ +void *mtod_check(struct mbuf *, size_t len); + +/* Return the end of the data of the mbuf */ +void *m_end(struct mbuf *); + +/* Initialize the ifs queue of the mbuf */ static inline void ifs_init(struct mbuf *ifm) { - ifm->ifs_next = ifm->ifs_prev = ifm; + ifm->m_nextpkt = ifm->m_prevpkt = ifm; } +#ifdef SLIRP_DEBUG +# define MBUF_DEBUG 1 +#else +# ifdef HAVE_VALGRIND +# include +# define MBUF_DEBUG RUNNING_ON_VALGRIND +# else +# define MBUF_DEBUG 0 +# endif +#endif + +/* + * When a function is given an mbuf as well as the responsibility to free it, we + * want valgrind etc. to properly identify the new responsible for the + * free. Achieve this by making a new copy. For instance: + * + * f0(void) { + * struct mbuf *m = m_get(slirp); + * [...] + * switch (something) { + * case 1: + * f1(m); + * break; + * case 2: + * f2(m); + * break; + * [...] + * } + * } + * + * f1(struct mbuf *m) { + * M_DUP_DEBUG(m->slirp, m); + * [...] + * m_free(m); // but author of f1 might be forgetting this + * } + * + * f0 transfers the freeing responsibility to f1, f2, etc. Without the + * M_DUP_DEBUG call in f1, valgrind would tell us that it is f0 where the buffer + * was allocated, but it's difficult to know whether a leak is actually in f0, + * or in f1, or in f2, etc. Duplicating the mbuf in M_DUP_DEBUG each time the + * responsibility is transferred allows to immediately know where the leak + * actually is. + */ +#define M_DUP_DEBUG(slirp, m, copy_header, header_size) do { \ + if (MBUF_DEBUG) { \ + struct mbuf *__n; \ + __n = m_dup((slirp), (m), (copy_header), (header_size)); \ + m_free(m); \ + (m) = __n; \ + } else { \ + (void) (slirp); (void) (copy_header); \ + assert(M_ROOMBEFORE(m) >= (header_size)); \ + } \ +} while(0) + #endif diff --git a/bochs/iodev/network/slirp/misc.cc b/bochs/iodev/network/slirp/misc.cc index 4dd6f15121..9608f529cc 100644 --- a/bochs/iodev/network/slirp/misc.cc +++ b/bochs/iodev/network/slirp/misc.cc @@ -1,269 +1,126 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ #include "slirp.h" -#include "libslirp.h" - -#ifndef _WIN32 -#include -#endif - #if BX_NETWORKING && BX_NETMOD_SLIRP -#ifdef DEBUG -int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR; +#ifndef _WIN32 +#include #endif -struct quehead { - struct quehead *qh_link; - struct quehead *qh_rlink; -}; - -void insque(void *a, void *b) +void slirp_insque(void *a, void *b) { - struct quehead *element = (struct quehead *) a; - 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; + struct slirp_quehead *element = (struct slirp_quehead *) a; + struct slirp_quehead *head = (struct slirp_quehead *) b; + element->qh_link = head->qh_link; + head->qh_link = (struct slirp_quehead *)element; + element->qh_rlink = (struct slirp_quehead *)head; + ((struct slirp_quehead *)(element->qh_link))->qh_rlink = + (struct slirp_quehead *)element; } -void remque(void *a) +void slirp_remque(void *a) { - 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; + struct slirp_quehead *element = (struct slirp_quehead *) a; + ((struct slirp_quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; + ((struct slirp_quehead *)(element->qh_rlink))->qh_link = element->qh_link; + element->qh_rlink = NULL; } -int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, - struct in_addr addr, int port) +/* TODO: IPv6 */ +struct gfwd_list *add_guestfwd(struct gfwd_list **ex_ptr, SlirpWriteCb write_cb, + void *opaque, struct in_addr addr, int port) { - struct ex_list *tmp_ptr; + struct gfwd_list *f = (struct gfwd_list *)malloc(sizeof(struct gfwd_list)); - /* 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.s_addr == tmp_ptr->ex_addr.s_addr) - return -1; - } + f->write_cb = write_cb; + f->opaque = opaque; + f->ex_fport = port; + f->ex_addr = addr; + f->ex_next = *ex_ptr; + *ex_ptr = f; - 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 = (do_pty == 3) ? exec : strdup(exec); - (*ex_ptr)->ex_next = tmp_ptr; - return 0; + return f; } -#ifndef HAVE_STRERROR +struct gfwd_list *add_exec(struct gfwd_list **ex_ptr, const char *cmdline, + struct in_addr addr, int port) +{ + struct gfwd_list *f = add_guestfwd(ex_ptr, NULL, NULL, addr, port); -/* - * For systems with no strerror - */ + f->ex_exec = strdup(cmdline); -extern int sys_nerr; -extern char *sys_errlist[]; + return f; +} -char * -strerror(error) - int error; +struct gfwd_list *add_unix(struct gfwd_list **ex_ptr, const char *unixsock, + struct in_addr addr, int port) { - if (error < sys_nerr) - return sys_errlist[error]; - else - return "Unknown error."; -} + struct gfwd_list *f = add_guestfwd(ex_ptr, NULL, NULL, addr, port); -#endif + f->ex_unix = strdup(unixsock); + return f; +} -#ifdef _WIN32 +int remove_guestfwd(struct gfwd_list **ex_ptr, struct in_addr addr, int port) +{ + for (; *ex_ptr != NULL; ex_ptr = &((*ex_ptr)->ex_next)) { + struct gfwd_list *f = *ex_ptr; + if (f->ex_addr.s_addr == addr.s_addr && f->ex_fport == port) { + *ex_ptr = f->ex_next; + free(f->ex_exec); + free(f); + return 0; + } + } + return -1; +} -int -fork_exec(struct socket *so, const char *ex, int do_pty) +int fork_exec(struct socket *so, const char *ex) { /* not implemented */ return 0; } -#else - -/* - * 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, const char *ex, int do_pty) +int open_unix(struct socket *so, const char *unixpath) { - int s; - struct sockaddr_in addr; - socklen_t addrlen = sizeof(addr); - int opt; - const char *argv[256]; - /* don't want to clobber the original */ - char *bptr; - const char *curarg; - int c, i, ret; - pid_t pid; - - 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) { - return 0; - } else { - addr.sin_family = AF_INET; - addr.sin_port = 0; - addr.sin_addr.s_addr = INADDR_ANY; - - if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 || - bind(s, (struct sockaddr *)&addr, addrlen) < 0 || - listen(s, 1) < 0) { -#ifdef DEBUG - printf("Error: inet socket: %s\n", strerror(errno)); -#endif - closesocket(s); - - return 0; - } - } - - pid = fork(); - switch(pid) { - case -1: -#ifdef DEBUG - printf("Error: fork failed: %s\n", strerror(errno)); -#endif - close(s); - return 0; - - case 0: - setsid(); - - /* Set the DISPLAY */ - getsockname(s, (struct sockaddr *)&addr, &addrlen); - close(s); - /* - * Connect to the socket - * XXX If any of these fail, we're in trouble! - */ - s = qemu_socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr = loopback_addr; - do { - ret = connect(s, (struct sockaddr *)&addr, addrlen); - } while (ret < 0 && errno == EINTR); - - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); -#ifdef ANDROID - { - /* No getdtablesize() on Android, we will use /proc/XXX/fd/ Linux virtual FS instead */ - char proc_fd_path[256]; - sprintf(proc_fd_path, "/proc/%u/fd", (unsigned)getpid()); - DIR *proc_dir = opendir(proc_fd_path); - if (proc_dir) { - for (struct dirent *fd = readdir(proc_dir); fd != NULL; fd = readdir(proc_dir)) { - if (atoi(fd->d_name) >= 3 && fd->d_name[0] != '.') /* ".." and "." will return 0 anyway */ - close(atoi(fd->d_name)); - } - closedir(proc_dir); - } - } -#else - for (s = getdtablesize() - 1; s >= 3; s--) - close(s); -#endif - - 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] = NULL; - execvp(argv[0], (char **)argv); - - /* Ooops, failed, let's tell the user why */ - fprintf(stderr, "Error: execvp of %s failed: %s\n", - argv[0], strerror(errno)); - close(0); close(1); close(2); /* XXX */ - exit(1); - - default: - slirp_warning(so->slirp, "qemu_add_child_watch(pid) not implemented"); - /* - * 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); - socket_set_fast_reuse(so->s); - opt = 1; - qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); - qemu_set_nonblock(so->s); - - /* Append the telnet options now */ - if (so->so_m != NULL && do_pty == 1) { - sbappend(so, so->so_m); - so->so_m = NULL; - } - - return 1; - } + /* not implemented */ + return 0; } -#endif -#ifndef HAVE_STRDUP -char * -strdup(str) - const char *str; +char *slirp_connection_info(Slirp *slirp) { - char *bptr; + /* not implemented */ + return NULL; +} - bptr = (char *)malloc(strlen(str)+1); - strcpy(bptr, str); +char *slirp_neighbor_info(Slirp *slirp) +{ + /* not implemented */ + return NULL; +} - return bptr; +int slirp_bind_outbound(struct socket *so, unsigned short af) +{ + int ret = 0; + struct sockaddr *addr = NULL; + int addr_size = 0; + + if (af == AF_INET && so->slirp->outbound_addr != NULL) { + addr = (struct sockaddr *)so->slirp->outbound_addr; + addr_size = sizeof(struct sockaddr_in); + } else if (af == AF_INET6 && so->slirp->outbound_addr6 != NULL) { + addr = (struct sockaddr *)so->slirp->outbound_addr6; + addr_size = sizeof(struct sockaddr_in6); + } + + if (addr != NULL) { + ret = bind(so->s, addr, addr_size); + } + return ret; } -#endif #endif diff --git a/bochs/iodev/network/slirp/misc.h b/bochs/iodev/network/slirp/misc.h index cd9bd54d44..058ff5f426 100644 --- a/bochs/iodev/network/slirp/misc.h +++ b/bochs/iodev/network/slirp/misc.h @@ -1,27 +1,22 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ -#ifndef _MISC_H_ -#define _MISC_H_ +#ifndef MISC_H +#define MISC_H -struct ex_list { - int ex_pty; /* Do we want a pty? */ - struct in_addr ex_addr; /* Server address */ - int ex_fport; /* Port to telnet to */ - const char *ex_exec; /* Command line of what to exec */ - struct ex_list *ex_next; -}; +#include "libslirp.h" -#ifndef HAVE_STRDUP -char *strdup(const char *); -#endif +struct gfwd_list { + SlirpWriteCb write_cb; + void *opaque; + struct in_addr ex_addr; /* Server address */ + int ex_fport; /* Port to telnet to */ + char *ex_exec; /* Command line of what to exec */ + char *ex_unix; /* unix socket */ + struct gfwd_list *ex_next; +}; #define EMU_NONE 0x0 @@ -33,9 +28,8 @@ char *strdup(const char *); #define EMU_REALAUDIO 0x5 #define EMU_RLOGIN 0x6 #define EMU_IDENT 0x7 -#define EMU_RSH 0x8 -#define EMU_NOCONNECT 0x10 /* Don't connect */ +#define EMU_NOCONNECT 0x10 /* Don't connect */ struct tos_t { uint16_t lport; @@ -52,9 +46,42 @@ struct emu_t { struct emu_t *next; }; -void slirp_insque(void *, void *); -void slirp_remque(void *); -int add_exec(struct ex_list **, int, char *, struct in_addr, int); -int fork_exec(struct socket *so, const char *ex, int do_pty); +struct slirp_quehead { + struct slirp_quehead *qh_link; + struct slirp_quehead *qh_rlink; +}; + +/* Insert element a into queue b */ +void slirp_insque(void *a, void *b); + +/* Remove element a from its queue */ +void slirp_remque(void *a); + +/* Run the given command in the background, and expose its output as a socket */ +int fork_exec(struct socket *so, const char *ex); + +/* Create a Unix socket, and expose it as a socket */ +int open_unix(struct socket *so, const char *unixsock); + +/* Add a guest forward on the given address and port, with guest data being + * forwarded by calling write_cb */ +struct gfwd_list *add_guestfwd(struct gfwd_list **ex_ptr, SlirpWriteCb write_cb, + void *opaque, struct in_addr addr, int port); + +/* Run the given command in the backaground, and send its output to the guest on + * the given address and port */ +struct gfwd_list *add_exec(struct gfwd_list **ex_ptr, const char *cmdline, + struct in_addr addr, int port); + +/* Create a Unix socket, and expose it to the guest on the given address and + * port */ +struct gfwd_list *add_unix(struct gfwd_list **ex_ptr, const char *unixsock, + struct in_addr addr, int port); + +/* Remove the guest forward bound to the given address and port */ +int remove_guestfwd(struct gfwd_list **ex_ptr, struct in_addr addr, int port); + +/* Bind the socket to the outbound address specified in the slirp configuration */ +int slirp_bind_outbound(struct socket *so, unsigned short af); #endif diff --git a/bochs/iodev/network/slirp/ncsi-pkt.h b/bochs/iodev/network/slirp/ncsi-pkt.h new file mode 100644 index 0000000000..27bedf6a9b --- /dev/null +++ b/bochs/iodev/network/slirp/ncsi-pkt.h @@ -0,0 +1,527 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright Gavin Shan, IBM Corporation 2016. + * + * 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 copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NCSI_PKT_H +#define NCSI_PKT_H + +/* from linux/net/ncsi/ncsi-pkt.h */ +#define __be32 uint32_t +#define __be16 uint16_t + +SLIRP_PACKED_BEGIN +struct ncsi_pkt_hdr { + unsigned char mc_id; /* Management controller ID */ + unsigned char revision; /* NCSI version - 0x01 */ + unsigned char reserved; /* Reserved */ + unsigned char id; /* Packet sequence number */ + unsigned char type; /* Packet type */ + unsigned char channel; /* Network controller ID */ + __be16 length; /* Payload length */ + __be32 reserved1[2]; /* Reserved */ +} SLIRP_PACKED_END; + +SLIRP_PACKED_BEGIN +struct ncsi_cmd_pkt_hdr { + struct ncsi_pkt_hdr common; /* Common NCSI packet header */ +} SLIRP_PACKED_END; + +SLIRP_PACKED_BEGIN +struct ncsi_rsp_pkt_hdr { + struct ncsi_pkt_hdr common; /* Common NCSI packet header */ + __be16 code; /* Response code */ + __be16 reason; /* Response reason */ +} SLIRP_PACKED_END; + +SLIRP_PACKED_BEGIN +struct ncsi_aen_pkt_hdr { + struct ncsi_pkt_hdr common; /* Common NCSI packet header */ + unsigned char reserved2[3]; /* Reserved */ + unsigned char type; /* AEN packet type */ +} SLIRP_PACKED_END; + +/* NCSI common command packet */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + __be32 checksum; /* Checksum */ + unsigned char pad[26]; +} SLIRP_PACKED_END; + +SLIRP_PACKED_BEGIN +struct ncsi_rsp_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Response header */ + __be32 checksum; /* Checksum */ + unsigned char pad[22]; +} SLIRP_PACKED_END; + +/* Select Package */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_sp_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + unsigned char reserved[3]; /* Reserved */ + unsigned char hw_arbitration; /* HW arbitration */ + __be32 checksum; /* Checksum */ + unsigned char pad[22]; +} SLIRP_PACKED_END; + +/* Disable Channel */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_dc_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + unsigned char reserved[3]; /* Reserved */ + unsigned char ald; /* Allow link down */ + __be32 checksum; /* Checksum */ + unsigned char pad[22]; +} SLIRP_PACKED_END; + +/* Reset Channel */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_rc_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + __be32 reserved; /* Reserved */ + __be32 checksum; /* Checksum */ + unsigned char pad[22]; +} SLIRP_PACKED_END; + +/* AEN Enable */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_ae_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + unsigned char reserved[3]; /* Reserved */ + unsigned char mc_id; /* MC ID */ + __be32 mode; /* AEN working mode */ + __be32 checksum; /* Checksum */ + unsigned char pad[18]; +} SLIRP_PACKED_END; + +/* Set Link */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_sl_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + __be32 mode; /* Link working mode */ + __be32 oem_mode; /* OEM link mode */ + __be32 checksum; /* Checksum */ + unsigned char pad[18]; +} SLIRP_PACKED_END; + +/* Set VLAN Filter */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_svf_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + __be16 reserved; /* Reserved */ + __be16 vlan; /* VLAN ID */ + __be16 reserved1; /* Reserved */ + unsigned char index; /* VLAN table index */ + unsigned char enable; /* Enable or disable */ + __be32 checksum; /* Checksum */ + unsigned char pad[14]; +} SLIRP_PACKED_END; + +/* Enable VLAN */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_ev_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + unsigned char reserved[3]; /* Reserved */ + unsigned char mode; /* VLAN filter mode */ + __be32 checksum; /* Checksum */ + unsigned char pad[22]; +} SLIRP_PACKED_END; + +/* Set MAC Address */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_sma_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + unsigned char mac[6]; /* MAC address */ + unsigned char index; /* MAC table index */ + unsigned char at_e; /* Addr type and operation */ + __be32 checksum; /* Checksum */ + unsigned char pad[18]; +} SLIRP_PACKED_END; + +/* Enable Broadcast Filter */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_ebf_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + __be32 mode; /* Filter mode */ + __be32 checksum; /* Checksum */ + unsigned char pad[22]; +} SLIRP_PACKED_END; + +/* Enable Global Multicast Filter */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_egmf_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + __be32 mode; /* Global MC mode */ + __be32 checksum; /* Checksum */ + unsigned char pad[22]; +} SLIRP_PACKED_END; + +/* Set NCSI Flow Control */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_snfc_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + unsigned char reserved[3]; /* Reserved */ + unsigned char mode; /* Flow control mode */ + __be32 checksum; /* Checksum */ + unsigned char pad[22]; +} SLIRP_PACKED_END; + +/* OEM Request Command as per NCSI Specification */ +SLIRP_PACKED_BEGIN +struct ncsi_cmd_oem_pkt { + struct ncsi_cmd_pkt_hdr cmd; /* Command header */ + __be32 mfr_id; /* Manufacture ID */ + unsigned char data[]; /* OEM Payload Data */ +} SLIRP_PACKED_END; + +/* OEM Response Packet as per NCSI Specification */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_oem_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Command header */ + __be32 mfr_id; /* Manufacture ID */ + unsigned char data[]; /* Payload data */ +} SLIRP_PACKED_END; + +/* Mellanox Response Data */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_oem_mlx_pkt { + unsigned char cmd_rev; /* Command Revision */ + unsigned char cmd; /* Command ID */ + unsigned char param; /* Parameter */ + unsigned char optional; /* Optional data */ + unsigned char data[]; /* Data */ +} SLIRP_PACKED_END; + +/* Get Link Status */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_gls_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Response header */ + __be32 status; /* Link status */ + __be32 other; /* Other indications */ + __be32 oem_status; /* OEM link status */ + __be32 checksum; + unsigned char pad[10]; +} SLIRP_PACKED_END; + +/* Get Version ID */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_gvi_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Response header */ + __be32 ncsi_version; /* NCSI version */ + unsigned char reserved[3]; /* Reserved */ + unsigned char alpha2; /* NCSI version */ + unsigned char fw_name[12]; /* f/w name string */ + __be32 fw_version; /* f/w version */ + __be16 pci_ids[4]; /* PCI IDs */ + __be32 mf_id; /* Manufacture ID */ + __be32 checksum; +} SLIRP_PACKED_END; + +/* Get Capabilities */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_gc_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Response header */ + __be32 cap; /* Capabilities */ + __be32 bc_cap; /* Broadcast cap */ + __be32 mc_cap; /* Multicast cap */ + __be32 buf_cap; /* Buffering cap */ + __be32 aen_cap; /* AEN cap */ + unsigned char vlan_cnt; /* VLAN filter count */ + unsigned char mixed_cnt; /* Mix filter count */ + unsigned char mc_cnt; /* MC filter count */ + unsigned char uc_cnt; /* UC filter count */ + unsigned char reserved[2]; /* Reserved */ + unsigned char vlan_mode; /* VLAN mode */ + unsigned char channel_cnt; /* Channel count */ + __be32 checksum; /* Checksum */ +} SLIRP_PACKED_END; + +/* Get Parameters */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_gp_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Response header */ + unsigned char mac_cnt; /* Number of MAC addr */ + unsigned char reserved[2]; /* Reserved */ + unsigned char mac_enable; /* MAC addr enable flags */ + unsigned char vlan_cnt; /* VLAN tag count */ + unsigned char reserved1; /* Reserved */ + __be16 vlan_enable; /* VLAN tag enable flags */ + __be32 link_mode; /* Link setting */ + __be32 bc_mode; /* BC filter mode */ + __be32 valid_modes; /* Valid mode parameters */ + unsigned char vlan_mode; /* VLAN mode */ + unsigned char fc_mode; /* Flow control mode */ + unsigned char reserved2[2]; /* Reserved */ + __be32 aen_mode; /* AEN mode */ + unsigned char mac[6]; /* Supported MAC addr */ + __be16 vlan; /* Supported VLAN tags */ + __be32 checksum; /* Checksum */ +} SLIRP_PACKED_END; + +/* Get Controller Packet Statistics */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_gcps_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Response header */ + __be32 cnt_hi; /* Counter cleared */ + __be32 cnt_lo; /* Counter cleared */ + __be32 rx_bytes; /* Rx bytes */ + __be32 tx_bytes; /* Tx bytes */ + __be32 rx_uc_pkts; /* Rx UC packets */ + __be32 rx_mc_pkts; /* Rx MC packets */ + __be32 rx_bc_pkts; /* Rx BC packets */ + __be32 tx_uc_pkts; /* Tx UC packets */ + __be32 tx_mc_pkts; /* Tx MC packets */ + __be32 tx_bc_pkts; /* Tx BC packets */ + __be32 fcs_err; /* FCS errors */ + __be32 align_err; /* Alignment errors */ + __be32 false_carrier; /* False carrier detection */ + __be32 runt_pkts; /* Rx runt packets */ + __be32 jabber_pkts; /* Rx jabber packets */ + __be32 rx_pause_xon; /* Rx pause XON frames */ + __be32 rx_pause_xoff; /* Rx XOFF frames */ + __be32 tx_pause_xon; /* Tx XON frames */ + __be32 tx_pause_xoff; /* Tx XOFF frames */ + __be32 tx_s_collision; /* Single collision frames */ + __be32 tx_m_collision; /* Multiple collision frames */ + __be32 l_collision; /* Late collision frames */ + __be32 e_collision; /* Excessive collision frames */ + __be32 rx_ctl_frames; /* Rx control frames */ + __be32 rx_64_frames; /* Rx 64-bytes frames */ + __be32 rx_127_frames; /* Rx 65-127 bytes frames */ + __be32 rx_255_frames; /* Rx 128-255 bytes frames */ + __be32 rx_511_frames; /* Rx 256-511 bytes frames */ + __be32 rx_1023_frames; /* Rx 512-1023 bytes frames */ + __be32 rx_1522_frames; /* Rx 1024-1522 bytes frames */ + __be32 rx_9022_frames; /* Rx 1523-9022 bytes frames */ + __be32 tx_64_frames; /* Tx 64-bytes frames */ + __be32 tx_127_frames; /* Tx 65-127 bytes frames */ + __be32 tx_255_frames; /* Tx 128-255 bytes frames */ + __be32 tx_511_frames; /* Tx 256-511 bytes frames */ + __be32 tx_1023_frames; /* Tx 512-1023 bytes frames */ + __be32 tx_1522_frames; /* Tx 1024-1522 bytes frames */ + __be32 tx_9022_frames; /* Tx 1523-9022 bytes frames */ + __be32 rx_valid_bytes; /* Rx valid bytes */ + __be32 rx_runt_pkts; /* Rx error runt packets */ + __be32 rx_jabber_pkts; /* Rx error jabber packets */ + __be32 checksum; /* Checksum */ +} SLIRP_PACKED_END; + +/* Get NCSI Statistics */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_gns_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Response header */ + __be32 rx_cmds; /* Rx NCSI commands */ + __be32 dropped_cmds; /* Dropped commands */ + __be32 cmd_type_errs; /* Command type errors */ + __be32 cmd_csum_errs; /* Command checksum errors */ + __be32 rx_pkts; /* Rx NCSI packets */ + __be32 tx_pkts; /* Tx NCSI packets */ + __be32 tx_aen_pkts; /* Tx AEN packets */ + __be32 checksum; /* Checksum */ +} SLIRP_PACKED_END; + +/* Get NCSI Pass-through Statistics */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_gnpts_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Response header */ + __be32 tx_pkts; /* Tx packets */ + __be32 tx_dropped; /* Tx dropped packets */ + __be32 tx_channel_err; /* Tx channel errors */ + __be32 tx_us_err; /* Tx undersize errors */ + __be32 rx_pkts; /* Rx packets */ + __be32 rx_dropped; /* Rx dropped packets */ + __be32 rx_channel_err; /* Rx channel errors */ + __be32 rx_us_err; /* Rx undersize errors */ + __be32 rx_os_err; /* Rx oversize errors */ + __be32 checksum; /* Checksum */ +} SLIRP_PACKED_END; + +/* Get package status */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_gps_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Response header */ + __be32 status; /* Hardware arbitration status */ + __be32 checksum; +} SLIRP_PACKED_END; + +/* Get package UUID */ +SLIRP_PACKED_BEGIN +struct ncsi_rsp_gpuuid_pkt { + struct ncsi_rsp_pkt_hdr rsp; /* Response header */ + unsigned char uuid[16]; /* UUID */ + __be32 checksum; +} SLIRP_PACKED_END; + +/* AEN: Link State Change */ +SLIRP_PACKED_BEGIN +struct ncsi_aen_lsc_pkt { + struct ncsi_aen_pkt_hdr aen; /* AEN header */ + __be32 status; /* Link status */ + __be32 oem_status; /* OEM link status */ + __be32 checksum; /* Checksum */ + unsigned char pad[14]; +} SLIRP_PACKED_END; + +/* AEN: Configuration Required */ +SLIRP_PACKED_BEGIN +struct ncsi_aen_cr_pkt { + struct ncsi_aen_pkt_hdr aen; /* AEN header */ + __be32 checksum; /* Checksum */ + unsigned char pad[22]; +} SLIRP_PACKED_END; + +/* AEN: Host Network Controller Driver Status Change */ +SLIRP_PACKED_BEGIN +struct ncsi_aen_hncdsc_pkt { + struct ncsi_aen_pkt_hdr aen; /* AEN header */ + __be32 status; /* Status */ + __be32 checksum; /* Checksum */ + unsigned char pad[18]; +} SLIRP_PACKED_END; + +/* NCSI packet revision */ +#define NCSI_PKT_REVISION 0x01 + +/* NCSI packet commands */ +#define NCSI_PKT_CMD_CIS 0x00 /* Clear Initial State */ +#define NCSI_PKT_CMD_SP 0x01 /* Select Package */ +#define NCSI_PKT_CMD_DP 0x02 /* Deselect Package */ +#define NCSI_PKT_CMD_EC 0x03 /* Enable Channel */ +#define NCSI_PKT_CMD_DC 0x04 /* Disable Channel */ +#define NCSI_PKT_CMD_RC 0x05 /* Reset Channel */ +#define NCSI_PKT_CMD_ECNT 0x06 /* Enable Channel Network Tx */ +#define NCSI_PKT_CMD_DCNT 0x07 /* Disable Channel Network Tx */ +#define NCSI_PKT_CMD_AE 0x08 /* AEN Enable */ +#define NCSI_PKT_CMD_SL 0x09 /* Set Link */ +#define NCSI_PKT_CMD_GLS 0x0a /* Get Link */ +#define NCSI_PKT_CMD_SVF 0x0b /* Set VLAN Filter */ +#define NCSI_PKT_CMD_EV 0x0c /* Enable VLAN */ +#define NCSI_PKT_CMD_DV 0x0d /* Disable VLAN */ +#define NCSI_PKT_CMD_SMA 0x0e /* Set MAC address */ +#define NCSI_PKT_CMD_EBF 0x10 /* Enable Broadcast Filter */ +#define NCSI_PKT_CMD_DBF 0x11 /* Disable Broadcast Filter */ +#define NCSI_PKT_CMD_EGMF 0x12 /* Enable Global Multicast Filter */ +#define NCSI_PKT_CMD_DGMF 0x13 /* Disable Global Multicast Filter */ +#define NCSI_PKT_CMD_SNFC 0x14 /* Set NCSI Flow Control */ +#define NCSI_PKT_CMD_GVI 0x15 /* Get Version ID */ +#define NCSI_PKT_CMD_GC 0x16 /* Get Capabilities */ +#define NCSI_PKT_CMD_GP 0x17 /* Get Parameters */ +#define NCSI_PKT_CMD_GCPS 0x18 /* Get Controller Packet Statistics */ +#define NCSI_PKT_CMD_GNS 0x19 /* Get NCSI Statistics */ +#define NCSI_PKT_CMD_GNPTS 0x1a /* Get NCSI Pass-throu Statistics */ +#define NCSI_PKT_CMD_GPS 0x1b /* Get package status */ +#define NCSI_PKT_CMD_OEM 0x50 /* OEM */ +#define NCSI_PKT_CMD_PLDM 0x51 /* PLDM request over NCSI over RBT */ +#define NCSI_PKT_CMD_GPUUID 0x52 /* Get package UUID */ + +/* NCSI packet responses */ +#define NCSI_PKT_RSP_CIS (NCSI_PKT_CMD_CIS + 0x80) +#define NCSI_PKT_RSP_SP (NCSI_PKT_CMD_SP + 0x80) +#define NCSI_PKT_RSP_DP (NCSI_PKT_CMD_DP + 0x80) +#define NCSI_PKT_RSP_EC (NCSI_PKT_CMD_EC + 0x80) +#define NCSI_PKT_RSP_DC (NCSI_PKT_CMD_DC + 0x80) +#define NCSI_PKT_RSP_RC (NCSI_PKT_CMD_RC + 0x80) +#define NCSI_PKT_RSP_ECNT (NCSI_PKT_CMD_ECNT + 0x80) +#define NCSI_PKT_RSP_DCNT (NCSI_PKT_CMD_DCNT + 0x80) +#define NCSI_PKT_RSP_AE (NCSI_PKT_CMD_AE + 0x80) +#define NCSI_PKT_RSP_SL (NCSI_PKT_CMD_SL + 0x80) +#define NCSI_PKT_RSP_GLS (NCSI_PKT_CMD_GLS + 0x80) +#define NCSI_PKT_RSP_SVF (NCSI_PKT_CMD_SVF + 0x80) +#define NCSI_PKT_RSP_EV (NCSI_PKT_CMD_EV + 0x80) +#define NCSI_PKT_RSP_DV (NCSI_PKT_CMD_DV + 0x80) +#define NCSI_PKT_RSP_SMA (NCSI_PKT_CMD_SMA + 0x80) +#define NCSI_PKT_RSP_EBF (NCSI_PKT_CMD_EBF + 0x80) +#define NCSI_PKT_RSP_DBF (NCSI_PKT_CMD_DBF + 0x80) +#define NCSI_PKT_RSP_EGMF (NCSI_PKT_CMD_EGMF + 0x80) +#define NCSI_PKT_RSP_DGMF (NCSI_PKT_CMD_DGMF + 0x80) +#define NCSI_PKT_RSP_SNFC (NCSI_PKT_CMD_SNFC + 0x80) +#define NCSI_PKT_RSP_GVI (NCSI_PKT_CMD_GVI + 0x80) +#define NCSI_PKT_RSP_GC (NCSI_PKT_CMD_GC + 0x80) +#define NCSI_PKT_RSP_GP (NCSI_PKT_CMD_GP + 0x80) +#define NCSI_PKT_RSP_GCPS (NCSI_PKT_CMD_GCPS + 0x80) +#define NCSI_PKT_RSP_GNS (NCSI_PKT_CMD_GNS + 0x80) +#define NCSI_PKT_RSP_GNPTS (NCSI_PKT_CMD_GNPTS + 0x80) +#define NCSI_PKT_RSP_GPS (NCSI_PKT_CMD_GPS + 0x80) +#define NCSI_PKT_RSP_OEM (NCSI_PKT_CMD_OEM + 0x80) +#define NCSI_PKT_RSP_PLDM (NCSI_PKT_CMD_PLDM + 0x80) +#define NCSI_PKT_RSP_GPUUID (NCSI_PKT_CMD_GPUUID + 0x80) + +/* NCSI response code/reason */ +#define NCSI_PKT_RSP_C_COMPLETED 0x0000 /* Command Completed */ +#define NCSI_PKT_RSP_C_FAILED 0x0001 /* Command Failed */ +#define NCSI_PKT_RSP_C_UNAVAILABLE 0x0002 /* Command Unavailable */ +#define NCSI_PKT_RSP_C_UNSUPPORTED 0x0003 /* Command Unsupported */ +#define NCSI_PKT_RSP_R_NO_ERROR 0x0000 /* No Error */ +#define NCSI_PKT_RSP_R_INTERFACE 0x0001 /* Interface not ready */ +#define NCSI_PKT_RSP_R_PARAM 0x0002 /* Invalid Parameter */ +#define NCSI_PKT_RSP_R_CHANNEL 0x0003 /* Channel not Ready */ +#define NCSI_PKT_RSP_R_PACKAGE 0x0004 /* Package not Ready */ +#define NCSI_PKT_RSP_R_LENGTH 0x0005 /* Invalid payload length */ +#define NCSI_PKT_RSP_R_UNKNOWN 0x7fff /* Command type unsupported */ + +/* NCSI AEN packet type */ +#define NCSI_PKT_AEN 0xFF /* AEN Packet */ +#define NCSI_PKT_AEN_LSC 0x00 /* Link status change */ +#define NCSI_PKT_AEN_CR 0x01 /* Configuration required */ +#define NCSI_PKT_AEN_HNCDSC 0x02 /* HNC driver status change */ + +/* OEM Vendor Manufacture ID */ +#define NCSI_OEM_MFR_MLX_ID 0x8119 +#define NCSI_OEM_MFR_BCM_ID 0x113d +#define NCSI_OEM_MFR_INTEL_ID 0x157 +/* Intel specific OEM command */ +#define NCSI_OEM_INTEL_CMD_GMA 0x06 /* CMD ID for Get MAC */ +#define NCSI_OEM_INTEL_CMD_KEEP_PHY 0x20 /* CMD ID for Keep PHY up */ +/* Broadcom specific OEM Command */ +#define NCSI_OEM_BCM_CMD_GMA 0x01 /* CMD ID for Get MAC */ +/* Mellanox specific OEM Command */ +#define NCSI_OEM_MLX_CMD_GMA 0x00 /* CMD ID for Get MAC */ +#define NCSI_OEM_MLX_CMD_GMA_PARAM 0x1b /* Parameter for GMA */ +#define NCSI_OEM_MLX_CMD_SMAF 0x01 /* CMD ID for Set MC Affinity */ +#define NCSI_OEM_MLX_CMD_SMAF_PARAM 0x07 /* Parameter for SMAF */ +/* Offset in OEM request */ +#define MLX_SMAF_MAC_ADDR_OFFSET 8 /* Offset for MAC in SMAF */ +#define MLX_SMAF_MED_SUPPORT_OFFSET 14 /* Offset for medium in SMAF */ +/* Mac address offset in OEM response */ +#define BCM_MAC_ADDR_OFFSET 28 +#define MLX_MAC_ADDR_OFFSET 8 +#define INTEL_MAC_ADDR_OFFSET 1 + +/* Status offset in OEM response */ +#define MLX_GMA_STATUS_OFFSET 0 +/* OEM Response payload length */ +#define MLX_GMA_PAYLOAD_LEN 24 + +#endif /* NCSI_PKT_H */ diff --git a/bochs/iodev/network/slirp/ncsi.cc b/bochs/iodev/network/slirp/ncsi.cc new file mode 100644 index 0000000000..d8b63df1bb --- /dev/null +++ b/bochs/iodev/network/slirp/ncsi.cc @@ -0,0 +1,330 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * NC-SI (Network Controller Sideband Interface) "echo" model + * + * Copyright (C) 2016-2018 IBM Corp. + * + * 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 copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "slirp.h" + +#include "ncsi-pkt.h" + +#if BX_NETWORKING && BX_NETMOD_SLIRP + +static uint32_t ncsi_calculate_checksum(uint8_t *data, int len) +{ + uint32_t checksum = 0; + int i; + + /* + * 32-bit unsigned sum of the NC-SI packet header and NC-SI packet + * payload interpreted as a series of 16-bit unsigned integer values. + */ + for (i = 0; i < len; i += 2) { + checksum += (((uint16_t) data[i]) << 8) + data[i+1]; + } + + checksum = (~checksum + 1); + return checksum; +} + +/* Response handler for Mellanox command Get Mac Address */ +static int ncsi_rsp_handler_oem_mlx_gma(Slirp *slirp, + const struct ncsi_pkt_hdr *nh, + struct ncsi_rsp_pkt_hdr *rnh) +{ + uint8_t oob_eth_addr_allocated = 0; + struct ncsi_rsp_oem_pkt *rsp; + int i; + + rsp = (struct ncsi_rsp_oem_pkt *)rnh; + + /* Set the payload length */ + rsp->rsp.common.length = htons(MLX_GMA_PAYLOAD_LEN); + + for (i = 0; i < ETH_ALEN; i++) { + if (slirp->oob_eth_addr[i] != 0x00) { + oob_eth_addr_allocated = 1; + break; + } + } + rsp->data[MLX_GMA_STATUS_OFFSET] = oob_eth_addr_allocated; + + /* Set the allocated management address */ + memcpy(&rsp->data[MLX_MAC_ADDR_OFFSET], slirp->oob_eth_addr, ETH_ALEN); + + return 0; +} + +/* Response handler for Mellanox card */ +static int ncsi_rsp_handler_oem_mlx(Slirp *slirp, const struct ncsi_pkt_hdr *nh, + struct ncsi_rsp_pkt_hdr *rnh) +{ + const struct ncsi_cmd_oem_pkt *cmd; + const struct ncsi_rsp_oem_mlx_pkt *cmd_mlx; + struct ncsi_rsp_oem_pkt *rsp; + struct ncsi_rsp_oem_mlx_pkt *rsp_mlx; + + /* Get the command header */ + cmd = (const struct ncsi_cmd_oem_pkt *)nh; + cmd_mlx = (const struct ncsi_rsp_oem_mlx_pkt *)cmd->data; + + /* Get the response header */ + rsp = (struct ncsi_rsp_oem_pkt *)rnh; + rsp_mlx = (struct ncsi_rsp_oem_mlx_pkt *)rsp->data; + + /* Ensure the OEM response header matches the command's */ + rsp_mlx->cmd_rev = cmd_mlx->cmd_rev; + rsp_mlx->cmd = cmd_mlx->cmd; + rsp_mlx->param = cmd_mlx->param; + rsp_mlx->optional = cmd_mlx->optional; + + if (cmd_mlx->cmd == NCSI_OEM_MLX_CMD_GMA && + cmd_mlx->param == NCSI_OEM_MLX_CMD_GMA_PARAM) + return ncsi_rsp_handler_oem_mlx_gma(slirp, nh, rnh); + + rsp->rsp.common.length = htons(8); + rsp->rsp.code = htons(NCSI_PKT_RSP_C_UNSUPPORTED); + rsp->rsp.reason = htons(NCSI_PKT_RSP_R_UNKNOWN); + return -ENOENT; +} + +static const struct ncsi_rsp_oem_handler { + unsigned int mfr_id; + int (*handler)(Slirp *slirp, const struct ncsi_pkt_hdr *nh, + struct ncsi_rsp_pkt_hdr *rnh); +} ncsi_rsp_oem_handlers[] = { + { NCSI_OEM_MFR_MLX_ID, ncsi_rsp_handler_oem_mlx }, + { NCSI_OEM_MFR_BCM_ID, NULL }, + { NCSI_OEM_MFR_INTEL_ID, NULL }, +}; + +/* Response handler for OEM command */ +static int ncsi_rsp_handler_oem(Slirp *slirp, const struct ncsi_pkt_hdr *nh, + struct ncsi_rsp_pkt_hdr *rnh) +{ + const struct ncsi_rsp_oem_handler *nrh = NULL; + const struct ncsi_cmd_oem_pkt *cmd = (const struct ncsi_cmd_oem_pkt *)nh; + struct ncsi_rsp_oem_pkt *rsp = (struct ncsi_rsp_oem_pkt *)rnh; + uint32_t mfr_id = ntohl(cmd->mfr_id); + int i; + + rsp->mfr_id = cmd->mfr_id; + + if (mfr_id != slirp->mfr_id) { + goto error; + } + + /* Check for manufacturer id and Find the handler */ + for (i = 0; i < (int)SLIRP_N_ELEMENTS(ncsi_rsp_oem_handlers); i++) { + if (ncsi_rsp_oem_handlers[i].mfr_id == mfr_id) { + if (ncsi_rsp_oem_handlers[i].handler) + nrh = &ncsi_rsp_oem_handlers[i]; + else + nrh = NULL; + + break; + } + } + + if (!nrh) { + goto error; + } + + /* Process the packet */ + return nrh->handler(slirp, nh, rnh); + +error: + rsp->rsp.common.length = htons(8); + rsp->rsp.code = htons(NCSI_PKT_RSP_C_UNSUPPORTED); + rsp->rsp.reason = htons(NCSI_PKT_RSP_R_UNKNOWN); + return -ENOENT; +} + + +/* Get Version ID */ +static int ncsi_rsp_handler_gvi(Slirp *slirp, const struct ncsi_pkt_hdr *nh, + struct ncsi_rsp_pkt_hdr *rnh) +{ + struct ncsi_rsp_gvi_pkt *rsp = (struct ncsi_rsp_gvi_pkt *)rnh; + + rsp->ncsi_version = htonl(0xF1F0F000); + rsp->mf_id = htonl(slirp->mfr_id); + + return 0; +} + +/* Get Capabilities */ +static int ncsi_rsp_handler_gc(Slirp *slirp, const struct ncsi_pkt_hdr *nh, + struct ncsi_rsp_pkt_hdr *rnh) +{ + struct ncsi_rsp_gc_pkt *rsp = (struct ncsi_rsp_gc_pkt *)rnh; + + rsp->cap = htonl(~0); + rsp->bc_cap = htonl(~0); + rsp->mc_cap = htonl(~0); + rsp->buf_cap = htonl(~0); + rsp->aen_cap = htonl(~0); + rsp->vlan_mode = 0xff; + rsp->uc_cnt = 2; + return 0; +} + +/* Get Link status */ +static int ncsi_rsp_handler_gls(Slirp *slirp, const struct ncsi_pkt_hdr *nh, + struct ncsi_rsp_pkt_hdr *rnh) +{ + struct ncsi_rsp_gls_pkt *rsp = (struct ncsi_rsp_gls_pkt *)rnh; + + rsp->status = htonl(0x1); + return 0; +} + +/* Get Parameters */ +static int ncsi_rsp_handler_gp(Slirp *slirp, const struct ncsi_pkt_hdr *nh, + struct ncsi_rsp_pkt_hdr *rnh) +{ + struct ncsi_rsp_gp_pkt *rsp = (struct ncsi_rsp_gp_pkt *)rnh; + + /* no MAC address filters or VLAN filters on the channel */ + rsp->mac_cnt = 0; + rsp->mac_enable = 0; + rsp->vlan_cnt = 0; + rsp->vlan_enable = 0; + + return 0; +} + +static const struct ncsi_rsp_handler { + unsigned char type; + int payload; + int (*handler)(Slirp *slirp, const struct ncsi_pkt_hdr *nh, + struct ncsi_rsp_pkt_hdr *rnh); +} ncsi_rsp_handlers[] = { { NCSI_PKT_RSP_CIS, 4, NULL }, + { NCSI_PKT_RSP_SP, 4, NULL }, + { NCSI_PKT_RSP_DP, 4, NULL }, + { NCSI_PKT_RSP_EC, 4, NULL }, + { NCSI_PKT_RSP_DC, 4, NULL }, + { NCSI_PKT_RSP_RC, 4, NULL }, + { NCSI_PKT_RSP_ECNT, 4, NULL }, + { NCSI_PKT_RSP_DCNT, 4, NULL }, + { NCSI_PKT_RSP_AE, 4, NULL }, + { NCSI_PKT_RSP_SL, 4, NULL }, + { NCSI_PKT_RSP_GLS, 16, ncsi_rsp_handler_gls }, + { NCSI_PKT_RSP_SVF, 4, NULL }, + { NCSI_PKT_RSP_EV, 4, NULL }, + { NCSI_PKT_RSP_DV, 4, NULL }, + { NCSI_PKT_RSP_SMA, 4, NULL }, + { NCSI_PKT_RSP_EBF, 4, NULL }, + { NCSI_PKT_RSP_DBF, 4, NULL }, + { NCSI_PKT_RSP_EGMF, 4, NULL }, + { NCSI_PKT_RSP_DGMF, 4, NULL }, + { NCSI_PKT_RSP_SNFC, 4, NULL }, + { NCSI_PKT_RSP_GVI, 40, ncsi_rsp_handler_gvi }, + { NCSI_PKT_RSP_GC, 32, ncsi_rsp_handler_gc }, + { NCSI_PKT_RSP_GP, 40, ncsi_rsp_handler_gp }, + { NCSI_PKT_RSP_GCPS, 172, NULL }, + { NCSI_PKT_RSP_GNS, 172, NULL }, + { NCSI_PKT_RSP_GNPTS, 172, NULL }, + { NCSI_PKT_RSP_GPS, 8, NULL }, + { NCSI_PKT_RSP_OEM, 0, ncsi_rsp_handler_oem }, + { NCSI_PKT_RSP_PLDM, 0, NULL }, + { NCSI_PKT_RSP_GPUUID, 20, NULL } }; + +/* + * packet format : ncsi header + payload + checksum + */ +#define NCSI_MAX_PAYLOAD 172 +#define NCSI_MAX_LEN (sizeof(struct ncsi_pkt_hdr) + NCSI_MAX_PAYLOAD + 4) + +void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) +{ + const struct ncsi_pkt_hdr *nh = + (const struct ncsi_pkt_hdr *)(pkt + ETH_HLEN); + uint8_t ncsi_reply[2 + ETH_HLEN + NCSI_MAX_LEN]; + struct ethhdr *reh = (struct ethhdr *)(ncsi_reply + 2); + struct ncsi_rsp_pkt_hdr *rnh = + (struct ncsi_rsp_pkt_hdr *)(ncsi_reply + 2 + ETH_HLEN); + const struct ncsi_rsp_handler *handler = NULL; + int i; + int ncsi_rsp_len = sizeof(*nh); + uint32_t checksum; + uint32_t *pchecksum; + + if (pkt_len < (int)(ETH_HLEN + sizeof(struct ncsi_pkt_hdr))) { + return; /* packet too short */ + } + + memset(ncsi_reply, 0, sizeof(ncsi_reply)); + + memset(reh->h_dest, 0xff, ETH_ALEN); + memset(reh->h_source, 0xff, ETH_ALEN); + reh->h_proto = htons(ETH_P_NCSI); + + for (i = 0; i < (int)SLIRP_N_ELEMENTS(ncsi_rsp_handlers); i++) { + if (ncsi_rsp_handlers[i].type == nh->type + 0x80) { + handler = &ncsi_rsp_handlers[i]; + break; + } + } + + rnh->common.mc_id = nh->mc_id; + rnh->common.revision = NCSI_PKT_REVISION; + rnh->common.id = nh->id; + rnh->common.type = nh->type + 0x80; + rnh->common.channel = nh->channel; + + if (handler) { + rnh->common.length = htons(handler->payload); + rnh->code = htons(NCSI_PKT_RSP_C_COMPLETED); + rnh->reason = htons(NCSI_PKT_RSP_R_NO_ERROR); + + if (handler->handler) { + handler->handler(slirp, nh, rnh); + } + ncsi_rsp_len += ntohs(rnh->common.length); + } else { + rnh->common.length = 0; + rnh->code = htons(NCSI_PKT_RSP_C_UNAVAILABLE); + rnh->reason = htons(NCSI_PKT_RSP_R_UNKNOWN); + } + + /* Add the optional checksum at the end of the frame. */ + checksum = ncsi_calculate_checksum((uint8_t *)rnh, ncsi_rsp_len); + pchecksum = (uint32_t *)((char *)rnh + ncsi_rsp_len); + *pchecksum = htonl(checksum); + ncsi_rsp_len += 4; + + slirp_send_packet_all(slirp, ncsi_reply + 2, ETH_HLEN + ncsi_rsp_len); +} + +#endif diff --git a/bochs/iodev/network/slirp/ndp_table.cc b/bochs/iodev/network/slirp/ndp_table.cc new file mode 100644 index 0000000000..49218724ee --- /dev/null +++ b/bochs/iodev/network/slirp/ndp_table.cc @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2013 + * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. + */ + +#include "slirp.h" + +#if BX_NETWORKING && BX_NETMOD_SLIRP + +void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr, + uint8_t ethaddr[ETH_ALEN]) +{ + char addrstr[INET6_ADDRSTRLEN]; + NdpTable *ndp_table = &slirp->ndp_table; + int i; + char ethaddr_str[ETH_ADDRSTRLEN]; + + inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN); + + DEBUG_CALL("ndp_table_add"); + DEBUG_ARG("ip = %s", addrstr); + DEBUG_ARG("hw addr = %s", slirp_ether_ntoa(ethaddr, ethaddr_str, + sizeof(ethaddr_str))); + + if (IN6_IS_ADDR_MULTICAST(&ip_addr) || in6_zero(&ip_addr)) { + /* Do not register multicast or unspecified addresses */ + DEBUG_CALL(" abort: do not register multicast or unspecified address"); + return; + } + + /* Search for an entry */ + for (i = 0; i < NDP_TABLE_SIZE; i++) { + if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) { + DEBUG_CALL(" already in table: update the entry"); + /* Update the entry */ + memcpy(ndp_table->table[i].eth_addr, ethaddr, ETH_ALEN); + return; + } + } + + /* No entry found, create a new one */ + DEBUG_CALL(" create new entry"); + /* Save the first entry, it is the guest. */ + if (in6_zero(&ndp_table->guest_in6_addr)) { + ndp_table->guest_in6_addr = ip_addr; + } + ndp_table->table[ndp_table->next_victim].ip_addr = ip_addr; + memcpy(ndp_table->table[ndp_table->next_victim].eth_addr, ethaddr, + ETH_ALEN); + ndp_table->next_victim = (ndp_table->next_victim + 1) % NDP_TABLE_SIZE; +} + +bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr, + uint8_t out_ethaddr[ETH_ALEN]) +{ + char addrstr[INET6_ADDRSTRLEN]; + NdpTable *ndp_table = &slirp->ndp_table; + int i; + char ethaddr_str[ETH_ADDRSTRLEN]; + + inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN); + + DEBUG_CALL("ndp_table_search"); + DEBUG_ARG("ip = %s", addrstr); + + /* If unspecified address */ + if (in6_zero(&ip_addr)) { + /* return Ethernet broadcast address */ + memset(out_ethaddr, 0xff, ETH_ALEN); + return 1; + } + + /* Multicast address: fec0::abcd:efgh/8 -> 33:33:ab:cd:ef:gh */ + if (IN6_IS_ADDR_MULTICAST(&ip_addr)) { + out_ethaddr[0] = 0x33; + out_ethaddr[1] = 0x33; + out_ethaddr[2] = ip_addr.s6_addr[12]; + out_ethaddr[3] = ip_addr.s6_addr[13]; + out_ethaddr[4] = ip_addr.s6_addr[14]; + out_ethaddr[5] = ip_addr.s6_addr[15]; + DEBUG_ARG("multicast addr = %s", + slirp_ether_ntoa(out_ethaddr, ethaddr_str, + sizeof(ethaddr_str))); + return 1; + } + + for (i = 0; i < NDP_TABLE_SIZE; i++) { + if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) { + memcpy(out_ethaddr, ndp_table->table[i].eth_addr, ETH_ALEN); + DEBUG_ARG("found hw addr = %s", + slirp_ether_ntoa(out_ethaddr, ethaddr_str, + sizeof(ethaddr_str))); + return 1; + } + } + + DEBUG_CALL(" ip not found in table"); + return 0; +} + +#endif diff --git a/bochs/iodev/network/slirp/sbuf.cc b/bochs/iodev/network/slirp/sbuf.cc index fb2f53fe76..4eaf185971 100644 --- a/bochs/iodev/network/slirp/sbuf.cc +++ b/bochs/iodev/network/slirp/sbuf.cc @@ -1,11 +1,6 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ #include "slirp.h" @@ -14,180 +9,153 @@ static void sbappendsb(struct sbuf *sb, struct mbuf *m); -void -sbfree(struct sbuf *sb) +void sbfree(struct sbuf *sb) { - free(sb->sb_data); + free(sb->sb_data); } -void -sbdrop(struct sbuf *sb, int num) +bool sbdrop(struct sbuf *sb, size_t num) { int limit = sb->sb_datalen / 2; - /* - * We can only drop how much we have - * This should never succeed - */ - if (num > (int)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; - - if ((int)sb->sb_cc < limit && ((int)sb->sb_cc + num) >= limit) { -// qemu_notify_event(); + slirp_warn_if_fail(num <= sb->sb_cc); + 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; + + if ((int)sb->sb_cc < limit && (int)(sb->sb_cc + num) >= limit) { + return true; } + + return false; } -void -sbreserve(struct sbuf *sb, int size) +void sbreserve(struct sbuf *sb, size_t size) { - if (sb->sb_data) { - /* Already alloced, realloc if necessary */ - if ((int)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; - } + sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char*)realloc(sb->sb_data, size); + sb->sb_cc = 0; + sb->sb_datalen = size; } -/* - * 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) +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 = (int)slirp_send(so, 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); + int ret = 0; + + DEBUG_CALL("sbappend"); + DEBUG_ARG("so = %p", so); + DEBUG_ARG("m = %p", 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 = (int)slirp_send(so, 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 */ -static void -sbappendsb(struct sbuf *sb, struct mbuf *m) +static 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; + 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, int off, int len, char *to) +void sbcopy(struct sbuf *sb, size_t off, size_t 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 > (int)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); - } + char *from; + + assert(len + off <= sb->sb_cc); + + from = sb->sb_rptr + off; + if (from >= sb->sb_data + sb->sb_datalen) + from -= sb->sb_datalen; + + if (from < sb->sb_wptr) { + 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); + } } #endif diff --git a/bochs/iodev/network/slirp/sbuf.h b/bochs/iodev/network/slirp/sbuf.h index 479b5b360a..a3eaf4968d 100644 --- a/bochs/iodev/network/slirp/sbuf.h +++ b/bochs/iodev/network/slirp/sbuf.h @@ -1,33 +1,46 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ -#ifndef _SBUF_H_ -#define _SBUF_H_ +#ifndef SBUF_H +#define SBUF_H -#define sbflush(sb) sbdrop((sb),(sb)->sb_cc) +/* How many bytes are free in the sbuf */ #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 */ + uint32_t sb_cc; /* actual chars in buffer */ + uint32_t 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 *, int); -void sbreserve(struct sbuf *, int); -void sbappend(struct socket *, struct mbuf *); -void sbcopy(struct sbuf *, int, int, char *); +/* Release the sbuf */ +void sbfree(struct sbuf *sb); + +/* Drop len bytes from the reading end of the sbuf */ +bool sbdrop(struct sbuf *sb, size_t len); + +/* (re)Allocate sbuf buffer to store size bytes */ +void sbreserve(struct sbuf *sb, size_t size); + +/* + * 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 *sb, struct mbuf *mb); + +/* + * 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, size_t off, size_t len, char *p); #endif diff --git a/bochs/iodev/network/slirp/slirp.cc b/bochs/iodev/network/slirp/slirp.cc index 8cded33690..2d48c35f2c 100644 --- a/bochs/iodev/network/slirp/slirp.cc +++ b/bochs/iodev/network/slirp/slirp.cc @@ -1,6 +1,4 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: MIT */ /* * libslirp glue * @@ -27,11 +25,55 @@ #define BX_PLUGGABLE #include "slirp.h" -#include "iodev.h" #if BX_NETWORKING && BX_NETMOD_SLIRP -#define LOG_THIS ((logfunctions*)slirp->logfn)-> +static logfunctions *slirplog = NULL; + +#ifndef _WIN32 +#include +#endif + +/* https://gitlab.freedesktop.org/slirp/libslirp/issues/18 */ +#if defined(__NetBSD__) && defined(if_mtu) +#undef if_mtu +#endif + +#if defined(_WIN32) + +#define INITIAL_DNS_ADDR_BUF_SIZE 32 * 1024 +#define REALLOC_RETRIES 5 + +// Broadcast site local DNS resolvers. We do not use these because they are +// highly unlikely to be valid. +// https://www.ietf.org/proceedings/52/I-D/draft-ietf-ipngwg-dns-discovery-03.txt +static const struct in6_addr SITE_LOCAL_DNS_BROADCAST_ADDRS[] = { + { + {{ + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + }} + }, + { + {{ + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 + }} + }, + { + {{ + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + }} + }, +}; + +#endif + +int slirp_debug; + +/* Define to 1 if you want KEEPALIVE timers */ +bool slirp_do_keepalive; /* host loopback address */ struct in_addr loopback_addr; @@ -39,38 +81,29 @@ struct in_addr loopback_addr; unsigned long loopback_mask; /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */ -static const uint8_t special_ethaddr[ETH_ALEN] = { - 0x52, 0x55, 0x00, 0x00, 0x00, 0x00 -}; - -static const uint8_t zero_ethaddr[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - -/* XXX: suppress those select globals */ -fd_set *global_readfds, *global_writefds, *global_xfds; - -u_int curtime; +static const uint8_t special_ethaddr[ETH_ALEN] = { 0x52, 0x55, 0x00, + 0x00, 0x00, 0x00 }; -static QTAILQ_HEAD(slirp_instances, Slirp) slirp_instances = - QTAILQ_HEAD_INITIALIZER(slirp_instances); +unsigned curtime; static struct in_addr dns_addr; -static u_int dns_addr_time; +static struct in6_addr dns6_addr; +static uint32_t dns6_scope_id; +static unsigned dns_addr_time; +static unsigned dns6_addr_time; #define TIMEOUT_FAST 2 /* milliseconds */ #define TIMEOUT_SLOW 499 /* milliseconds */ /* for the aging of certain requests like DNS */ #define TIMEOUT_DEFAULT 1000 /* milliseconds */ -#if defined(_WIN32) || defined(__CYGWIN__) - -#include -#include +#if defined(_WIN32) int get_dns_addr(struct in_addr *pdns_addr) { - FIXED_INFO *FixedInfo=NULL; - ULONG BufLen; - DWORD ret; + FIXED_INFO *FixedInfo = NULL; + ULONG BufLen; + DWORD ret; IP_ADDR_STRING *pIPAddr; struct in_addr tmp_addr; @@ -91,7 +124,7 @@ int get_dns_addr(struct in_addr *pdns_addr) } if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) { - printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret ); + printf("GetNetworkParams failed. ret = %08x\n", (unsigned)ret); if (FixedInfo) { GlobalFree(FixedInfo); FixedInfo = NULL; @@ -111,82 +144,388 @@ int get_dns_addr(struct in_addr *pdns_addr) return 0; } -#else +static int is_site_local_dns_broadcast(struct in6_addr *address) +{ + int i; + for (i = 0; i < (int)SLIRP_N_ELEMENTS(SITE_LOCAL_DNS_BROADCAST_ADDRS); i++) { + if (in6_equal(address, &SITE_LOCAL_DNS_BROADCAST_ADDRS[i])) { + return 1; + } + } + return 0; +} -static struct stat dns_addr_stat; +static void print_dns_v6_address(struct in6_addr address) +{ + char address_str[INET6_ADDRSTRLEN] = ""; + if (inet_ntop(AF_INET6, &address, address_str, INET6_ADDRSTRLEN) + == NULL) { + DEBUG_ERROR("Failed to stringify IPv6 address for logging."); + return; + } + DEBUG_RAW_CALL("IPv6 DNS server found: %s", address_str); +} -int get_dns_addr(struct in_addr *pdns_addr) +// Gets the first valid DNS resolver with an IPv6 address. +// Ignores any site local broadcast DNS servers, as these +// are on deprecated addresses and not generally expected +// to work. Further details at: +// https://www.ietf.org/proceedings/52/I-D/draft-ietf-ipngwg-dns-discovery-03.txt +static int get_ipv6_dns_server(struct in6_addr *dns_server_address, uint32_t *scope_id) { - char buff[512]; - char buff2[257]; - FILE *f; - int found = 0; - struct in_addr tmp_addr; + PIP_ADAPTER_ADDRESSES addresses = NULL; + PIP_ADAPTER_ADDRESSES address = NULL; + IP_ADAPTER_DNS_SERVER_ADDRESS *dns_server = NULL; + struct sockaddr_in6 *dns_v6_addr = NULL; + + ULONG buf_size = INITIAL_DNS_ADDR_BUF_SIZE; + DWORD res = ERROR_BUFFER_OVERFLOW; + int i; + + for (i = 0; i < REALLOC_RETRIES; i++) { + // If non null, we hit buffer overflow, free it so we can try again. + if (addresses != NULL) { + free(addresses); + } + + addresses = (PIP_ADAPTER_ADDRESSES)malloc(buf_size); + res = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, + addresses, &buf_size); + + if (res != ERROR_BUFFER_OVERFLOW) { + break; + } + } + + if (res != NO_ERROR) { + DEBUG_ERROR("Failed to get IPv6 DNS addresses due to error %lX", res); + goto failure; + } + + address = addresses; + for (address = addresses; address != NULL; address = address->Next) { + for (dns_server = address->FirstDnsServerAddress; + dns_server != NULL; + dns_server = dns_server->Next) { + + if (dns_server->Address.lpSockaddr->sa_family != AF_INET6) { + continue; + } + + dns_v6_addr = (struct sockaddr_in6 *)dns_server->Address.lpSockaddr; + if (is_site_local_dns_broadcast(&dns_v6_addr->sin6_addr) == 0) { + print_dns_v6_address(dns_v6_addr->sin6_addr); + *dns_server_address = dns_v6_addr->sin6_addr; + *scope_id = dns_v6_addr->sin6_scope_id; + + free(addresses); + return 0; + } + } + } + + DEBUG_ERROR("No IPv6 DNS servers found.\n"); + +failure: + free(addresses); + return -1; +} + +int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id) +{ + if (!in6_zero(&dns6_addr) && (curtime - dns6_addr_time) < TIMEOUT_DEFAULT) { + *pdns6_addr = dns6_addr; + *scope_id = dns6_scope_id; + return 0; + } + + if (get_ipv6_dns_server(pdns6_addr, scope_id) == 0) { + dns6_addr = *pdns6_addr; + dns6_addr_time = curtime; + dns6_scope_id = *scope_id; + return 0; + } + + return -1; +} + +static void winsock_cleanup(void) +{ + WSACleanup(); +} + +#elif defined(__APPLE__) + +#include + +static int get_dns_addr_cached(void *pdns_addr, void *cached_addr, + socklen_t addrlen, unsigned *cached_time) +{ + if (curtime - *cached_time < TIMEOUT_DEFAULT) { + memcpy(pdns_addr, cached_addr, addrlen); + return 0; + } + return 1; +} + +static int get_dns_addr_libresolv(int af, void *pdns_addr, void *cached_addr, + socklen_t addrlen, + uint32_t *scope_id, uint32_t *cached_scope_id, + unsigned *cached_time) +{ + struct __res_state state; + union res_sockaddr_union servers[NI_MAXSERV]; + int count; + int found; + void *addr; + + // we only support IPv4 and IPv4, we assume it's one or the other + assert(af == AF_INET || af == AF_INET6); + + if (res_ninit(&state) != 0) { + return -1; + } + count = res_getservers(&state, servers, NI_MAXSERV); + found = 0; + DEBUG_MISC("IP address of your DNS(s):"); + for (int i = 0; i < count; i++) { + if (af == servers[i].sin.sin_family) { + found++; + } + if (af == AF_INET) { + addr = &servers[i].sin.sin_addr; + } else { // af == AF_INET6 + addr = &servers[i].sin6.sin6_addr; + } + + // we use the first found entry + if (found == 1) { + memcpy(pdns_addr, addr, addrlen); + memcpy(cached_addr, addr, addrlen); + if (scope_id) { + *scope_id = 0; + } + if (cached_scope_id) { + *cached_scope_id = 0; + } + *cached_time = curtime; + } + + if (found > 3) { + DEBUG_MISC(" (more)"); + break; + } else if (slirp_debug & DBG_MISC) { + char s[INET6_ADDRSTRLEN]; + const char *res = inet_ntop(af, addr, s, sizeof(s)); + if (!res) { + res = " (string conversion error)"; + } + DEBUG_MISC(" %s", res); + } + } + + res_ndestroy(&state); + if (!found) + return -1; + return 0; +} + +int get_dns_addr(struct in_addr *pdns_addr) +{ if (dns_addr.s_addr != 0) { - struct stat old_stat; - if ((curtime - dns_addr_time) < TIMEOUT_DEFAULT) { - *pdns_addr = dns_addr; - return 0; + int ret; + ret = get_dns_addr_cached(pdns_addr, &dns_addr, sizeof(dns_addr), + &dns_addr_time); + if (ret <= 0) { + return ret; } - old_stat = dns_addr_stat; - if (stat("/etc/resolv.conf", &dns_addr_stat) != 0) - return -1; - if ((dns_addr_stat.st_dev == old_stat.st_dev) - && (dns_addr_stat.st_ino == old_stat.st_ino) - && (dns_addr_stat.st_size == old_stat.st_size) - && (dns_addr_stat.st_mtime == old_stat.st_mtime)) { - *pdns_addr = dns_addr; - return 0; + } + return get_dns_addr_libresolv(AF_INET, pdns_addr, &dns_addr, + sizeof(dns_addr), NULL, NULL, &dns_addr_time); +} + +int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id) +{ + if (!in6_zero(&dns6_addr)) { + int ret; + ret = get_dns_addr_cached(pdns6_addr, &dns6_addr, sizeof(dns6_addr), + &dns6_addr_time); + if (ret == 0) { + *scope_id = dns6_scope_id; + } + if (ret <= 0) { + return ret; } } + return get_dns_addr_libresolv(AF_INET6, pdns6_addr, &dns6_addr, + sizeof(dns6_addr), + scope_id, &dns6_scope_id, &dns6_addr_time); +} + +#else // !defined(_WIN32) && !defined(__APPLE__) + +#if defined(__HAIKU__) +#define RESOLV_CONF_PATH "/boot/system/settings/network/resolv.conf" +#else +#define RESOLV_CONF_PATH "/etc/resolv.conf" +#endif + +static int get_dns_addr_cached(void *pdns_addr, void *cached_addr, + socklen_t addrlen, struct stat *cached_stat, + unsigned *cached_time) +{ + struct stat old_stat; + if (curtime - *cached_time < TIMEOUT_DEFAULT) { + memcpy(pdns_addr, cached_addr, addrlen); + return 0; + } + old_stat = *cached_stat; + if (stat(RESOLV_CONF_PATH, cached_stat) != 0) { + return -1; + } + if (cached_stat->st_dev == old_stat.st_dev && + cached_stat->st_ino == old_stat.st_ino && + cached_stat->st_size == old_stat.st_size && + cached_stat->st_mtime == old_stat.st_mtime) { + memcpy(pdns_addr, cached_addr, addrlen); + return 0; + } + return 1; +} + +static bool try_and_setdns_server(int af, unsigned found, unsigned if_index, + const char *buff2, void *pdns_addr, void *cached_addr, + socklen_t addrlen, uint32_t *scope_id, uint32_t *cached_scope_id, + unsigned *cached_time) +{ + union { + struct in_addr dns_addr; + struct in6_addr dns6_addr; + } tmp_addr; + + assert(sizeof(tmp_addr) >= addrlen); + + if (!inet_pton(af, buff2, &tmp_addr)) + return false; + + /* If it's the first one, set it to dns_addr */ + if (!found) { + memcpy(pdns_addr, &tmp_addr, addrlen); + memcpy(cached_addr, &tmp_addr, addrlen); + if (scope_id) { + *scope_id = if_index; + } + if (cached_scope_id) { + *cached_scope_id = if_index; + } + *cached_time = curtime; + } + + if (found > 2) { + DEBUG_MISC(" (more)"); + } else if (slirp_debug & DBG_MISC) { + char s[INET6_ADDRSTRLEN]; + const char *res = inet_ntop(af, &tmp_addr, s, sizeof(s)); + if (!res) { + res = " (string conversion error)"; + } + DEBUG_MISC(" %s", res); + } - f = fopen("/etc/resolv.conf", "r"); + return true; +} + +static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr, + socklen_t addrlen, + uint32_t *scope_id, uint32_t *cached_scope_id, + unsigned *cached_time) +{ + char buff[512]; + char buff2[257]; + FILE *f; + int found = 0; + unsigned if_index; + unsigned nameservers = 0; + + f = fopen(RESOLV_CONF_PATH, "r"); if (!f) return -1; -#ifdef DEBUG - printf("IP address of your DNS(s): "); -#endif + DEBUG_MISC("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 it's the first one, set it to dns_addr */ - if (!found) { - *pdns_addr = tmp_addr; - dns_addr = tmp_addr; - dns_addr_time = curtime; + char *c = strchr(buff2, '%'); + if (c) { + if_index = if_nametoindex(c + 1); + *c = '\0'; + } else { + if_index = 0; } -#ifdef DEBUG - else - printf(", "); -#endif - if (++found > 3) { -#ifdef DEBUG - printf("(more)"); -#endif - break; - } -#ifdef DEBUG - else - printf("%s", inet_ntoa(tmp_addr)); -#endif + + nameservers++; + + if (!try_and_setdns_server(af, found, if_index, buff2, pdns_addr, + cached_addr, addrlen, scope_id, + cached_scope_id, cached_time)) + continue; + + if (++found > 3) + break; } } fclose(f); - if (!found) + if (nameservers && !found) return -1; - return 0; + if (!nameservers) { + found += try_and_setdns_server(af, found, 0, "127.0.0.1", + pdns_addr, cached_addr, addrlen, scope_id, + cached_scope_id, cached_time); + found += try_and_setdns_server(af, found, 0, "::1", + pdns_addr, cached_addr, addrlen, scope_id, + cached_scope_id, cached_time); + } + + return found ? 0 : -1; } -#endif +int get_dns_addr(struct in_addr *pdns_addr) +{ + static struct stat dns_addr_stat; -#ifdef _WIN32 -static void CDECL winsock_cleanup(void) + if (dns_addr.s_addr != 0) { + int ret; + ret = get_dns_addr_cached(pdns_addr, &dns_addr, sizeof(dns_addr), + &dns_addr_stat, &dns_addr_time); + if (ret <= 0) { + return ret; + } + } + return get_dns_addr_resolv_conf(AF_INET, pdns_addr, &dns_addr, + sizeof(dns_addr), + NULL, NULL, &dns_addr_time); +} + +int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id) { - WSACleanup(); + static struct stat dns6_addr_stat; + + if (!in6_zero(&dns6_addr)) { + int ret; + ret = get_dns_addr_cached(pdns6_addr, &dns6_addr, sizeof(dns6_addr), + &dns6_addr_stat, &dns6_addr_time); + if (ret == 0) { + *scope_id = dns6_scope_id; + } + if (ret <= 0) { + return ret; + } + } + return get_dns_addr_resolv_conf(AF_INET6, pdns6_addr, &dns6_addr, + sizeof(dns6_addr), + scope_id, &dns6_scope_id, &dns6_addr_time); } + #endif static void slirp_init_once(void) @@ -208,86 +547,216 @@ static void slirp_init_once(void) loopback_addr.s_addr = htonl(INADDR_LOOPBACK); loopback_mask = htonl(IN_CLASSA_NET); + + slirp_debug = 0; } -Slirp *slirp_init(int restricted, struct in_addr vnetwork, - struct in_addr vnetmask, struct in_addr vhost, - const char *vhostname, const char *tftp_path, - const char *bootfile, struct in_addr vdhcp_start, - struct in_addr vnameserver, const char **vdnssearch, - void *opaque, void *logfn) +static void ra_timer_handler_cb(void *opaque) { - Slirp *slirp = (Slirp*)malloc(sizeof(Slirp)); + Slirp *slirp = (Slirp*)opaque; + + ra_timer_handler(slirp, NULL); +} + +void slirp_handle_timer(Slirp *slirp, SlirpTimerId id, void *cb_opaque) +{ + slirp_return_if_fail(id >= 0 && id < SLIRP_TIMER_NUM); + + switch (id) { + case SLIRP_TIMER_RA: + ra_timer_handler(slirp, cb_opaque); + return; + default: + abort(); + } +} + +void *slirp_timer_new(Slirp *slirp, SlirpTimerId id, void *cb_opaque) +{ + slirp_return_val_if_fail(id >= 0 && id < SLIRP_TIMER_NUM, NULL); + + if (slirp->cfg_version >= 4 && slirp->cb->timer_new_opaque) { + return slirp->cb->timer_new_opaque(id, cb_opaque, slirp->opaque); + } + + switch (id) { + case SLIRP_TIMER_RA: + slirp_return_val_if_fail(cb_opaque == NULL, NULL); + return slirp->cb->timer_new(ra_timer_handler_cb, slirp, slirp->opaque); + + default: + abort(); + } +} + +Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque) +{ + Slirp *slirp; + + slirp_return_val_if_fail(cfg != NULL, NULL); + slirp_return_val_if_fail(cfg->version >= SLIRP_CONFIG_VERSION_MIN, NULL); + slirp_return_val_if_fail(cfg->version <= SLIRP_CONFIG_VERSION_MAX, NULL); + slirp_return_val_if_fail(cfg->if_mtu >= IF_MTU_MIN || cfg->if_mtu == 0, NULL); + slirp_return_val_if_fail(cfg->if_mtu <= IF_MTU_MAX, NULL); + slirp_return_val_if_fail(cfg->if_mru >= IF_MRU_MIN || cfg->if_mru == 0, NULL); + slirp_return_val_if_fail(cfg->if_mru <= IF_MRU_MAX, NULL); + slirp_return_val_if_fail(!cfg->bootfile || + (strlen(cfg->bootfile) < + G_SIZEOF_MEMBER(struct bootp_t, bp_file)), NULL); + + slirp = (Slirp*)malloc(sizeof(Slirp)); memset(slirp, 0, sizeof(Slirp)); slirp_init_once(); - slirp->restricted = restricted; + slirp->cfg_version = cfg->version; + slirp->opaque = opaque; + slirp->cb = callbacks; + slirp->restricted = cfg->restricted; + + slirp->in_enabled = cfg->in_enabled; + slirp->in6_enabled = cfg->in6_enabled; if_init(slirp); ip_init(slirp); - /* Initialise mbufs *after* setting the MTU */ m_init(slirp); - slirp->vnetwork_addr = vnetwork; - slirp->vnetwork_mask = vnetmask; - slirp->vhost_addr = vhost; - if (vhostname) { - pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname), - vhostname); + slirp->vnetwork_addr = cfg->vnetwork; + slirp->vnetwork_mask = cfg->vnetmask; + slirp->vhost_addr = cfg->vhost; + slirp->vprefix_addr6 = cfg->vprefix_addr6; + slirp->vprefix_len = cfg->vprefix_len; + slirp->vhost_addr6 = cfg->vhost6; + if (cfg->vhostname) { + slirp_pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname), + cfg->vhostname); + } + if (cfg->tftp_path) { + slirp->tftp_prefix = strdup(cfg->tftp_path); + } + if (cfg->bootfile) { + slirp->bootp_filename = strdup(cfg->bootfile); + } + if (cfg->vdomainname) { + slirp->vdomainname = strdup(cfg->vdomainname); + } + slirp->vdhcp_startaddr = cfg->vdhcp_start; + slirp->vnameserver_addr = cfg->vnameserver; + slirp->vnameserver_addr6 = cfg->vnameserver6; + if (cfg->tftp_server_name) { + slirp->tftp_server_name = strdup(cfg->tftp_server_name); + } + + if (cfg->vdnssearch) { + translate_dnssearch(slirp, cfg->vdnssearch); } - if (tftp_path) { - slirp->tftp_prefix = strdup(tftp_path); + slirp->if_mtu = cfg->if_mtu == 0 ? IF_MTU_DEFAULT : cfg->if_mtu; + slirp->if_mru = cfg->if_mru == 0 ? IF_MRU_DEFAULT : cfg->if_mru; + slirp->disable_host_loopback = cfg->disable_host_loopback; + slirp->enable_emu = cfg->enable_emu; + + if (cfg->version >= 2) { + slirp->outbound_addr = cfg->outbound_addr; + slirp->outbound_addr6 = cfg->outbound_addr6; + } else { + slirp->outbound_addr = NULL; + slirp->outbound_addr6 = NULL; } - if (bootfile) { - slirp->bootp_filename = strdup(bootfile); + + if (cfg->version >= 3) { + slirp->disable_dns = cfg->disable_dns; + } else { + slirp->disable_dns = false; } - slirp->vdhcp_startaddr = vdhcp_start; - slirp->vnameserver_addr = vnameserver; - if (vdnssearch) { - translate_dnssearch(slirp, vdnssearch); + if (cfg->version >= 4) { + slirp->disable_dhcp = cfg->disable_dhcp; + } else { + slirp->disable_dhcp = false; } - slirp->opaque = opaque; - slirp->logfn = logfn; + if (slirp->cfg_version >= 4 && slirp->cb->init_completed) { + slirp->cb->init_completed(slirp, slirp->opaque); + } - QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry); + if (cfg->version >= 5) { + slirp->mfr_id = cfg->mfr_id; + memcpy(slirp->oob_eth_addr, cfg->oob_eth_addr, ETH_ALEN); + } else { + slirp->mfr_id = 0; + memset(slirp->oob_eth_addr, 0, ETH_ALEN); + } + ip6_post_init(slirp); return slirp; } +Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork, + struct in_addr vnetmask, struct in_addr vhost, + bool in6_enabled, struct in6_addr vprefix_addr6, + uint8_t vprefix_len, struct in6_addr vhost6, + const char *vhostname, const char *tftp_server_name, + const char *tftp_path, const char *bootfile, + struct in_addr vdhcp_start, struct in_addr vnameserver, + struct in6_addr vnameserver6, const char **vdnssearch, + const char *vdomainname, const SlirpCb *callbacks, + void *opaque) +{ + SlirpConfig cfg; + memset(&cfg, 0, sizeof(cfg)); + cfg.version = 1; + cfg.restricted = restricted; + cfg.in_enabled = in_enabled; + cfg.vnetwork = vnetwork; + cfg.vnetmask = vnetmask; + cfg.vhost = vhost; + cfg.in6_enabled = in6_enabled; + cfg.vprefix_addr6 = vprefix_addr6; + cfg.vprefix_len = vprefix_len; + cfg.vhost6 = vhost6; + cfg.vhostname = vhostname; + cfg.tftp_server_name = tftp_server_name; + cfg.tftp_path = tftp_path; + cfg.bootfile = bootfile; + cfg.vdhcp_start = vdhcp_start; + cfg.vnameserver = vnameserver; + cfg.vnameserver6 = vnameserver6; + cfg.vdnssearch = vdnssearch; + cfg.vdomainname = vdomainname; + return slirp_new(&cfg, callbacks, opaque); +} + void slirp_cleanup(Slirp *slirp) { - struct ex_list *ex_ptr; + struct gfwd_list *e, *next; - QTAILQ_REMOVE(&slirp_instances, slirp, entry); + for (e = slirp->guestfwd_list; e; e = next) { + next = e->ex_next; + free(e->ex_exec); +// free(e->ex_unix); + free(e); + } ip_cleanup(slirp); + ip6_cleanup(slirp); m_cleanup(slirp); + tftp_cleanup(slirp); - while (slirp->exec_list != NULL) { - ex_ptr = slirp->exec_list->ex_next; - if (slirp->exec_list->ex_pty != 3) { - free((void*)slirp->exec_list->ex_exec); - } - free(slirp->exec_list); - slirp->exec_list = ex_ptr; - } - + free(slirp->vdomainname); free(slirp->tftp_prefix); + free(slirp->tftp_server_name); free(slirp->bootp_filename); free(slirp); } -#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) +#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) -static void slirp_update_timeout(uint32_t *timeout) +static void slirp_update_timeout(Slirp *slirp, uint32_t *timeout) { - Slirp *slirp; uint32_t t; if (*timeout <= TIMEOUT_FAST) { @@ -299,378 +768,361 @@ static void slirp_update_timeout(uint32_t *timeout) /* If we have tcp timeout with slirp, then we will fill @timeout with * more precise value. */ - QTAILQ_FOREACH(slirp, &slirp_instances, entry) { - if (slirp->time_fasttimo) { - *timeout = TIMEOUT_FAST; - return; - } - if (slirp->do_slowtimo) { - t = MIN(TIMEOUT_SLOW, t); - } + if (slirp->time_fasttimo) { + *timeout = TIMEOUT_FAST; + return; + } + if (slirp->do_slowtimo) { + t = MIN(TIMEOUT_SLOW, t); } *timeout = t; } -void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, - fd_set *xfds, uint32_t *timeout) +void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout, + SlirpAddPollCb add_poll, void *opaque) { - Slirp *slirp; struct socket *so, *so_next; - int nfds; - - if (QTAILQ_EMPTY(&slirp_instances)) { - return; - } - - /* fail safe */ - global_readfds = NULL; - global_writefds = NULL; - global_xfds = NULL; - nfds = *pnfds; /* * First, TCP sockets */ - QTAILQ_FOREACH(slirp, &slirp_instances, entry) { + /* + * *_slowtimo needs calling if there are IP fragments + * in the fragment queue, or there are TCP connections active + */ + slirp->do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) || + (&slirp->ipq.ip_link != slirp->ipq.ip_link.next)); + + for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) { + int events = 0; + + so_next = so->so_next; + + so->pollfds_idx = -1; + /* - * *_slowtimo needs calling if there are IP fragments - * in the fragment queue, or there are TCP connections active + * See if we need a tcp_fasttimo */ - slirp->do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) || - (&slirp->ipq.ip_link != slirp->ipq.ip_link.next)); + if (slirp->time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) { + slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */ + } - for (so = slirp->tcb.so_next; so != &slirp->tcb; - so = so_next) { - so_next = so->so_next; + /* + * 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; + } - /* - * See if we need a tcp_fasttimo - */ - if (slirp->time_fasttimo == 0 && - so->so_tcpcb->t_flags & TF_DELACK) { - slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */ - } + /* + * Set for reading sockets which are accepting + */ + if (so->so_state & SS_FACCEPTCONN) { + so->pollfds_idx = add_poll( + so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque); + continue; + } - /* - * 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 writing sockets which are connecting + */ + if (so->so_state & SS_ISFCONNECTING) { + so->pollfds_idx = + add_poll(so->s, SLIRP_POLL_OUT | SLIRP_POLL_ERR, opaque); + 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 if we are connected, can send more, and + * we have something to send + */ + if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) { + events |= SLIRP_POLL_OUT | SLIRP_POLL_ERR; + } - /* - * 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 reading (and urgent data) if we are connected, can + * receive more, and we have room for it. + * + * If sb is already half full, we will wait for the guest to consume it, + * and notify again in sbdrop() when the sb becomes less than half full. + */ + if (CONN_CANFRCV(so) && + (so->so_snd.sb_cc < (so->so_snd.sb_datalen / 2))) { + events |= SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR | + SLIRP_POLL_PRI; + } - /* - * 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); - } + if (events) { + so->pollfds_idx = add_poll(so->s, events, opaque); + } + } - /* - * 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 = slirp->udb.so_next; so != &slirp->udb; so = so_next) { + so_next = so->so_next; + + so->pollfds_idx = -1; + + /* + * See if it's timed out + */ + if (so->so_expire) { + if (so->so_expire <= curtime) { + udp_detach(so); + continue; + } else { + slirp->do_slowtimo = true; /* Let socket expire */ } } /* - * UDP sockets + * 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 ?) */ - for (so = slirp->udb.so_next; so != &slirp->udb; - so = so_next) { - so_next = so->so_next; + if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) { + so->pollfds_idx = add_poll( + so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque); + } + } - /* - * See if it's timed out - */ - if (so->so_expire) { - if (so->so_expire <= curtime) { - udp_detach(so); - continue; - } else { - slirp->do_slowtimo = true; /* Let socket expire */ - } - } + /* + * ICMP sockets + */ + for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) { + so_next = so->so_next; - /* - * 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); - } - } + so->pollfds_idx = -1; /* - * ICMP sockets + * See if it's timed out */ - for (so = slirp->icmp.so_next; so != &slirp->icmp; - so = so_next) { - so_next = so->so_next; - - /* - * See if it's timed out - */ - if (so->so_expire) { - if (so->so_expire <= curtime) { - icmp_detach(so); - continue; - } else { - slirp->do_slowtimo = true; /* Let socket expire */ - } + if (so->so_expire) { + if (so->so_expire <= curtime) { + icmp_detach(so); + continue; + } else { + slirp->do_slowtimo = true; /* Let socket expire */ } + } - if (so->so_state & SS_ISFCONNECTED) { - FD_SET(so->s, readfds); - UPD_NFDS(so->s); - } + if (so->so_state & SS_ISFCONNECTED) { + so->pollfds_idx = add_poll( + so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque); } } - slirp_update_timeout(timeout); - *pnfds = nfds; + + slirp_update_timeout(slirp, timeout); } -void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, - int select_error) +void slirp_pollfds_poll(Slirp *slirp, int select_error, + SlirpGetREventsCb get_revents, void *opaque) { - Slirp *slirp; struct socket *so, *so_next; int ret; - if (QTAILQ_EMPTY(&slirp_instances)) { - return; - } - - global_readfds = readfds; - global_writefds = writefds; - global_xfds = xfds; + curtime = slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS; - curtime = (u_int)(bx_pc_system.time_usec() / 1000); + /* + * See if anything has timed out + */ + if (slirp->time_fasttimo && + ((curtime - slirp->time_fasttimo) >= TIMEOUT_FAST)) { + tcp_fasttimo(slirp); + slirp->time_fasttimo = 0; + } + if (slirp->do_slowtimo && + ((curtime - slirp->last_slowtimo) >= TIMEOUT_SLOW)) { + ip_slowtimo(slirp); + tcp_slowtimo(slirp); + slirp->last_slowtimo = curtime; + } - QTAILQ_FOREACH(slirp, &slirp_instances, entry) { + /* + * Check sockets + */ + if (!select_error) { /* - * See if anything has timed out + * Check TCP sockets */ - if (slirp->time_fasttimo && - ((curtime - slirp->time_fasttimo) >= TIMEOUT_FAST)) { - tcp_fasttimo(slirp); - slirp->time_fasttimo = 0; - } - if (slirp->do_slowtimo && - ((curtime - slirp->last_slowtimo) >= TIMEOUT_SLOW)) { - ip_slowtimo(slirp); - tcp_slowtimo(slirp); - slirp->last_slowtimo = curtime; - } + for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) { + int revents; - /* - * Check sockets - */ - if (!select_error) { + so_next = so->so_next; + + revents = 0; + if (so->pollfds_idx != -1) { + revents = get_revents(so->pollfds_idx, opaque); + } + + if (so->so_state & SS_NOFDREF || so->s == -1) { + continue; + } + +#ifndef __APPLE__ /* - * Check TCP sockets + * Check for URG data + * This will soread as well, so no need to + * test for SLIRP_POLL_IN below if this succeeds. + * + * This is however disabled on MacOS, which apparently always + * reports data as PRI when it is the last data of the + * connection. We would then report it out of band, which the guest + * would most probably not be ready for. */ - for (so = slirp->tcb.so_next; so != &slirp->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) { + if (revents & SLIRP_POLL_PRI) { + ret = sorecvoob(so); + if (ret < 0) { + /* Socket error might have resulted in the socket being + * removed, do not try to do anything more with it. */ continue; } + } + /* + * Check sockets for reading + */ + else +#endif + if (revents & + (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR | SLIRP_POLL_PRI)) { /* - * 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 + * Check for incoming connections */ - 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); + 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)); - } + /* 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, (const char*) &ret, 0, 0); - if (ret < 0) { - /* XXXXX Must fix, zero bytes is a NOP */ - if (errno == EAGAIN || errno == EWOULDBLOCK || - errno == EINPROGRESS || errno == ENOTCONN) { - continue; - } - - /* else failed */ - so->so_state &= SS_PERSISTENT_MASK; - 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 - */ + if (ret < 0) { + /* Socket error might have resulted in the socket being + * removed, do not try to do anything more with it. */ + continue; } + } + /* + * Check sockets for writing + */ + if (!(so->so_state & SS_NOFDREF) && + (revents & (SLIRP_POLL_OUT | SLIRP_POLL_ERR))) { /* - * Probe a still-connecting, non-blocking socket - * to check if it's still alive + * Check for non-blocking, still-connecting sockets */ -#ifdef PROBE_CONN if (so->so_state & SS_ISFCONNECTING) { - ret = qemu_recv(so->s, &ret, 0, 0); + /* Connected */ + so->so_state &= ~SS_ISFCONNECTING; + ret = send(so->s, (const void *)&ret, 0, 0); if (ret < 0) { - /* XXX */ + /* XXXXX Must fix, zero bytes is a NOP */ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == ENOTCONN) { - continue; /* Still connecting, continue */ + continue; } /* else failed */ so->so_state &= SS_PERSISTENT_MASK; so->so_state |= SS_NOFDREF; + } + /* else so->so_state &= ~SS_ISFCONNECTING; */ - /* tcp_input will take care of it */ - } else { - ret = send(so->s, (const char*)&ret, 0, 0); - if (ret < 0) { - /* XXX */ - if (errno == EAGAIN || errno == EWOULDBLOCK || - errno == EINPROGRESS || errno == ENOTCONN) { - continue; - } - /* else failed */ - so->so_state &= SS_PERSISTENT_MASK; - so->so_state |= SS_NOFDREF; - } else { - so->so_state &= ~SS_ISFCONNECTING; - } - + /* + * Continue tcp_input + */ + tcp_input((struct mbuf *)NULL, sizeof(struct ip), so, + so->so_ffamily); + /* continue; */ + } else { + ret = sowrite(so); + if (ret > 0) { + /* Call tcp_output in case we need to send a window + * update to the guest, otherwise it will be stuck + * until it sends a window probe. */ + tcp_output(sototcpcb(so)); } - 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 = slirp->udb.so_next; so != &slirp->udb; - so = so_next) { - so_next = so->so_next; + /* + * Now UDP sockets. + * Incoming packets are sent straight away, they're not buffered. + * Incoming UDP data isn't buffered either. + */ + for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) { + int revents; - if (so->s != -1 && FD_ISSET(so->s, readfds)) { - sorecvfrom(so); - } - } + so_next = so->so_next; - /* - * Check incoming ICMP relies. - */ - for (so = slirp->icmp.so_next; so != &slirp->icmp; - so = so_next) { - so_next = so->so_next; + revents = 0; + if (so->pollfds_idx != -1) { + revents = get_revents(so->pollfds_idx, opaque); + } - if (so->s != -1 && FD_ISSET(so->s, readfds)) { - icmp_receive(so); - } + if (so->s != -1 && + (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) { + sorecvfrom(so); } } - if_start(slirp); + /* + * Check incoming ICMP relies. + */ + for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) { + int revents; + + so_next = so->so_next; + + revents = 0; + if (so->pollfds_idx != -1) { + revents = get_revents(so->pollfds_idx, opaque); + } + + if (so->s != -1 && + (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) { + if (so->so_type == IPPROTO_IPV6 || so->so_type == IPPROTO_ICMPV6) + icmp6_receive(so); + else + icmp_receive(so); + } + } } - /* 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; + if_start(slirp); } static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) { - struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN); - uint8_t arp_reply[max(ETH_HLEN + sizeof(struct arphdr), 64)]; - struct ethhdr *reh = (struct ethhdr *)arp_reply; - struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN); + const struct slirp_arphdr *ah = + (const struct slirp_arphdr *)(pkt + ETH_HLEN); + uint8_t arp_reply[MAX(2 + ETH_HLEN + sizeof(struct slirp_arphdr), 2 + 64)]; + struct ethhdr *reh = (struct ethhdr *)(arp_reply + 2); + struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_reply + 2 + ETH_HLEN); int ar_op; - struct ex_list *ex_ptr; + struct gfwd_list *ex_ptr; + + if (!slirp->in_enabled) { + return; + } + + if (pkt_len < (int)(ETH_HLEN + sizeof(struct slirp_arphdr))) { + return; /* packet too short */ + } ar_op = ntohs(ah->ar_op); switch(ar_op) { @@ -686,7 +1138,9 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) if (ah->ar_tip == slirp->vnameserver_addr.s_addr || ah->ar_tip == slirp->vhost_addr.s_addr) goto arp_ok; - for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + /* TODO: IPv6 */ + for (ex_ptr = slirp->guestfwd_list; ex_ptr; + ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_addr.s_addr == ah->ar_tip) goto arp_ok; } @@ -711,7 +1165,7 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) rah->ar_sip = ah->ar_tip; memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN); rah->ar_tip = ah->ar_sip; - slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply)); + slirp_send_packet_all(slirp, arp_reply + 2, sizeof(arp_reply) - 2); } break; case ARPOP_REPLY: @@ -730,7 +1184,7 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) if (pkt_len < ETH_HLEN) return; - proto = ntohs(*(uint16_t *)(pkt + 12)); + proto = (((uint16_t)pkt[12]) << 8) + pkt[13]; switch(proto) { case ETH_P_ARP: arp_input(slirp, pkt, pkt_len); @@ -740,47 +1194,48 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) m = m_get(slirp); if (!m) return; - /* Note: we add to align the IP header */ - if (M_FREEROOM(m) < pkt_len + 2) { - m_inc(m, pkt_len + 2); + /* Note: we add 2 to align the IP header on 8 bytes despite the ethernet + * header, and add the margin for the tcpiphdr overhead */ + if (M_FREEROOM(m) < pkt_len + TCPIPHDR_DELTA + 2) { + m_inc(m, pkt_len + TCPIPHDR_DELTA + 2); } - m->m_len = pkt_len + 2; - memcpy(m->m_data + 2, pkt, pkt_len); + m->m_len = pkt_len + TCPIPHDR_DELTA + 2; + memcpy(m->m_data + TCPIPHDR_DELTA + 2, pkt, pkt_len); - m->m_data += 2 + ETH_HLEN; - m->m_len -= 2 + ETH_HLEN; + m->m_data += TCPIPHDR_DELTA + 2 + ETH_HLEN; + m->m_len -= TCPIPHDR_DELTA + 2 + ETH_HLEN; if (proto == ETH_P_IP) { - ip_input(m); - } else { - BX_ERROR(("IPv6 packet not supported yet")); + ip_input(m); + } else if (proto == ETH_P_IPV6) { + ip6_input(m); } break; + + case ETH_P_NCSI: + ncsi_input(slirp, pkt, pkt_len); + break; + default: break; } } -/* Output the IP packet to the ethernet device. Returns 0 if the packet must be - * re-queued. +/* Prepare the IPv4 packet to be sent to the ethernet device. Returns 1 if no + * packet should be sent, 0 if the packet must be re-queued, 2 if the packet + * is ready to go. */ -int if_encap(Slirp *slirp, struct mbuf *ifm) +static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh, + uint8_t ethaddr[ETH_ALEN]) { - uint8_t buf[1600]; - struct ethhdr *eh = (struct ethhdr *)buf; - uint8_t ethaddr[ETH_ALEN]; const struct ip *iph = (const struct ip *)ifm->m_data; - if (ifm->m_len + ETH_HLEN > (int)sizeof(buf)) { - return 1; - } - if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) { - uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)]; - struct ethhdr *reh = (struct ethhdr *)arp_req; - struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN); + uint8_t arp_req[2 + ETH_HLEN + sizeof(struct slirp_arphdr)]; + struct ethhdr *reh = (struct ethhdr *)(arp_req + 2); + struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_req + 2 + ETH_HLEN); - if (!ifm->arp_requested) { + if (!ifm->resolution_requested) { /* If the client addr is not known, send an ARP request */ memset(reh->h_dest, 0xff, ETH_ALEN); memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4); @@ -805,23 +1260,93 @@ int if_encap(Slirp *slirp, struct mbuf *ifm) /* target IP */ rah->ar_tip = iph->ip_dst.s_addr; slirp->client_ipaddr = iph->ip_dst; - slirp_output(slirp->opaque, arp_req, sizeof(arp_req)); - ifm->arp_requested = true; + slirp_send_packet_all(slirp, arp_req + 2, sizeof(arp_req) - 2); + ifm->resolution_requested = true; /* Expire request and drop outgoing packet after 1 second */ - ifm->expiration_date = (bx_pc_system.time_usec() + 1000000ULL) * 1000ULL; + ifm->expiration_date = + slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL; } return 0; } else { - memcpy(eh->h_dest, ethaddr, ETH_ALEN); memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4); /* XXX: not correct */ memcpy(&eh->h_source[2], &slirp->vhost_addr, 4); eh->h_proto = htons(ETH_P_IP); - memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len); - slirp_output(slirp->opaque, buf, ifm->m_len + ETH_HLEN); + + /* Send this */ + return 2; + } +} + +/* Prepare the IPv6 packet to be sent to the ethernet device. Returns 1 if no + * packet should be sent, 0 if the packet must be re-queued, 2 if the packet + * is ready to go. + */ +static int if_encap6(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh, + uint8_t ethaddr[ETH_ALEN]) +{ + const struct ip6 *ip6h = mtod(ifm, const struct ip6 *); + if (!ndp_table_search(slirp, ip6h->ip_dst, ethaddr)) { + if (!ifm->resolution_requested) { + ndp_send_ns(slirp, ip6h->ip_dst); + ifm->resolution_requested = true; + ifm->expiration_date = + slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL; + } + return 0; + } else { + eh->h_proto = htons(ETH_P_IPV6); + in6_compute_ethaddr(ip6h->ip_src, eh->h_source); + + /* Send this */ + return 2; + } +} + +/* Output the IP packet to the ethernet device. Returns 0 if the packet must be + * re-queued. + */ +int if_encap(Slirp *slirp, struct mbuf *ifm) +{ + uint8_t buf[IF_MTU_MAX + 100]; + struct ethhdr *eh = (struct ethhdr *)(buf + 2); + uint8_t ethaddr[ETH_ALEN]; + const struct ip *iph = (const struct ip *)ifm->m_data; + int ret; + char ethaddr_str[ETH_ADDRSTRLEN]; + + if (ifm->m_len + ETH_HLEN > (int)sizeof(buf) - 2) { return 1; } + + switch (iph->ip_v) { + case IPVERSION: + ret = if_encap4(slirp, ifm, eh, ethaddr); + if (ret < 2) { + return ret; + } + break; + + case IP6VERSION: + ret = if_encap6(slirp, ifm, eh, ethaddr); + if (ret < 2) { + return ret; + } + break; + + default: + slirplog_error("unknown protocol"); + } + + memcpy(eh->h_dest, ethaddr, ETH_ALEN); + DEBUG_ARG("src = %s", slirp_ether_ntoa(eh->h_source, ethaddr_str, + sizeof(ethaddr_str))); + DEBUG_ARG("dst = %s", slirp_ether_ntoa(eh->h_dest, ethaddr_str, + sizeof(ethaddr_str))); + memcpy(buf + 2 + sizeof(struct ethhdr), ifm->m_data, ifm->m_len); + slirp_send_packet_all(slirp, buf + 2, ifm->m_len + ETH_HLEN); + return 1; } /* Drop host forwarding rule, return 0 if found. */ @@ -838,9 +1363,12 @@ int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, addr_len = sizeof(addr); if ((so->so_state & SS_HOSTFWD) && getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 && + addr_len == sizeof(addr) && + addr.sin_family == AF_INET && addr.sin_addr.s_addr == host_addr.s_addr && addr.sin_port == port) { - close(so->s); + so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); + closesocket(so->s); sofree(so); return 0; } @@ -867,39 +1395,184 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, return 0; } -int slirp_add_exec(Slirp *slirp, int do_pty, const void *args, - struct in_addr *guest_addr, int guest_port) +int slirp_remove_hostxfwd(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + int flags) +{ + struct socket *so; + struct socket *head = (flags & SLIRP_HOSTFWD_UDP ? &slirp->udb : &slirp->tcb); + struct sockaddr_storage addr; + socklen_t addr_len; + + for (so = head->so_next; so != head; so = so->so_next) { + addr_len = sizeof(addr); + if ((so->so_state & SS_HOSTFWD) && + getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 && + sockaddr_equal(&addr, (const struct sockaddr_storage *) haddr)) { + so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); + closesocket(so->s); + sofree(so); + return 0; + } + } + + return -1; +} + +int slirp_add_hostxfwd(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + const struct sockaddr *gaddr, socklen_t gaddrlen, + int flags) +{ + struct sockaddr_in gdhcp_addr; + int fwd_flags = SS_HOSTFWD; + + if (flags & SLIRP_HOSTFWD_V6ONLY) + fwd_flags |= SS_HOSTFWD_V6ONLY; + + if (gaddr->sa_family == AF_INET) { + const struct sockaddr_in *gaddr_in = (const struct sockaddr_in *) gaddr; + + if (gaddrlen < sizeof(struct sockaddr_in)) { + errno = EINVAL; + return -1; + } + + if (!gaddr_in->sin_addr.s_addr) { + gdhcp_addr = *gaddr_in; + gdhcp_addr.sin_addr = slirp->vdhcp_startaddr; + gaddr = (struct sockaddr *) &gdhcp_addr; + gaddrlen = sizeof(gdhcp_addr); + } + } else { + if (gaddrlen < sizeof(struct sockaddr_in6)) { + errno = EINVAL; + return -1; + } + + /* + * Libslirp currently only provides a stateless DHCPv6 server, thus + * we can't translate "addr-any" to the guest here. Instead, we defer + * performing the translation to when it's needed. See + * soassign_guest_addr_if_needed(). + */ + } + + if (flags & SLIRP_HOSTFWD_UDP) { + if (!udpx_listen(slirp, haddr, haddrlen, + gaddr, gaddrlen, + fwd_flags)) + return -1; + } else { + if (!tcpx_listen(slirp, haddr, haddrlen, + gaddr, gaddrlen, + fwd_flags)) + return -1; + } + return 0; +} + +/* TODO: IPv6 */ +static bool check_guestfwd(Slirp *slirp, struct in_addr *guest_addr, + int guest_port) { + struct gfwd_list *tmp_ptr; + if (!guest_addr->s_addr) { guest_addr->s_addr = slirp->vnetwork_addr.s_addr | - (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr); + (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr); } if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) != - slirp->vnetwork_addr.s_addr || + slirp->vnetwork_addr.s_addr || guest_addr->s_addr == slirp->vhost_addr.s_addr || guest_addr->s_addr == slirp->vnameserver_addr.s_addr) { + return false; + } + + /* check if the port is "bound" */ + for (tmp_ptr = slirp->guestfwd_list; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { + if (guest_port == tmp_ptr->ex_fport && + guest_addr->s_addr == tmp_ptr->ex_addr.s_addr) + return false; + } + + return true; +} + +int slirp_add_exec(Slirp *slirp, const char *cmdline, + struct in_addr *guest_addr, int guest_port) +{ + if (!check_guestfwd(slirp, guest_addr, guest_port)) { + return -1; + } + + add_exec(&slirp->guestfwd_list, cmdline, *guest_addr, htons(guest_port)); + return 0; +} + +int slirp_add_unix(Slirp *slirp, const char *unixsock, + struct in_addr *guest_addr, int guest_port) +{ +#ifndef _WIN32 + if (!check_guestfwd(slirp, guest_addr, guest_port)) { + return -1; + } + + add_unix(&slirp->guestfwd_list, unixsock, *guest_addr, htons(guest_port)); + return 0; +#else + return -1; +#endif +} + +int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque, + struct in_addr *guest_addr, int guest_port) +{ + if (!check_guestfwd(slirp, guest_addr, guest_port)) { return -1; } - return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr, - htons(guest_port)); + + add_guestfwd(&slirp->guestfwd_list, write_cb, opaque, *guest_addr, + htons(guest_port)); + return 0; +} + +int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr, + int guest_port) +{ + return remove_guestfwd(&slirp->guestfwd_list, guest_addr, + htons(guest_port)); } -ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) +slirp_ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) { - if (so->s == -1 && so->extra) { - Slirp *slirp = so->slirp; - BX_ERROR(("slirp_send(): so->extra not supported")); + if (so->s == -1 && so->guestfwd) { + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + so->guestfwd->write_cb(buf, len, so->guestfwd->opaque); return len; } - return send(so->s, (const char*)buf, len, flags); + if (so->s == -1) { + /* + * This should in theory not happen but it is hard to be + * sure because some code paths will end up with so->s == -1 + * on a failure but don't dispose of the struct socket. + * Check specifically, so we don't pass -1 to send(). + */ + errno = EBADF; + return -1; + } + + return send(so->s, buf, len, flags); } -static struct socket * -slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port) +struct socket *slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, + int guest_port) { struct socket *so; + /* TODO: IPv6 */ for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) { if (so->so_faddr.s_addr == guest_addr.s_addr && htons(so->so_fport) == guest_port) { @@ -922,6 +1595,8 @@ size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr, } if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2)) { + /* If the sb is already half full, we will wait for the guest to consume it, + * and notify again in sbdrop() when the sb becomes less than half full. */ return 0; } @@ -943,9 +1618,67 @@ void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port, tcp_output(sototcpcb(so)); } -void slirp_warning(Slirp *slirp, const char *msg) +void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len) +{ + slirp_ssize_t ret; + + if (len < ETH_MINLEN) { + char tmp[ETH_MINLEN]; + memcpy(tmp, buf, len); + memset(tmp + len, 0, ETH_MINLEN - len); + + ret = slirp->cb->send_packet(tmp, ETH_MINLEN, slirp->opaque); + } else { + ret = slirp->cb->send_packet(buf, len, slirp->opaque); + } + + if (ret < 0) { + slirplog_error("Failed to send packet"); + } else if ((size_t)ret < len) { + DEBUG_ERROR("send_packet() didn't send all data: %ld < %lu", (long)ret, + (unsigned long)len); + } +} + +/* Bochs additions */ + +void slirp_set_logfn(void *slirp, void *logfn, uint8_t debug_switches) +{ + if (slirp && logfn) { + slirplog = (logfunctions*)logfn; + slirp_debug = debug_switches; + } +} + +void slirplog_error(const char *fmt, ...) +{ + va_list ap; + char msg[512]; + + if (slirplog) { + va_start(ap, fmt); + vsprintf(msg, fmt, ap); + va_end(ap); + slirplog->error("%s", msg); + } +} + +void slirplog_debug(const char *fmt, ...) +{ + va_list ap; + char msg[512]; + + if (slirplog) { + va_start(ap, fmt); + vsprintf(msg, fmt, ap); + va_end(ap); + slirplog->ldebug("%s", msg); + } +} + +const char *slirp_version_string(void) { - BX_ERROR(("%s",msg)); + return SLIRP_VERSION_STRING; } #endif diff --git a/bochs/iodev/network/slirp/slirp.h b/bochs/iodev/network/slirp/slirp.h index 031cb298ab..f3fe70bb15 100644 --- a/bochs/iodev/network/slirp/slirp.h +++ b/bochs/iodev/network/slirp/slirp.h @@ -1,196 +1,83 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ +#ifndef SLIRP_H +#define SLIRP_H -#ifndef __COMMON_H__ -#define __COMMON_H__ +#define SLIRP_VERSION_STRING "4.8.0" #ifdef __CYGWIN__ #define __USE_W32_SOCKETS #define _WIN32 #endif -#include "config.h" -#include "slirp_config.h" - -#ifdef _WIN32 - -#if !defined(_MSC_VER) -# include -#endif - -typedef char *caddr_t; - -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif -# include -# include -# include -# include - -#if defined(__CYGWIN__) && defined(_WIN64) -#undef FIONBIO -#define FIONBIO 0x8004667e -#undef FIONREAD -#define FIONREAD 0x4004667f -#endif - +#ifdef BX_PLUGGABLE +#include "bochs.h" #else -# define ioctlsocket ioctl -# define closesocket(s) close(s) -# if !defined(__HAIKU__) && !defined(__CYGWIN__) -# define O_BINARY 0 -# endif -#endif - -#include -#if defined(__OpenBSD__) || defined(__linux__) -#include -#include -#endif -#ifdef HAVE_SYS_BITYPES_H -# include +#include "config.h" #endif -#if !defined(_MSC_VER) - -#include +#ifdef _WIN32 -#ifdef HAVE_UNISTD_H -# include +/* as defined in sdkddkver.h */ +#ifdef _WIN32_WINNT +#if _WIN32_WINNT < 0x0601 +#undef _WIN32_WINNT #endif - #endif - -#ifdef HAVE_STDLIB_H -# include +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0601 /* Windows 7 */ #endif - -#include -#include - -#ifndef HAVE_MEMMOVE -#define memmove(x, y, z) bcopy(y, x, z) +/* reduces the number of implicitly included headers */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN #endif -#if TIME_WITH_SYS_TIME -# include -# include -#else -# ifdef HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif +#include +#include +#include +#include +#include -#ifdef HAVE_STRING_H -# include #else -# include +#define O_BINARY 0 #endif #ifndef _WIN32 #include -#endif - -#ifndef _WIN32 #include #include -#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 - -#include -#ifndef NO_UNIX_SOCKETS -#include -#endif -#include -#ifdef HAVE_SYS_SIGNAL_H -# include -#endif -#ifndef _WIN32 #include +#include #endif -#if defined(HAVE_SYS_IOCTL_H) -# include -#endif - -#ifdef HAVE_SYS_SELECT_H -# include +#ifdef __APPLE__ +#include #endif -#ifdef HAVE_SYS_WAIT_H -# include -#endif - -#ifdef HAVE_SYS_FILIO_H -# include -#endif - -#ifdef USE_PPP -#include -#endif - -#ifdef __STDC__ -#include -#else -#include -#endif - -#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 "compat.h" #include "debug.h" +#include "util.h" #include "libslirp.h" #include "ip.h" +#include "ip6.h" #include "tcp.h" #include "tcp_timer.h" #include "tcp_var.h" #include "tcpip.h" #include "udp.h" #include "ip_icmp.h" +#include "ip6_icmp.h" #include "mbuf.h" #include "sbuf.h" #include "socket.h" #include "if.h" #include "main.h" #include "misc.h" -#ifdef USE_PPP -#include "ppp/pppd.h" -#include "ppp/ppp.h" -#endif #include "bootp.h" #include "tftp.h" -#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 ETH_P_IPV6 0x86dd /* IP version 6 packet */ - #define ARPOP_REQUEST 1 /* ARP request */ #define ARPOP_REPLY 2 /* ARP reply */ @@ -200,11 +87,8 @@ struct ethhdr { unsigned short h_proto; /* packet type ID field */ }; -#if defined(_MSC_VER) -#pragma pack(push, 1) -#endif - -struct arphdr { +SLIRP_PACKED_BEGIN +struct slirp_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 */ @@ -214,55 +98,97 @@ struct arphdr { /* * Ethernet looks like this : This bit is variable sized however... */ - unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ - uint32_t ar_sip; /* sender IP address */ - unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ - uint32_t ar_tip; /* target IP address */ -} GCC_ATTRIBUTE((packed)); - -#if defined(_MSC_VER) -#pragma pack(pop) -#endif + uint8_t ar_sha[ETH_ALEN]; /* sender hardware address */ + uint32_t ar_sip; /* sender IP address */ + uint8_t ar_tha[ETH_ALEN]; /* target hardware address */ + uint32_t ar_tip; /* target IP address */ +} SLIRP_PACKED_END; #define ARP_TABLE_SIZE 16 typedef struct ArpTable { - struct arphdr table[ARP_TABLE_SIZE]; + struct slirp_arphdr table[ARP_TABLE_SIZE]; int next_victim; } ArpTable; -void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]); +/* Add a new ARP entry for the given addresses */ +void arp_table_add(Slirp *slirp, uint32_t ip_addr, + const uint8_t ethaddr[ETH_ALEN]); +/* Look for an ARP entry for the given IP address */ bool arp_table_search(Slirp *slirp, uint32_t ip_addr, uint8_t out_ethaddr[ETH_ALEN]); +struct ndpentry { + uint8_t eth_addr[ETH_ALEN]; /* sender hardware address */ + struct in6_addr ip_addr; /* sender IP address */ +}; + +#define NDP_TABLE_SIZE 16 + +typedef struct NdpTable { + struct ndpentry table[NDP_TABLE_SIZE]; + /* + * The table is a cache with old entries overwritten when the table fills. + * Preserve the first entry: it is the guest, which is needed for lazy + * hostfwd guest address assignment. + */ + struct in6_addr guest_in6_addr; + int next_victim; +} NdpTable; + +/* Add a new NDP entry for the given addresses */ +void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr, + uint8_t ethaddr[ETH_ALEN]); + +/* Look for an NDP entry for the given IPv6 address */ +bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr, + uint8_t out_ethaddr[ETH_ALEN]); + +/* Slirp configuration, specified by the application */ struct Slirp { - QTAILQ_ENTRY(Slirp) entry; - u_int time_fasttimo; - u_int last_slowtimo; + int cfg_version; + + unsigned time_fasttimo; + unsigned last_slowtimo; bool do_slowtimo; + bool in_enabled, in6_enabled; + /* virtual network configuration */ struct in_addr vnetwork_addr; struct in_addr vnetwork_mask; struct in_addr vhost_addr; + struct in6_addr vprefix_addr6; + uint8_t vprefix_len; + struct in6_addr vhost_addr6; + bool disable_dhcp; /* slirp will not reply to any DHCP requests */ struct in_addr vdhcp_startaddr; struct in_addr vnameserver_addr; + struct in6_addr vnameserver_addr6; struct in_addr client_ipaddr; char client_hostname[33]; int restricted; - struct ex_list *exec_list; + struct gfwd_list *guestfwd_list; + + int if_mtu; + int if_mru; + + bool disable_host_loopback; + + uint32_t mfr_id; + uint8_t oob_eth_addr[ETH_ALEN]; /* mbuf states */ - struct mbuf m_freelist, m_usedlist; + struct slirp_quehead m_freelist; + struct slirp_quehead m_usedlist; int mbuf_alloced; /* if states */ - 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 */ + struct slirp_quehead if_fastq; /* fast queue (for interactive data) */ + struct slirp_quehead if_batchq; /* queue for non-interactive data */ bool if_start_busy; /* avoid if_start recursion */ /* ip states */ @@ -274,6 +200,7 @@ struct Slirp { char *bootp_filename; size_t vdnssearch_len; uint8_t *vdnssearch; + char *vdomainname; /* tcp states */ struct socket tcb; @@ -292,110 +219,191 @@ struct Slirp { /* tftp states */ char *tftp_prefix; struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; + char *tftp_server_name; ArpTable arp_table; + NdpTable ndp_table; - void *opaque; - void *logfn; -}; + void *ra_timer; -extern Slirp *slirp_instance; + bool enable_emu; -#ifndef NULL -#define NULL (void *)0 -#endif + const SlirpCb *cb; + void *opaque; -#ifndef FULL_BOLT + struct sockaddr_in *outbound_addr; + struct sockaddr_in6 *outbound_addr6; + bool disable_dns; /* slirp will not redirect/serve any DNS packet */ +}; + +/* + * Send one packet from each session. + * If there are packets on the fastq, they are sent FIFO, before + * everything else. Then we choose the first packet from each + * batchq session (socket) and send it. + * For example, if there are 3 ftp sessions 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. + */ void if_start(Slirp *); -#else -void if_start(struct ttys *); -#endif -#ifndef HAVE_STRERROR - char *strerror(int error); -#endif +/* Get the address of the DNS server on the host side */ +int get_dns_addr(struct in_addr *pdns_addr); -#ifndef HAVE_INDEX - char *index(const char *, int); -#endif +/* Get the IPv6 address of the DNS server on the host side */ +int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id); -#ifndef HAVE_GETHOSTID - long gethostid(void); -#endif +/* ncsi.c */ -void slirp_warning(Slirp *, const char *); +/* Process NCSI packet coming from the guest */ +void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len); #ifndef _WIN32 #include #endif -#define DEFAULT_BAUD 115200 +/* Whether we should send TCP keepalive packets */ +extern bool slirp_do_keepalive; -#define SO_OPTIONS DO_KEEPALIVE #define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL) /* dnssearch.c */ +/* Translate from vdnssearch in configuration, into Slirp */ int translate_dnssearch(Slirp *s, const char ** names); /* cksum.c */ +/* Compute the checksum of the mbuf */ int cksum(struct mbuf *m, int len); +/* Compute the checksum of the mbuf which contains an IPv6 packet */ +int ip6_cksum(struct mbuf *m); /* if.c */ +/* Called from slirp_new */ void if_init(Slirp *); +/* Queue packet into an output queue (fast or batch), for sending to the guest */ void if_output(struct socket *, struct mbuf *); /* ip_input.c */ +/* Called from slirp_new */ void ip_init(Slirp *); +/* Called from slirp_cleanup */ void ip_cleanup(Slirp *); +/* Process IPv4 packet coming from the guest */ void ip_input(struct mbuf *); +/* + * IP timer processing; + * if a timer expires on a reassembly + * queue, discard it. + */ void ip_slowtimo(Slirp *); -void ip_stripoptions(struct mbuf *, struct mbuf *); +/* + * Strip out IP options, at higher + * level protocol in the kernel. + */ +void ip_stripoptions(struct mbuf *); /* ip_output.c */ +/* Send IPv4 packet to the guest */ int ip_output(struct socket *, struct mbuf *); +/* ip6_input.c */ +/* Called from slirp_new, but after other initialization */ +void ip6_post_init(Slirp *); +/* Called from slirp_cleanup */ +void ip6_cleanup(Slirp *); +/* Process IPv6 packet coming from the guest */ +void ip6_input(struct mbuf *); + +/* ip6_output */ +/* Send IPv6 packet to the guest */ +int ip6_output(struct socket *, struct mbuf *, int fast); + /* tcp_input.c */ -void tcp_input(struct mbuf *, int, struct socket *); -int tcp_mss(struct tcpcb *, u_int); +/* Process TCP datagram coming from the guest */ +void tcp_input(struct mbuf *, int, struct socket *, unsigned short af); +/* Determine a reasonable value for maxseg size */ +int tcp_mss(struct tcpcb *, unsigned offer); /* tcp_output.c */ +/* Send TCP datagram to the guest */ int tcp_output(struct tcpcb *); +/* Start/restart persistence timer */ void tcp_setpersist(struct tcpcb *); /* tcp_subr.c */ +/* Called from slirp_new */ void tcp_init(Slirp *); +/* Called from slirp_cleanup */ void tcp_cleanup(Slirp *); +/* + * 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. + */ void tcp_template(struct tcpcb *); -void tcp_respond(struct tcpcb *, struct tcpiphdr *, struct mbuf *, tcp_seq, tcp_seq, int); +/* + * Send a single message to the TCP at address specified by + * the given TCP/IP header. + */ +void tcp_respond(struct tcpcb *, struct tcpiphdr *, + struct mbuf *, tcp_seq, tcp_seq, int, unsigned short); +/* + * 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 *); -struct tcpcb * tcp_close(struct tcpcb *); +/* + * Close a TCP control block: + * discard all space held by the tcp + * discard internet protocol block + * wake up any sleepers + */ +struct tcpcb *tcp_close(struct tcpcb *); +/* The Internet socket got closed, tell the guest */ void tcp_sockclosed(struct tcpcb *); -int tcp_fconnect(struct socket *); +/* + * Connect to a host on the Internet + * Called by tcp_input + */ +int tcp_fconnect(struct socket *, unsigned short af); +/* Accept the connection from the Internet, and connect to the guest */ void tcp_connect(struct socket *); -int tcp_attach(struct socket *); +/* Attach a TCPCB to a socket */ +void tcp_attach(struct socket *); +/* * Return TOS according to the ports */ uint8_t tcp_tos(struct socket *); +/* + * We received a packet from the guest. + * + * 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 + */ int tcp_emu(struct socket *, struct mbuf *); +/* Configure the socket, now that the guest completed accepting the connection */ int tcp_ctl(struct socket *); +/* + * 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); -#ifdef USE_PPP -#define MIN_MRU MINMRU -#define MAX_MRU MAXMRU -#else -#define MIN_MRU 128 -#define MAX_MRU 16384 -#endif +/* Find the socket for the guest address and port */ +struct socket *slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, + int guest_port); -#ifndef min -#define min(x,y) ((x) < (y) ? (x) : (y)) -#endif -#ifndef max -#define max(x,y) ((x) > (y) ? (x) : (y)) -#endif +/* Send a frame to the virtual Ethernet board, i.e. call the application send_packet callback */ +void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len); -#ifdef _WIN32 -#undef errno -#define errno (WSAGetLastError()) -#endif +/* Create a new timer, i.e. call the application timer_new callback */ +void *slirp_timer_new(Slirp *slirp, SlirpTimerId id, void *cb_opaque); + +/* Bochs addition */ +void slirplog_error(const char *fmt, ...) BX_CPP_AttrPrintf(1, 2); +void slirplog_debug(const char *fmt, ...) BX_CPP_AttrPrintf(1, 2); #endif diff --git a/bochs/iodev/network/slirp/slirp_config.h b/bochs/iodev/network/slirp/slirp_config.h deleted file mode 100644 index 43d29196f8..0000000000 --- a/bochs/iodev/network/slirp/slirp_config.h +++ /dev/null @@ -1,188 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// -/* - * User definable configuration options - */ - -/* 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 - -/* Define this if your compiler doesn't like prototypes */ -#ifndef __STDC__ -#define NO_PROTOTYPES -#endif - -/*********************************************************/ -/* - * Autoconf defined configuration options - * You shouldn't need to touch any of these - */ - -/* Ignore this */ -#undef DUMMY_PPP - -/* Define if you have unistd.h */ -#define HAVE_UNISTD_H - -/* Define if you have stdlib.h */ -#define HAVE_STDLIB_H - -/* Define if you have sys/ioctl.h */ -#undef HAVE_SYS_IOCTL_H -#ifndef _WIN32 -#define HAVE_SYS_IOCTL_H -#endif - -/* Define if you have sys/filio.h */ -#undef HAVE_SYS_FILIO_H -#ifdef __APPLE__ -#define HAVE_SYS_FILIO_H -#endif - -/* Define if you have strerror */ -#define HAVE_STRERROR - -/* Define if you have strdup() */ -#define HAVE_STRDUP - -/* Define according to how time.h should be included */ -#define TIME_WITH_SYS_TIME 0 -#undef HAVE_SYS_TIME_H - -/* Define if you have sys/bitypes.h */ -#undef HAVE_SYS_BITYPES_H - -/* 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 you have a POSIX.1 sys/wait.h */ -#undef HAVE_SYS_WAIT_H - -/* Define if you have sys/select.h */ -#undef HAVE_SYS_SELECT_H -#ifndef _WIN32 -#define HAVE_SYS_SELECT_H -#endif - -/* Define if you have strings.h */ -#define HAVE_STRING_H - -/* Define if you have arpa/inet.h */ -#undef HAVE_ARPA_INET_H -#ifndef _WIN32 -#define HAVE_ARPA_INET_H -#endif - -/* Define if you have sys/signal.h */ -#undef HAVE_SYS_SIGNAL_H - -/* Define if you have sys/stropts.h */ -#undef HAVE_SYS_STROPTS_H - -/* Define to whatever your compiler thinks inline should be */ -//#define inline inline - -/* Define to whatever your compiler thinks const should be */ -//#define const const - -/* Define if your compiler doesn't like prototypes */ -#undef NO_PROTOTYPES - -/* Define to sizeof(char) */ -#define SIZEOF_CHAR 1 - -/* Define to sizeof(short) */ -#define SIZEOF_SHORT 2 - -/* Define to sizeof(int) */ -#define SIZEOF_INT 4 - -/* Define to sizeof(char *) */ -#define SIZEOF_CHAR_P SIZEOF_INT_P - -/* Define if you have random() */ -#undef HAVE_RANDOM - -/* Define if you have srandom() */ -#undef HAVE_SRANDOM - -/* Define if you have inet_aton */ -#undef HAVE_INET_ATON -#ifndef _WIN32 -#define HAVE_INET_ATON -#endif - -/* Define if you have setenv */ -#undef HAVE_SETENV - -/* Define if you have index() */ -#define 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 */ -#define HAVE_GETHOSTID - -/* Define if you DON'T have unix-domain sockets */ -#undef NO_UNIX_SOCKETS -#ifdef _WIN32 -#define NO_UNIX_SOCKETS -#endif - -/* 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/bochs/iodev/network/slirp/socket.cc b/bochs/iodev/network/slirp/socket.cc index 777afd2f06..ed2a373f53 100644 --- a/bochs/iodev/network/slirp/socket.cc +++ b/bochs/iodev/network/slirp/socket.cc @@ -1,11 +1,6 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ #include "slirp.h" @@ -16,134 +11,166 @@ #ifdef __sun__ #include #endif +#ifdef __linux__ +#include +#endif static void sofcantrcvmore(struct socket *so); static void sofcantsendmore(struct socket *so); -struct socket * -solookup(struct socket *head, struct in_addr laddr, u_int lport, - struct in_addr faddr, u_int fport) +struct socket *solookup(struct socket **last, struct socket *head, + struct sockaddr_storage *lhost, + struct sockaddr_storage *fhost) { - 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; + struct socket *so = *last; + + /* Optimisation */ + if (so != head && sockaddr_equal(&(so->lhost.ss), lhost) && + (!fhost || sockaddr_equal(&so->fhost.ss, fhost))) { + return so; + } + + for (so = head->so_next; so != head; so = so->so_next) { + if (sockaddr_equal(&(so->lhost.ss), lhost) && + (!fhost || sockaddr_equal(&so->fhost.ss, fhost))) { + *last = so; + return so; + } + } + return (struct socket *)NULL; } /* * Create a new socket, initialise the fields * It is the responsibility of the caller to - * insque() it into the correct linked-list + * slirp_insque() it into the correct linked-list */ -struct socket * -socreate(Slirp *slirp) +struct socket *socreate(Slirp *slirp, int type) { - 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; - so->slirp = slirp; + struct socket *so = (struct socket *)malloc(sizeof(struct socket)); + if (so) { + memset(so, 0, sizeof(struct socket)); + so->so_type = type; + so->so_state = SS_NOFDREF; + so->s = -1; + so->s_aux = -1; + so->slirp = slirp; + so->pollfds_idx = -1; } - return(so); + + return so; } /* - * remque and free a socket, clobber cache + * Remove references to so from the given message queue. */ -void -sofree(struct socket *so) +static void soqfree(struct socket *so, struct slirp_quehead *qh) { - Slirp *slirp = so->slirp; - - if (so->so_emu==EMU_RSH && so->extra) { - sofree((struct socket*)so->extra); - so->extra=NULL; - } - if (so == slirp->tcp_last_so) { - slirp->tcp_last_so = &slirp->tcb; - } else if (so == slirp->udp_last_so) { - slirp->udp_last_so = &slirp->udb; - } else if (so == slirp->icmp_last_so) { - slirp->icmp_last_so = &slirp->icmp; - } - m_free(so->so_m); - - if(so->so_next && so->so_prev) - remque(so); /* crashes if so is not in a queue */ + struct mbuf *ifq; + + for (ifq = (struct mbuf *)qh->qh_link; (struct slirp_quehead *)ifq != qh; + ifq = ifq->m_next) { + if (ifq->m_so == so) { + struct mbuf *ifm; + ifq->m_so = NULL; + for (ifm = ifq->m_nextpkt; ifm != ifq; ifm = ifm->m_nextpkt) { + ifm->m_so = NULL; + } + } + } +} - free(so); +/* + * slirp_remque and free a socket, clobber cache + */ +void sofree(struct socket *so) +{ + Slirp *slirp = so->slirp; + + if (so->s_aux != -1) { + closesocket(so->s_aux); + } + + soqfree(so, &slirp->if_fastq); + soqfree(so, &slirp->if_batchq); + + if (so == slirp->tcp_last_so) { + slirp->tcp_last_so = &slirp->tcb; + } else if (so == slirp->udp_last_so) { + slirp->udp_last_so = &slirp->udb; + } else if (so == slirp->icmp_last_so) { + slirp->icmp_last_so = &slirp->icmp; + } + m_free(so->so_m); + + if(so->so_next && so->so_prev) + slirp_remque(so); /* crashes if so is not in a queue */ + + if (so->so_tcpcb) { + free(so->so_tcpcb); + } + free(so); } size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) { - int n, lss, total; - struct sbuf *sb = &so->so_snd; - int len = sb->sb_datalen - sb->sb_cc; - u_short mss = so->so_tcpcb->t_maxseg; - - DEBUG_CALL("sopreprbuf"); - DEBUG_ARG("so = %lx", (long )so); - - if (len <= 0) - return 0; - - iov[0].iov_base = sb->sb_wptr; - iov[1].iov_base = NULL; - iov[1].iov_len = 0; - if (sb->sb_wptr < sb->sb_rptr) { - iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; - /* Should never succeed, but... */ - if ((int)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 ((int)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 ((int)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 ((int)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; - } - } - if (np) - *np = n; - - return iov[0].iov_len + (n - 1) * iov[1].iov_len; + int n, lss, total; + struct sbuf *sb = &so->so_snd; + int len = sb->sb_datalen - sb->sb_cc; + int mss = so->so_tcpcb->t_maxseg; + + DEBUG_CALL("sopreprbuf"); + DEBUG_ARG("so = %p", so); + + if (len <= 0) + return 0; + + iov[0].iov_base = sb->sb_wptr; + iov[1].iov_base = NULL; + iov[1].iov_len = 0; + if (sb->sb_wptr < sb->sb_rptr) { + iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; + /* Should never succeed, but... */ + if ((int)iov[0].iov_len > len) + iov[0].iov_len = len; + if ((int)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 ((int)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 ((int)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 ((int)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 ((int)iov[0].iov_len > mss) + iov[0].iov_len -= iov[0].iov_len%mss; + n = 1; + } + } + if (np) + *np = n; + + return iov[0].iov_len + (n - 1) * iov[1].iov_len; } /* @@ -151,81 +178,100 @@ size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) * 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(struct socket *so) +int soread(struct socket *so) { - int n = 0, nn; - struct sbuf *sb = &so->so_snd; - struct iovec iov[2] = {NULL, 0}; - - 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 - */ - sopreprbuf(so, iov, &n); - -#ifdef HAVE_READV - nn = readv(so->s, (struct iovec *)iov, n); - DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); -#else - nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0); -#endif - if (nn <= 0) { - if (nn < 0 && (errno == EINTR || errno == EAGAIN)) - 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 == (int)iov[0].iov_len) { - int ret; - ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0); - if (ret > 0) - nn += ret; - } + int n = 0, nn; + size_t buf_len; + struct sbuf *sb = &so->so_snd; + struct iovec iov[2] = {NULL, 0}; + + DEBUG_CALL("soread"); + DEBUG_ARG("so = %p", so); + + /* + * No need to check if there's enough room to read. + * soread wouldn't have been called if there weren't + */ + buf_len = sopreprbuf(so, iov, &n); + assert(buf_len != 0); + + nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0); + if (nn <= 0) { + if (nn < 0 && (errno == EINTR || errno == EAGAIN)) + return 0; + else { + int err; + socklen_t elen = sizeof err; + struct sockaddr_storage addr; + struct sockaddr *paddr = (struct sockaddr *)&addr; + socklen_t alen = sizeof addr; + + err = errno; + if (nn == 0) { + int shutdown_wr = so->so_state & SS_FCANTSENDMORE; + + if (!shutdown_wr && getpeername(so->s, paddr, &alen) < 0) { + err = errno; + } else { + getsockopt(so->s, SOL_SOCKET, SO_ERROR, &err, &elen); + } + } - DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); -#endif + DEBUG_MISC(" --- soread() disconnected, nn = %d, errno = %d-%s", nn, + errno, strerror(errno)); + sofcantrcvmore(so); - /* 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; + if (err == ECONNABORTED || err == ECONNRESET || err == ECONNREFUSED || + err == ENOTCONN || err == EPIPE) { + tcp_drop(sototcpcb(so), err); + } else { + tcp_sockclosed(sototcpcb(so)); + } + return -1; + } + } + + /* + * 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 won't (shouldn't) happen, since it didn't happen above + */ + if (n == 2 && nn == (int)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(" ... read nn = %d bytes", nn); + + /* 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; } int soreadbuf(struct socket *so, const char *buf, int size) { int n, nn, copy = size; - struct sbuf *sb = &so->so_snd; - struct iovec iov[2] = {NULL, 0}; - - DEBUG_CALL("soreadbuf"); - 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 - */ - if ((int)sopreprbuf(so, iov, &n) < size) + struct sbuf *sb = &so->so_snd; + struct iovec iov[2] = {NULL, 0}; + + DEBUG_CALL("soreadbuf"); + DEBUG_ARG("so = %p", so); + + /* + * No need to check if there's enough room to read. + * soread wouldn't have been called if there weren't + */ + assert(size > 0); + if ((int)sopreprbuf(so, iov, &n) < size) goto err; nn = MIN((int)iov[0].iov_len, copy); @@ -241,16 +287,16 @@ int soreadbuf(struct socket *so, const char *buf, int size) done: /* Update fields */ - sb->sb_cc += size; - sb->sb_wptr += size; - if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) - sb->sb_wptr -= sb->sb_datalen; + sb->sb_cc += size; + sb->sb_wptr += size; + if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) + sb->sb_wptr -= sb->sb_datalen; return size; err: sofcantrcvmore(so); tcp_sockclosed(sototcpcb(so)); - fprintf(stderr, "soreadbuf buffer to small"); + slirplog_error("soreadbuf buffer to small"); return -1; } @@ -261,402 +307,611 @@ int soreadbuf(struct socket *so, const char *buf, int size) * so when OOB data arrives, we soread() it and everything * in the send buffer is sent as urgent data */ -void -sorecvoob(struct socket *so) +int sorecvoob(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; + struct tcpcb *tp = sototcpcb(so); + int ret; + + DEBUG_CALL("sorecvoob"); + DEBUG_ARG("so = %p", 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. + */ + ret = soread(so); + if (ret > 0) { + tp->snd_up = tp->snd_una + so->so_snd.sb_cc; + tp->t_force = 1; + tcp_output(tp); + tp->t_force = 0; + } + + return ret; } /* * Send urgent data * There's a lot duplicated code here, but... */ -int -sosendoob(struct socket *so) +int sosendoob(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 = (int)slirp_send(so, 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 = (int)slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ -#ifdef DEBUG - if (n != len) - DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); + struct sbuf *sb = &so->so_rcv; + char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ + + int n; + + DEBUG_CALL("sosendoob"); + DEBUG_ARG("so = %p", so); + DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); + + if (so->so_urgc > sizeof(buff)) + so->so_urgc = sizeof(buff); /* XXXX */ + + if (sb->sb_rptr < sb->sb_wptr) { + /* We can send it directly */ + n = (int)slirp_send(so, sb->sb_rptr, so->so_urgc, + (MSG_OOB)); /* |MSG_DONTWAIT)); */ + } else { + /* + * Since there's no sendv or sendtov like writev, + * we must copy all data to a linear buffer then + * send it all + */ + uint32_t urgc = so->so_urgc; /* Amount of room left in buff */ + int len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; + if (len > (int)urgc) { + len = urgc; + } + memcpy(buff, sb->sb_rptr, len); + urgc -= len; + if (urgc) { + /* We still have some room for the rest */ + n = sb->sb_wptr - sb->sb_data; + if (n > (int)urgc) { + n = urgc; + } + memcpy((buff + len), sb->sb_data, n); + len += n; + } + n = (int)slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ +#ifdef SLIRP_DEBUG + if (n != len) { + DEBUG_ERROR("Didn't send all data urgently XXXXX"); + } #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; + if (n < 0) { + return n; + } + so->so_urgc -= n; + DEBUG_MISC(" ---2 sent %d bytes urgent data, %d urgent bytes left", n, + so->so_urgc); - return n; + 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(struct socket *so) +int sowrite(struct socket *so) { - int n,nn; - struct sbuf *sb = &so->so_rcv; - 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 - */ - - iov[0].iov_base = sb->sb_rptr; - iov[1].iov_base = NULL; - iov[1].iov_len = 0; - if (sb->sb_rptr < sb->sb_wptr) { - iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; - /* Should never succeed, but... */ - if ((int)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 ((int)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 ((int)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 = (int)slirp_send(so, iov[0].iov_base, iov[0].iov_len,0); -#endif - /* This should never happen, but people tell me it does *shrug* */ - if (nn < 0 && (errno == EAGAIN || errno == EINTR)) - 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 == (int)iov[0].iov_len) { - int ret; - ret = (int)slirp_send(so, iov[1].iov_base, iov[1].iov_len,0); - if (ret > 0) - nn += ret; + int n,nn; + struct sbuf *sb = &so->so_rcv; + int len = sb->sb_cc; + struct iovec iov[2]; + + DEBUG_CALL("sowrite"); + DEBUG_ARG("so = %p", so); + + if (so->so_urgc) { + uint32_t expected = so->so_urgc; + if (sosendoob(so) < (int)expected) { + /* Treat a short write as a fatal error too, + * rather than continuing on and sending the urgent + * data as if it were non-urgent and leaving the + * so_urgc count wrong. + */ + goto err_disconnected; } - 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; + if (sb->sb_cc == 0) + return 0; + } + + /* + * No need to check if there's something to write, + * sowrite wouldn't have been called otherwise + */ + + iov[0].iov_base = sb->sb_rptr; + iov[1].iov_base = NULL; + iov[1].iov_len = 0; + if (sb->sb_rptr < sb->sb_wptr) { + iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; + /* Should never succeed, but... */ + if ((int)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 ((int)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 ((int)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 */ + + nn = (int)slirp_send(so, iov[0].iov_base, iov[0].iov_len,0); + /* This should never happen, but people tell me it does *shrug* */ + if (nn < 0 && (errno == EAGAIN || errno == EINTR)) + return 0; + + if (nn <= 0) { + goto err_disconnected; + } + + if (n == 2 && nn == (int)iov[0].iov_len) { + int ret; + ret = (int)slirp_send(so, iov[1].iov_base, iov[1].iov_len,0); + if (ret > 0) + nn += ret; + } + DEBUG_MISC(" ... wrote nn = %d bytes", nn); + + /* 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; + +err_disconnected: + DEBUG_MISC(" --- sowrite disconnected, so->so_state = %x, errno = %d", + so->so_state, errno); + sofcantsendmore(so); + tcp_sockclosed(sototcpcb(so)); + return -1; } /* * recvfrom() a UDP socket */ -void -sorecvfrom(struct socket *so) +void sorecvfrom(struct socket *so) { - struct sockaddr_in addr; - socklen_t addrlen = sizeof(struct sockaddr_in); + struct sockaddr_storage addr; + struct sockaddr_storage saddr, daddr; + socklen_t addrlen = sizeof(struct sockaddr_storage); + char buff[256]; + +#ifdef __linux__ + ssize_t size; + struct msghdr msg; + struct iovec iov; + char control[1024]; + + /* First look for errors */ + memset(&msg, 0, sizeof(msg)); + msg.msg_name = &saddr; + msg.msg_namelen = sizeof(saddr); + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + iov.iov_base = buff; + iov.iov_len = sizeof(buff); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + size = recvmsg(so->s, &msg, MSG_ERRQUEUE); + if (size >= 0) { + struct cmsghdr *cmsg; + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + + if (cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == IP_RECVERR) { + struct sock_extended_err *ee = + (struct sock_extended_err *) CMSG_DATA(cmsg); + + if (ee->ee_origin == SO_EE_ORIGIN_ICMP) { + /* Got an ICMP error, forward it */ + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *) SO_EE_OFFENDER(ee); + icmp_forward_error(so->so_m, ee->ee_type, ee->ee_code, + 0, NULL, &sin->sin_addr); + } + } + else if (cmsg->cmsg_level == IPPROTO_IPV6 && + cmsg->cmsg_type == IPV6_RECVERR) { + struct sock_extended_err *ee = + (struct sock_extended_err *) CMSG_DATA(cmsg); + + if (ee->ee_origin == SO_EE_ORIGIN_ICMP6) { + /* Got an ICMPv6 error, forward it */ + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *) SO_EE_OFFENDER(ee); + icmp6_forward_error(so->so_m, ee->ee_type, ee->ee_code, + &sin6->sin6_addr); + } + } + } + return; + } +#endif - DEBUG_CALL("sorecvfrom"); - DEBUG_ARG("so = %lx", (long)so); + DEBUG_CALL("sorecvfrom"); + DEBUG_ARG("so = %p", so); - if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ - char buff[256]; - int len; + if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ + int len; - len = recvfrom(so->s, buff, 256, 0, - (struct sockaddr *)&addr, &addrlen); - /* XXX Check if reply is "correct"? */ + 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; + if (len == -1 || len == 0) { + uint8_t code = ICMP_UNREACH_PORT; - if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; - else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; + if (errno == EHOSTUNREACH) + code = ICMP_UNREACH_HOST; + else if(errno == ENETUNREACH) + 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); + DEBUG_MISC(" udp icmp rx errno = %d-%s", errno,strerror(errno)); + icmp_send_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); + } else { + icmp_reflect(so->so_m); + so->so_m = NULL; /* Don't m_free() it again! */ + } + /* No need for this socket anymore, udp_detach it */ + udp_detach(so); + } else if (so->so_type == IPPROTO_ICMPV6) { /* This is a "ping" reply */ + int len; + + len = recvfrom(so->s, buff, 256, 0, (struct sockaddr *)&addr, &addrlen); + /* XXX Check if reply is "correct"? */ + + if (len == -1 || len == 0) { + uint8_t code = ICMP6_UNREACH_PORT; + + if (errno == EHOSTUNREACH) + code = ICMP6_UNREACH_ADDRESS; + else if (errno == ENETUNREACH) + code = ICMP6_UNREACH_NO_ROUTE; + + DEBUG_MISC(" udp icmp6 rx errno = %d-%s", errno, strerror(errno)); + icmp6_send_error(so->so_m, ICMP_UNREACH, code); + } else { + icmp6_reflect(so->so_m); so->so_m = NULL; /* 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; - int len; + } + /* No need for this socket anymore, udp_detach it */ + udp_detach(so); + } else { /* A "normal" UDP packet */ + struct mbuf *m; + int len; #ifdef _WIN32 - ULONG n; + unsigned long n; #else - int n; + int n; #endif - m = m_get(so->slirp); - if (!m) { - 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 ((int)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; - - if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; - else if(errno == ENETUNREACH) 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 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 */ + if (ioctlsocket(so->s, FIONREAD, &n) != 0) { + DEBUG_MISC(" ioctlsocket errno = %d-%s\n", errno, strerror(errno)); + return; + } + + m = m_get(so->slirp); + if (!m) { + return; + } + switch (so->so_ffamily) { + case AF_INET: + m->m_data += IF_MAXLINKHDR + sizeof(struct udpiphdr); + break; + case AF_INET6: + m->m_data += + IF_MAXLINKHDR + sizeof(struct ip6) + sizeof(struct udphdr); + break; + default: + slirplog_error("Unknown protocol"); + } + + /* + * 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)) { */ + + if ((int)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(" did recvfrom %d, errno = %d-%s", m->m_len, errno, + strerror(errno)); + if (m->m_len < 0) { + if (errno == ENOTCONN) { + /* + * UDP socket got burnt, e.g. by suspend on iOS. Tear it down + * and let it get re-created if the guest still needs it + */ + udp_detach(so); + } else { + /* Report error as ICMP */ + switch (so->so_lfamily) { + uint8_t code; + case AF_INET: + code = ICMP_UNREACH_PORT; + + if (errno == EHOSTUNREACH) { + code = ICMP_UNREACH_HOST; + } else if (errno == ENETUNREACH) { + code = ICMP_UNREACH_NET; + } + + DEBUG_MISC(" rx error, tx icmp ICMP_UNREACH:%i", code); + icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, + strerror(errno)); + break; + case AF_INET6: + code = ICMP6_UNREACH_PORT; + + if (errno == EHOSTUNREACH) { + code = ICMP6_UNREACH_ADDRESS; + } else if (errno == ENETUNREACH) { + code = ICMP6_UNREACH_NO_ROUTE; + } + + DEBUG_MISC(" rx error, tx icmp6 ICMP_UNREACH:%i", code); + icmp6_send_error(so->so_m, ICMP6_UNREACH, code); + break; + default: + slirplog_error("Unknown protocol"); + } + 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 this packet was destined for CTL_ADDR, + * make it look like that's where it came from + */ + saddr = addr; + sotranslate_in(so, &saddr); + + /* Perform lazy guest IP address resolution if needed. */ + if (so->so_state & SS_HOSTFWD) { + if (soassign_guest_addr_if_needed(so) < 0) { + DEBUG_MISC(" guest address not available yet"); + switch (so->so_lfamily) { + case AF_INET: + icmp_send_error(so->so_m, ICMP_UNREACH, + ICMP_UNREACH_HOST, 0, + "guest address not available yet"); + break; + case AF_INET6: + icmp6_send_error(so->so_m, ICMP6_UNREACH, + ICMP6_UNREACH_ADDRESS); + break; + default: + slirplog_error("Unknown protocol"); + } + m_free(m); + return; + } + } + daddr = so->lhost.ss; + + switch (so->so_ffamily) { + case AF_INET: + udp_output(so, m, (struct sockaddr_in *)&saddr, + (struct sockaddr_in *)&daddr, so->so_iptos); + break; + case AF_INET6: + udp6_output(so, m, (struct sockaddr_in6 *)&saddr, + (struct sockaddr_in6 *)&daddr); + break; + default: + slirplog_error("Unknown protocol"); + } + } /* rx error */ + } /* if ping packet */ } /* * sendto() a socket */ -int -sosendto(struct socket *so, struct mbuf *m) +int sosendto(struct socket *so, struct mbuf *m) { - Slirp *slirp = so->slirp; - 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 & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { - /* It's an alias */ - if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { - if (get_dns_addr(&addr.sin_addr) < 0) - addr.sin_addr = loopback_addr; - } else { - addr.sin_addr = loopback_addr; - } - } else - addr.sin_addr = so->so_faddr; - addr.sin_port = so->so_fport; - - DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr))); - - /* 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_PERSISTENT_MASK; - so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */ - return 0; + int ret; + struct sockaddr_storage addr; + + DEBUG_CALL("sosendto"); + DEBUG_ARG("so = %p", so); + DEBUG_ARG("m = %p", m); + + addr = so->fhost.ss; + DEBUG_CALL(" sendto()ing)"); + if (sotranslate_out(so, &addr) < 0) { + return -1; + } + + /* Don't care what port we get */ + ret = sendto(so->s, m->m_data, m->m_len, 0, (struct sockaddr *)&addr, + sockaddr_size(&addr)); + 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_PERSISTENT_MASK; + so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */ + return 0; } -/* - * Listen for incoming TCP connections - */ -struct socket * -tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, - u_int lport, int flags) +struct socket *tcpx_listen(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + const struct sockaddr *laddr, socklen_t laddrlen, + int flags) { - struct sockaddr_in addr; - struct socket *so; - int s, opt = 1; - socklen_t addrlen = sizeof(addr); - memset(&addr, 0, addrlen); - - DEBUG_CALL("tcp_listen"); - DEBUG_ARG("haddr = %x", haddr); - DEBUG_ARG("hport = %d", hport); - DEBUG_ARG("laddr = %x", laddr); - DEBUG_ARG("lport = %d", lport); - DEBUG_ARG("flags = %x", flags); - - so = socreate(slirp); - if (!so) { - 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, &slirp->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_PERSISTENT_MASK; - so->so_state |= (SS_FACCEPTCONN | flags); - so->so_lport = lport; /* Kept in network format */ - so->so_laddr.s_addr = laddr; /* Ditto */ - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = haddr; - addr.sin_port = hport; - - if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) || - (socket_set_fast_reuse(s) < 0) || - (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || - (listen(s,1) < 0)) { - int tmperrno = errno; /* Don't clobber the real reason we failed */ - - close(s); - sofree(so); - /* Restore the real errno */ + struct socket *so; + int s, opt = 1; + socklen_t addrlen; + + DEBUG_CALL("tcpx_listen"); + /* AF_INET6 addresses are bigger than AF_INET, so this is big enough. */ + char addrstr[INET6_ADDRSTRLEN]; + char portstr[6]; + int ret; + switch (haddr->sa_family) { + case AF_INET: + case AF_INET6: + ret = getnameinfo(haddr, haddrlen, addrstr, sizeof(addrstr), portstr, sizeof(portstr), NI_NUMERICHOST|NI_NUMERICSERV); + assert(ret == 0); + DEBUG_ARG("hfamily = INET"); + DEBUG_ARG("haddr = %s", addrstr); + DEBUG_ARG("hport = %s", portstr); + break; +#ifndef _WIN32 + case AF_UNIX: + DEBUG_ARG("hfamily = UNIX"); + DEBUG_ARG("hpath = %s", ((struct sockaddr_un *) haddr)->sun_path); + break; +#endif + default: + slirplog_error("Unknown protocol"); + } + switch (laddr->sa_family) { + case AF_INET: + case AF_INET6: + ret = getnameinfo(laddr, laddrlen, addrstr, sizeof(addrstr), portstr, sizeof(portstr), NI_NUMERICHOST|NI_NUMERICSERV); + assert(ret == 0); + DEBUG_ARG("laddr = %s", addrstr); + DEBUG_ARG("lport = %s", portstr); + break; + default: + slirplog_error("Unknown protocol"); + } + DEBUG_ARG("flags = %x", flags); + + /* + * SS_HOSTFWD sockets can be accepted multiple times, so they can't be + * SS_FACCEPTONCE. Also, SS_HOSTFWD connections can be accepted and + * immediately closed if the guest address isn't available yet, which is + * incompatible with the "accept once" concept. Correct code will never + * request both, so disallow their combination by assertion. + */ + assert(!((flags & SS_HOSTFWD) && (flags & SS_FACCEPTONCE))); + + so = socreate(slirp, IPPROTO_TCP); + + /* Don't tcp_attach... we don't need so_snd nor so_rcv */ + so->so_tcpcb = tcp_newtcpcb(so); + slirp_insque(so, &slirp->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_PERSISTENT_MASK; + so->so_state |= (SS_FACCEPTCONN | flags); + + sockaddr_copy(&so->lhost.sa, sizeof(so->lhost), laddr, laddrlen); + + s = slirp_socket(haddr->sa_family, SOCK_STREAM, 0); + if ((s < 0) || + (haddr->sa_family == AF_INET6 && slirp_socket_set_v6only(s, (flags & SS_HOSTFWD_V6ONLY) != 0) < 0) || + (slirp_socket_set_fast_reuse(s) < 0) || + (bind(s, haddr, haddrlen) < 0) || + (listen(s, 1) < 0)) { + int tmperrno = errno; /* Don't clobber the real reason we failed */ + if (s >= 0) { + closesocket(s); + } + sofree(so); + /* Restore the real errno */ #ifdef _WIN32 - WSASetLastError(tmperrno); + WSASetLastError(tmperrno); #else - errno = tmperrno; + errno = tmperrno; #endif - return NULL; - } - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &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 = slirp->vhost_addr; - else - so->so_faddr = addr.sin_addr; - - so->s = s; - return so; + return NULL; + } + setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); + slirp_socket_set_nodelay(s); + + addrlen = sizeof(so->fhost); + getsockname(s, &so->fhost.sa, &addrlen); + sotranslate_accept(so); + + so->s = s; + return so; +} + +struct socket *tcp_listen(Slirp *slirp, uint32_t haddr, unsigned hport, + uint32_t laddr, unsigned lport, int flags) +{ + struct sockaddr_in hsa, lsa; + + memset(&hsa, 0, sizeof(hsa)); + hsa.sin_family = AF_INET; + hsa.sin_addr.s_addr = haddr; + hsa.sin_port = hport; + + memset(&lsa, 0, sizeof(lsa)); + lsa.sin_family = AF_INET; + lsa.sin_addr.s_addr = laddr; + lsa.sin_port = lport; + + return tcpx_listen(slirp, (const struct sockaddr *) &hsa, sizeof(hsa), (struct sockaddr *) &lsa, sizeof(lsa), flags); } /* @@ -665,71 +920,336 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, * The socket state stuff needs work, these often get call 2 or 3 * times each when only 1 was needed */ -void -soisfconnecting(struct socket *so) +void soisfconnecting(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(struct socket *so) +{ + so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF); + so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ +} + +static void sofcantrcvmore(struct socket *so) +{ + if ((so->so_state & SS_NOFDREF) == 0) { + shutdown(so->s,0); + } + so->so_state &= ~(SS_ISFCONNECTING); + if (so->so_state & SS_FCANTSENDMORE) { + so->so_state &= SS_PERSISTENT_MASK; + so->so_state |= SS_NOFDREF; /* Don't select it */ + } else { + so->so_state |= SS_FCANTRCVMORE; + } +} + +static void sofcantsendmore(struct socket *so) +{ + if ((so->so_state & SS_NOFDREF) == 0) { + shutdown(so->s,1); /* send FIN to fhost */ + } + so->so_state &= ~(SS_ISFCONNECTING); + if (so->so_state & SS_FCANTRCVMORE) { + so->so_state &= SS_PERSISTENT_MASK; + so->so_state |= SS_NOFDREF; /* as above */ + } else { + so->so_state |= SS_FCANTSENDMORE; + } +} + +void sofwdrain(struct socket *so) { - so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE| - SS_FCANTSENDMORE|SS_FWDRAIN); - so->so_state |= SS_ISFCONNECTING; /* Clobber other states */ + if (so->so_rcv.sb_cc) + so->so_state |= SS_FWDRAIN; + else + sofcantsendmore(so); } -void -soisfconnected(struct socket *so) +static bool sotranslate_out4(Slirp *s, struct socket *so, struct sockaddr_in *sin) { - so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF); - so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ + if (!s->disable_dns && so->so_faddr.s_addr == s->vnameserver_addr.s_addr) { + return so->so_fport == htons(53) && get_dns_addr(&sin->sin_addr) >= 0; + } + + if (so->so_faddr.s_addr == s->vhost_addr.s_addr || + so->so_faddr.s_addr == 0xffffffff) { + if (s->disable_host_loopback) { + return false; + } + + sin->sin_addr = loopback_addr; + } + + return true; } -static void -sofcantrcvmore(struct socket *so) +static bool sotranslate_out6(Slirp *s, struct socket *so, struct sockaddr_in6 *sin) { - 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_PERSISTENT_MASK; - so->so_state |= SS_NOFDREF; /* Don't select it */ - } else { - so->so_state |= SS_FCANTRCVMORE; - } + if (!s->disable_dns && in6_equal(&so->so_faddr6, &s->vnameserver_addr6)) { + uint32_t scope_id; + if (so->so_fport == htons(53) && get_dns6_addr(&sin->sin6_addr, &scope_id) >= 0) { + sin->sin6_scope_id = scope_id; + return true; + } + return false; + } + + if (in6_equal_net(&so->so_faddr6, &s->vprefix_addr6, s->vprefix_len) || + in6_equal(&so->so_faddr6, &ALLNODES_MULTICAST)) { + if (s->disable_host_loopback) { + return false; + } + + sin->sin6_addr = in6addr_loopback; + } + + return true; +} + + +int sotranslate_out(struct socket *so, struct sockaddr_storage *addr) +{ + bool ok = true; + + switch (addr->ss_family) { + case AF_INET: + ok = sotranslate_out4(so->slirp, so, (struct sockaddr_in *)addr); + break; + case AF_INET6: + ok = sotranslate_out6(so->slirp, so, (struct sockaddr_in6 *)addr); + break; + } + + if (!ok) { + errno = EPERM; + return -1; + } + + return 0; } -static void -sofcantsendmore(struct socket *so) +void sotranslate_in(struct socket *so, struct sockaddr_storage *addr) { - if ((so->so_state & SS_NOFDREF) == 0) { - shutdown(so->s,1); /* send FIN to fhost */ - if (global_readfds) { - FD_CLR(so->s,global_readfds); + Slirp *slirp = so->slirp; + struct sockaddr_in *sin = (struct sockaddr_in *)addr; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; + + switch (addr->ss_family) { + case AF_INET: + if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == + slirp->vnetwork_addr.s_addr) { + uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr; + + if ((so->so_faddr.s_addr & inv_mask) == inv_mask) { + sin->sin_addr = slirp->vhost_addr; + } else if (sin->sin_addr.s_addr == loopback_addr.s_addr || + so->so_faddr.s_addr != slirp->vhost_addr.s_addr) { + sin->sin_addr = so->so_faddr; } - if (global_xfds) { - FD_CLR(so->s,global_xfds); + } + break; + + case AF_INET6: + if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6, + slirp->vprefix_len)) { + if (in6_equal(&sin6->sin6_addr, &in6addr_loopback) || + !in6_equal(&so->so_faddr6, &slirp->vhost_addr6)) { + sin6->sin6_addr = so->so_faddr6; } - } - so->so_state &= ~(SS_ISFCONNECTING); - if (so->so_state & SS_FCANTRCVMORE) { - so->so_state &= SS_PERSISTENT_MASK; - so->so_state |= SS_NOFDREF; /* as above */ - } else { - so->so_state |= SS_FCANTSENDMORE; - } + } + break; + + default: + break; + } +} + +void sotranslate_accept(struct socket *so) +{ + Slirp *slirp = so->slirp; + + switch (so->so_ffamily) { + case AF_INET: + if (so->so_faddr.s_addr == INADDR_ANY || + (so->so_faddr.s_addr & loopback_mask) == + (loopback_addr.s_addr & loopback_mask)) { + so->so_faddr = slirp->vhost_addr; + } + break; + + case AF_INET6: + if (in6_equal(&so->so_faddr6, &in6addr_any) || + in6_equal(&so->so_faddr6, &in6addr_loopback)) { + so->so_faddr6 = slirp->vhost_addr6; + } + break; + + case AF_UNIX: { + /* Translate Unix socket to random ephemeral source port. We obtain + * this source port by binding to port 0 so that the OS allocates a + * port for us. If this fails, we fall back to choosing a random port + * with a random number generator. */ + int s = 0; + struct sockaddr_in in_addr; + struct sockaddr_in6 in6_addr; + socklen_t in_addr_len; + + if (so->slirp->in_enabled) { + so->so_ffamily = AF_INET; + so->so_faddr = slirp->vhost_addr; + so->so_fport = 0; + + switch (so->so_type) { + case IPPROTO_TCP: + s = slirp_socket(PF_INET, SOCK_STREAM, 0); + break; + case IPPROTO_UDP: + s = slirp_socket(PF_INET, SOCK_DGRAM, 0); + break; + default: + slirplog_error("Unknown protocol"); + break; + } + if (s < 0) { + slirplog_error("Ephemeral slirp_socket() allocation failed"); + goto unix2inet_cont; + } + memset(&in_addr, 0, sizeof(in_addr)); + in_addr.sin_family = AF_INET; + in_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + in_addr.sin_port = htons(0); + if (bind(s, (struct sockaddr *) &in_addr, sizeof(in_addr))) { + slirplog_error("Ephemeral bind() failed"); + closesocket(s); + goto unix2inet_cont; + } + in_addr_len = sizeof(in_addr); + if (getsockname(s, (struct sockaddr *) &in_addr, &in_addr_len)) { + slirplog_error("Ephemeral getsockname() failed"); + closesocket(s); + goto unix2inet_cont; + } + so->s_aux = s; + so->so_fport = in_addr.sin_port; + +unix2inet_cont: + if (!so->so_fport) { + slirplog_error("Falling back to random port allocation"); + so->so_fport = htons(slirp_rand_int_range(49152, 65536)); + } + } else if (so->slirp->in6_enabled) { + so->so_ffamily = AF_INET6; + so->so_faddr6 = slirp->vhost_addr6; + so->so_fport6 = 0; + + switch (so->so_type) { + case IPPROTO_TCP: + s = slirp_socket(PF_INET6, SOCK_STREAM, 0); + break; + case IPPROTO_UDP: + s = slirp_socket(PF_INET6, SOCK_DGRAM, 0); + break; + default: + slirplog_error("Unknown protocol"); + break; + } + if (s < 0) { + slirplog_error("Ephemeral slirp_socket() allocation failed"); + goto unix2inet6_cont; + } + memset(&in6_addr, 0, sizeof(in6_addr)); + in6_addr.sin6_family = AF_INET6; + in6_addr.sin6_addr = in6addr_loopback; + in6_addr.sin6_port = htons(0); + if (bind(s, (struct sockaddr *) &in6_addr, sizeof(in6_addr))) { + slirplog_error("Ephemeral bind() failed"); + closesocket(s); + goto unix2inet6_cont; + } + in_addr_len = sizeof(in6_addr); + if (getsockname(s, (struct sockaddr *) &in6_addr, &in_addr_len)) { + slirplog_error("Ephemeral getsockname() failed"); + closesocket(s); + goto unix2inet6_cont; + } + so->s_aux = s; + so->so_fport6 = in6_addr.sin6_port; + +unix2inet6_cont: + if (!so->so_fport6) { + slirplog_error("Falling back to random port allocation"); + so->so_fport6 = htons(slirp_rand_int_range(49152, 65536)); + } + } else { + slirplog_error("Unknown protocol"); + } + break; + } /* case AF_UNIX */ + + default: + break; + } +} + +void sodrop(struct socket *s, int num) +{ + if (sbdrop(&s->so_snd, num)) { + s->slirp->cb->notify(s->slirp->opaque); + } } /* - * Set write drain mode - * Set CANTSENDMORE once all data has been write()n + * Translate "addr-any" in so->lhost to the guest's actual address. + * Returns 0 for success, or -1 if the guest doesn't have an address yet + * with errno set to EHOSTUNREACH. + * + * The guest address is taken from the first entry in the ARP table for IPv4 + * and the first entry in the NDP table for IPv6. + * Note: The IPv4 path isn't exercised yet as all hostfwd "" guest translations + * are handled immediately by using slirp->vdhcp_startaddr. */ -void -sofwdrain(struct socket *so) +int soassign_guest_addr_if_needed(struct socket *so) { - if (so->so_rcv.sb_cc) - so->so_state |= SS_FWDRAIN; - else - sofcantsendmore(so); + Slirp *slirp = so->slirp; + /* AF_INET6 addresses are bigger than AF_INET, so this is big enough. */ + char addrstr[INET6_ADDRSTRLEN]; + char portstr[6]; + + assert(so->so_state & SS_HOSTFWD); + + switch (so->so_ffamily) { + case AF_INET: + if (so->so_laddr.s_addr == INADDR_ANY) { + slirplog_error("Unsupported address"); + } + break; + + case AF_INET6: + if (in6_zero(&so->so_laddr6)) { + int ret; + if (in6_zero(&slirp->ndp_table.guest_in6_addr)) { + errno = EHOSTUNREACH; + return -1; + } + so->so_laddr6 = slirp->ndp_table.guest_in6_addr; + ret = getnameinfo((const struct sockaddr *) &so->lhost.ss, + sizeof(so->lhost.ss), addrstr, sizeof(addrstr), + portstr, sizeof(portstr), + NI_NUMERICHOST|NI_NUMERICSERV); + assert(ret == 0); + DEBUG_MISC("%s: new ip = [%s]:%s", __func__, addrstr, portstr); + } + break; + + default: + break; + } + + return 0; } #endif diff --git a/bochs/iodev/network/slirp/socket.h b/bochs/iodev/network/slirp/socket.h index aab6cc9689..5ac1318f21 100644 --- a/bochs/iodev/network/slirp/socket.h +++ b/bochs/iodev/network/slirp/socket.h @@ -1,59 +1,91 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. */ -#ifndef _SLIRP_SOCKET_H_ -#define _SLIRP_SOCKET_H_ +#ifndef SLIRP_SOCKET_H +#define SLIRP_SOCKET_H + +#include + +#ifndef _WIN32 +#include +#endif + +#include "misc.h" +#include "sbuf.h" #define SO_EXPIRE 240000 #define SO_EXPIREFAST 10000 +/* Helps unify some in/in6 routines. */ +union in4or6_addr { + struct in_addr addr4; + struct in6_addr addr6; +}; +typedef union in4or6_addr in4or6_addr; + /* * Our socket structure */ -struct socket { - struct socket *so_next,*so_prev; /* For a linked list of sockets */ - - int s; /* The actual socket */ - - Slirp *slirp; /* managing slirp instance */ - - /* 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 */ - uint16_t so_fport; /* foreign port */ - uint16_t so_lport; /* local port */ - - uint8_t so_iptos; /* Type of service */ - uint8_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 */ +union slirp_sockaddr { + struct sockaddr sa; + struct sockaddr_storage ss; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; +}; - struct sbuf so_rcv; /* Receive buffer */ - struct sbuf so_snd; /* Send buffer */ - void * extra; /* Extra pointer */ +struct socket { + struct socket *so_next, *so_prev; /* For a linked list of sockets */ + + int s; /* The actual socket */ + int s_aux; /* An auxiliary socket for miscellaneous use. Currently used to + * reserve OS ports in UNIX-to-inet translation. */ + struct gfwd_list *guestfwd; + + int pollfds_idx; + + Slirp *slirp; /* managing slirp instance */ + + /* 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 */ + uint32_t so_urgc; + union slirp_sockaddr fhost; /* Foreign host */ +#define so_faddr fhost.sin.sin_addr +#define so_fport fhost.sin.sin_port +#define so_faddr6 fhost.sin6.sin6_addr +#define so_fport6 fhost.sin6.sin6_port +#define so_ffamily fhost.ss.ss_family + + union slirp_sockaddr lhost; /* Local host */ +#define so_laddr lhost.sin.sin_addr +#define so_lport lhost.sin.sin_port +#define so_laddr6 lhost.sin6.sin6_addr +#define so_lport6 lhost.sin6.sin6_port +#define so_lfamily lhost.ss.ss_family + + uint8_t so_iptos; /* Type of service */ + uint8_t so_emu; /* Is the socket emulated? */ + + uint8_t so_type; /* Protocol of the socket. May be 0 if loading old + * states. */ + int32_t so_state; /* internal state flags SS_*, below */ + + struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */ + unsigned 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 */ }; @@ -61,38 +93,146 @@ struct socket { * 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_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 */ - -#define SS_PERSISTENT_MASK 0xf000 /* Unremovable state bits */ -#define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */ -#define SS_INCOMING 0x2000 /* Connection was initiated by a host on the internet */ - -struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int); -struct socket * socreate(Slirp *); +#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_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 */ + +#define SS_PERSISTENT_MASK 0xf000 /* Unremovable state bits */ +#define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */ +#define SS_INCOMING \ + 0x2000 /* Connection was initiated by a host on the internet */ +#define SS_HOSTFWD_V6ONLY 0x4000 /* Only bind on v6 addresses */ + +/* Check that two addresses are equal */ +static inline int sockaddr_equal(const struct sockaddr_storage *a, + const struct sockaddr_storage *b) +{ + if (a->ss_family != b->ss_family) { + return 0; + } + + switch (a->ss_family) { + case AF_INET: { + const struct sockaddr_in *a4 = (const struct sockaddr_in *)a; + const struct sockaddr_in *b4 = (const struct sockaddr_in *)b; + return a4->sin_addr.s_addr == b4->sin_addr.s_addr && + a4->sin_port == b4->sin_port; + } + case AF_INET6: { + const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)a; + const struct sockaddr_in6 *b6 = (const struct sockaddr_in6 *)b; + return (in6_equal(&a6->sin6_addr, &b6->sin6_addr) && + a6->sin6_port == b6->sin6_port); + } +#ifndef _WIN32 + case AF_UNIX: { + const struct sockaddr_un *aun = (const struct sockaddr_un *)a; + const struct sockaddr_un *bun = (const struct sockaddr_un *)b; + return strncmp(aun->sun_path, bun->sun_path, sizeof(aun->sun_path)) == 0; + } +#endif + default: + fprintf(stderr, "Unknown protocol\n"); + } + + return 0; +} + +/* Get the size of an address */ +static inline socklen_t sockaddr_size(const struct sockaddr_storage *a) +{ + switch (a->ss_family) { + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); +#ifndef _WIN32 + case AF_UNIX: + return sizeof(struct sockaddr_un); +#endif + default: + fprintf(stderr, "Unknown protocol\n"); + } + + return 0; +} + +/* Copy an address */ +static inline void sockaddr_copy(struct sockaddr *dst, socklen_t dstlen, const struct sockaddr *src, socklen_t srclen) +{ + socklen_t len = sockaddr_size((const struct sockaddr_storage *) src); + assert(len <= srclen); + assert(len <= dstlen); + memcpy(dst, src, len); +} + +/* Find the socket corresponding to lhost & fhost, trying last as a guess */ +struct socket *solookup(struct socket **last, struct socket *head, + struct sockaddr_storage *lhost, struct sockaddr_storage *fhost); +/* Create a new socket */ +struct socket *socreate(Slirp *, int); +/* Release a socket */ void sofree(struct socket *); +/* Receive the available data from the Internet socket and queue it on the sb */ int soread(struct socket *); -void sorecvoob(struct socket *); +/* Receive the available OOB data from the Internet socket and try to send it immediately */ +int sorecvoob(struct socket *); +/* Send OOB data to the Internet socket */ int sosendoob(struct socket *); +/* Send data to the Internet socket */ int sowrite(struct socket *); +/* Receive the available data from the Internet UDP socket, and send it to the guest */ void sorecvfrom(struct socket *); +/* Send data to the Internet UDP socket */ int sosendto(struct socket *, struct mbuf *); -struct socket * tcp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int, - int); +/* Listen for incoming TCPv4 connections on this haddr+hport */ +struct socket * tcp_listen(Slirp *, uint32_t haddr, unsigned hport, uint32_t laddr, unsigned lport, int flags); +/* + * Listen for incoming TCP connections on this haddr + * On failure errno contains the reason. + */ +struct socket * tcpx_listen(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + const struct sockaddr *laddr, socklen_t laddrlen, + int flags); +/* Note that the socket is connecting */ void soisfconnecting(struct socket *); +/* Note that the socket is connected */ void soisfconnected(struct socket *); +/* + * Set write drain mode + * Set CANTSENDMORE once all data has been write()n + */ void sofwdrain(struct socket *); struct iovec; /* For win32 */ +/* Prepare iov for storing into the sb */ size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np); +/* Get data from the buffer and queue it on the sb */ int soreadbuf(struct socket *so, const char *buf, int size); -#endif /* _SOCKET_H_ */ +/* Translate addr into host addr when it is a virtual address, before sending to the Internet */ +int sotranslate_out(struct socket *, struct sockaddr_storage *); +/* Translate addr into virtual address when it is host, before sending to the guest */ +void sotranslate_in(struct socket *, struct sockaddr_storage *); +/* Translate connections from localhost to the real hostname */ +void sotranslate_accept(struct socket *); +/* Drop num bytes from the reading end of the socket */ +void sodrop(struct socket *, int num); +/* Forwarding a connection to the guest, try to find the guest address to use, fill lhost with it */ +int soassign_guest_addr_if_needed(struct socket *so); + +#endif /* SLIRP_SOCKET_H */ diff --git a/bochs/iodev/network/slirp/tcp.h b/bochs/iodev/network/slirp/tcp.h index a8e498ff84..96c6c7974f 100644 --- a/bochs/iodev/network/slirp/tcp.h +++ b/bochs/iodev/network/slirp/tcp.h @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,20 +27,21 @@ * 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 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_ +#ifndef TCP_H +#define TCP_H -typedef uint32_t tcp_seq; +typedef uint32_t tcp_seq; -#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ -#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ +#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ +#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ -#define TCP_SNDSPACE 8192 -#define TCP_RCVSPACE 8192 +#define TCP_SNDSPACE 1024 * 128 +#define TCP_RCVSPACE 1024 * 128 +#define TCP_MAXSEG_MAX 32768 /* * TCP header. @@ -50,71 +49,61 @@ typedef uint32_t tcp_seq; */ #define tcphdr slirp_tcphdr struct tcphdr { - uint16_t th_sport; /* source port */ - uint16_t th_dport; /* destination port */ - tcp_seq th_seq; /* sequence number */ - tcp_seq th_ack; /* acknowledgement number */ + uint16_t th_sport; /* source port */ + uint16_t th_dport; /* destination port */ + tcp_seq th_seq; /* sequence number */ + tcp_seq th_ack; /* acknowledgement number */ #ifndef BX_LITTLE_ENDIAN - uint8_t th_off:4, /* data offset */ - th_x2:4; /* (unused) */ + uint8_t th_off:4, /* data offset */ + th_x2:4; /* (unused) */ #else - uint8_t th_x2:4, /* (unused) */ - th_off:4; /* data offset */ + uint8_t th_x2:4, /* (unused) */ + th_off:4; /* data offset */ #endif - uint8_t th_flags; - uint16_t th_win; /* window */ - uint16_t th_sum; /* checksum */ - uint16_t th_urp; /* urgent pointer */ + uint8_t th_flags; + uint16_t th_win; /* window */ + uint16_t th_sum; /* checksum */ + uint16_t th_urp; /* urgent pointer */ }; #include "tcp_var.h" #ifndef TH_FIN -#define TH_FIN 0x01 -#define TH_SYN 0x02 -#define TH_RST 0x04 -#define TH_PUSH 0x08 -#define TH_ACK 0x10 -#define TH_URG 0x20 +#define TH_FIN 0x01 +#define TH_SYN 0x02 +#define TH_RST 0x04 +#define TH_PUSH 0x08 +#define TH_ACK 0x10 +#define TH_URG 0x20 #endif #ifndef TCPOPT_EOL -#define TCPOPT_EOL 0 -#define TCPOPT_NOP 1 -#define TCPOPT_MAXSEG 2 -#define TCPOPT_WINDOW 3 -#define TCPOPT_SACK_PERMITTED 4 /* Experimental */ -#define TCPOPT_SACK 5 /* Experimental */ -#define TCPOPT_TIMESTAMP 8 - -#define TCPOPT_TSTAMP_HDR \ - (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) +#define TCPOPT_EOL 0 +#define TCPOPT_NOP 1 +#define TCPOPT_MAXSEG 2 +#define TCPOPT_WINDOW 3 +#define TCPOPT_SACK_PERMITTED 4 /* Experimental */ +#define TCPOPT_SACK 5 /* Experimental */ +#define TCPOPT_TIMESTAMP 8 + +#define TCPOPT_TSTAMP_HDR \ + (TCPOPT_NOP << 24 | TCPOPT_NOP << 16 | TCPOPT_TIMESTAMP << 8 | \ + TCPOLEN_TIMESTAMP) #endif #ifndef TCPOLEN_MAXSEG -#define TCPOLEN_MAXSEG 4 -#define TCPOLEN_WINDOW 3 -#define TCPOLEN_SACK_PERMITTED 2 -#define TCPOLEN_TIMESTAMP 10 -#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ +#define TCPOLEN_MAXSEG 4 +#define TCPOLEN_WINDOW 3 +#define TCPOLEN_SACK_PERMITTED 2 +#define TCPOLEN_TIMESTAMP 10 +#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ #endif -/* - * 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. - */ -#undef TCP_MSS -#define TCP_MSS 1460 - #undef TCP_MAXWIN -#define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ +#define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ #undef TCP_MAX_WINSHIFT -#define TCP_MAX_WINSHIFT 14 /* maximum window shift */ +#define TCP_MAX_WINSHIFT 14 /* maximum window shift */ /* * User-settable options (used with setsockopt). @@ -124,7 +113,7 @@ struct tcphdr { * so we undefine them. */ #undef TCP_NODELAY -#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ #undef TCP_MAXSEG /* @@ -168,8 +157,7 @@ struct tcphdr { * 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_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 diff --git a/bochs/iodev/network/slirp/tcp_input.cc b/bochs/iodev/network/slirp/tcp_input.cc index 38582fba6b..a6d3ff3463 100644 --- a/bochs/iodev/network/slirp/tcp_input.cc +++ b/bochs/iodev/network/slirp/tcp_input.cc @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,16 +27,13 @@ * 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 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 "slirp.h" @@ -46,316 +41,354 @@ #if BX_NETWORKING && BX_NETMOD_SLIRP -#define TCPREXMTTHRESH 3 +#define TCPREXMTTHRESH 3 -#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * PR_SLOWHZ) +#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) +#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. + * a segment with FIN. * 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 && \ - tcpfrag_list_empty(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; \ - if (so->so_emu) { \ - if (tcp_emu((so),(m))) sbappend((so), (m)); \ - } else \ - sbappend((so), (m)); \ - } 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 && \ - tcpfrag_list_empty(tp) && \ - (tp)->t_state == TCPS_ESTABLISHED) { \ - tp->t_flags |= TF_DELACK; \ - (tp)->rcv_nxt += (ti)->ti_len; \ - flags = (ti)->ti_flags & TH_FIN; \ - if (so->so_emu) { \ - if (tcp_emu((so),(m))) sbappend(so, (m)); \ - } else \ - sbappend((so), (m)); \ - } else { \ - (flags) = tcp_reass((tp), (ti), (m)); \ - tp->t_flags |= TF_ACKNOW; \ - } \ -} -#endif -static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, + +static void tcp_dooptions(struct tcpcb *tp, uint8_t *cp, int cnt, struct tcpiphdr *ti); static void tcp_xmit_timer(struct tcpcb *tp, int rtt); -static int -tcp_reass(struct tcpcb *tp, struct tcpiphdr *ti, +static int tcp_reass(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m) { - struct tcpiphdr *q; - struct socket *so = tp->t_socket; - int flags; - - /* - * Call with ti==NULL after become established to - * force pre-ESTABLISHED data up to user socket. - */ - if (ti == NULL) - goto present; - - /* - * Find a segment which begins after this one does. - */ - for (q = tcpfrag_list_first(tp); !tcpfrag_list_end(q, tp); - q = tcpiphdr_next(q)) - 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 (!tcpfrag_list_end(tcpiphdr_prev(q), tp)) { - int i; - q = tcpiphdr_prev(q); - /* 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) { - m_free(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 = tcpiphdr_next(q); - } - ti->ti_mbuf = m; - - /* - * While we overlap succeeding segments trim them or, - * if they are completely covered, dequeue them. - */ - while (!tcpfrag_list_end(q, tp)) { - 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(q->ti_mbuf, i); - break; - } - q = tcpiphdr_next(q); - m = tcpiphdr_prev(q)->ti_mbuf; - remque(tcpiphdr2qlink(tcpiphdr_prev(q))); - m_free(m); - } - - /* - * Stick new segment in its place. - */ - insque(tcpiphdr2qlink(ti), tcpiphdr2qlink(tcpiphdr_prev(q))); + struct tcpiphdr *q; + struct socket *so = tp->t_socket; + int flags; + + /* + * Call with ti==NULL after become established to + * force pre-ESTABLISHED data up to user socket. + */ + if (ti == NULL) + goto present; + + /* + * Find a segment which begins after this one does. + */ + for (q = tcpfrag_list_first(tp); !tcpfrag_list_end(q, tp); + q = tcpiphdr_next(q)) + 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 (!tcpfrag_list_end(tcpiphdr_prev(q), tp)) { + int i; + q = tcpiphdr_prev(q); + /* 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) { + m_free(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 = tcpiphdr_next(q); + } + ti->ti_mbuf = m; + + /* + * While we overlap succeeding segments trim them or, + * if they are completely covered, dequeue them. + */ + while (!tcpfrag_list_end(q, tp)) { + 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(q->ti_mbuf, i); + break; + } + q = tcpiphdr_next(q); + m = tcpiphdr_prev(q)->ti_mbuf; + slirp_remque(tcpiphdr2qlink(tcpiphdr_prev(q))); + m_free(m); + } + + /* + * Stick new segment in its place. + */ + slirp_insque(tcpiphdr2qlink(ti), tcpiphdr2qlink(tcpiphdr_prev(q))); present: - /* - * Present data to user, advancing rcv_nxt through - * completed sequence space. - */ - if (!TCPS_HAVEESTABLISHED(tp->t_state)) - return (0); - ti = tcpfrag_list_first(tp); - if (tcpfrag_list_end(ti, 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(tcpiphdr2qlink(ti)); - m = ti->ti_mbuf; - ti = tcpiphdr_next(ti); - if (so->so_state & SS_FCANTSENDMORE) - m_free(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); - return (flags); + /* + * Present data to user, advancing rcv_nxt through + * completed sequence space. + */ + if (!TCPS_HAVEESTABLISHED(tp->t_state)) + return (0); + ti = tcpfrag_list_first(tp); + if (tcpfrag_list_end(ti, 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; + slirp_remque(tcpiphdr2qlink(ti)); + m = ti->ti_mbuf; + ti = tcpiphdr_next(ti); + if (so->so_state & SS_FCANTSENDMORE) + m_free(m); + else { + if (so->so_emu) { + if (tcp_emu(so,m)) + sbappend(so, m); + } else + sbappend(so, m); + } + } while (!tcpfrag_list_end(ti, tp) && ti->ti_seq == tp->rcv_nxt); + return (flags); } /* * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. */ -void -tcp_input(struct mbuf *m, int iphlen, struct socket *inso) +void tcp_input(struct mbuf *m, int iphlen, struct socket *inso, + unsigned short af) { - struct ip save_ip, *ip; - struct tcpiphdr *ti; - caddr_t optp = NULL; - int optlen = 0; - int len, tlen, off; - struct tcpcb *tp = NULL; - int tiflags; - struct socket *so = NULL; - int todrop, acked, ourfinisacked, needoutput = 0; - int iss = 0; - u_long tiwin; - int ret; - struct ex_list *ex_ptr; + struct ip save_ip, *ip; + struct ip6 save_ip6, *ip6; + struct tcpiphdr *ti = NULL; + char *optp = NULL; + int optlen = 0; + int len, tlen = 0, off; + struct tcpcb *tp = NULL; + int tiflags; + struct socket *so = NULL; + int todrop, acked, ourfinisacked, needoutput = 0; + int iss = 0; + uint32_t tiwin; + int ret; + struct sockaddr_storage lhost, fhost; + struct sockaddr_in *lhost4, *fhost4; + struct sockaddr_in6 *lhost6, *fhost6; + struct gfwd_list *ex_ptr; Slirp *slirp; - 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; - slirp = so->slirp; - - /* Re-set a few variables */ - tp = sototcpcb(so); - m = so->so_m; - so->so_m = NULL; - ti = so->so_ti; - tiwin = ti->ti_win; - tiflags = ti->ti_flags; - - goto cont_conn; - } - slirp = m->slirp; - - /* - * Get IP and TCP header together in first mbuf. - * Note: IP leaves IP header in first mbuf. - */ - ti = mtod(m, struct tcpiphdr *); - if (iphlen > (int)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; + DEBUG_CALL("tcp_input"); + DEBUG_ARG("m = %p iphlen = %2d inso = %p", m, iphlen, inso); + + memset(&lhost, 0, sizeof(struct sockaddr_storage)); + memset(&fhost, 0, sizeof(struct sockaddr_storage)); + + /* + * If called with m == 0, then we're continuing the connect + */ + if (m == NULL) { + so = inso; + slirp = so->slirp; + + /* Re-set a few variables */ + tp = sototcpcb(so); + m = so->so_m; + so->so_m = NULL; + ti = so->so_ti; + tiwin = ti->ti_win; + tiflags = ti->ti_flags; + + goto cont_conn; + } + slirp = m->slirp; + switch (af) { + case AF_INET: + M_DUP_DEBUG(slirp, m, 0, + (int)(sizeof(struct qlink) + sizeof(struct tcpiphdr) - sizeof(struct ip) - sizeof(struct tcphdr))); + break; + case AF_INET6: + M_DUP_DEBUG(slirp, m, 0, + (int)(sizeof(struct qlink) + sizeof(struct tcpiphdr) - sizeof(struct ip6) - sizeof(struct tcphdr))); + break; + } + + ip = mtod(m, struct ip *); + ip6 = mtod(m, struct ip6 *); + + switch (af) { + case AF_INET: + if (iphlen > (int)sizeof(struct ip )) { + ip_stripoptions(m); + 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. + */ + save_ip = *ip; + save_ip.ip_len+= iphlen; + + /* + * Get IP and TCP header together in first mbuf. + * Note: IP leaves IP header in first mbuf. + */ + m->m_data -= + sizeof(struct tcpiphdr) - sizeof(struct ip) - sizeof(struct tcphdr); + m->m_len += + sizeof(struct tcpiphdr) - sizeof(struct ip) - sizeof(struct tcphdr); + ti = mtod(m, struct tcpiphdr *); + + /* + * Checksum extended TCP header and data. + */ + tlen = ip->ip_len; + tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL; + memset(&ti->ih_mbuf, 0, sizeof(struct mbuf_ptr)); + memset(&ti->ti, 0, sizeof(ti->ti)); + ti->ti_x0 = 0; + ti->ti_src = save_ip.ip_src; + ti->ti_dst = save_ip.ip_dst; + ti->ti_pr = save_ip.ip_p; + ti->ti_len = htons((uint16_t)tlen); + break; + + case AF_INET6: + /* + * Save a copy of the IP header in case we want restore it + * for sending an ICMP error message in response. + */ + save_ip6 = *ip6; + /* + * Get IP and TCP header together in first mbuf. + * Note: IP leaves IP header in first mbuf. + */ + m->m_data -= sizeof(struct tcpiphdr) - + (sizeof(struct ip6) + sizeof(struct tcphdr)); + m->m_len += sizeof(struct tcpiphdr) - + (sizeof(struct ip6) + sizeof(struct tcphdr)); + ti = mtod(m, struct tcpiphdr *); + + tlen = ip6->ip_pl; tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL; - memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); - ti->ti_x1 = 0; - ti->ti_len = htons((uint16_t)tlen); - len = sizeof(struct ip ) + tlen; - if(cksum(m, len)) { - goto drop; - } - - /* - * Check that TCP offset makes sense, - * pull out TCP options and adjust length. XXX - */ - off = ti->ti_off << 2; - if (off < (int)sizeof(struct tcphdr) || off > tlen) { - goto drop; - } - tlen -= off; - ti->ti_len = tlen; - if (off > (int)sizeof(struct tcphdr)) { - optlen = off - sizeof (struct tcphdr); - optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr); - } - 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. - */ + memset(&ti->ih_mbuf, 0, sizeof(struct mbuf_ptr)); + memset(&ti->ti, 0, sizeof(ti->ti)); + ti->ti_x0 = 0; + ti->ti_src6 = save_ip6.ip_src; + ti->ti_dst6 = save_ip6.ip_dst; + ti->ti_nh6 = save_ip6.ip_nh; + ti->ti_len = htons((uint16_t)tlen); + break; + + default: + slirplog_error("Unknown protocol"); + } + + len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen); + if (cksum(m, len)) { + goto drop; + } + + /* + * Check that TCP offset makes sense, + * pull out TCP options and adjust length. XXX + */ + off = ti->ti_off << 2; + if (off < (int)sizeof(struct tcphdr) || off > tlen) { + goto drop; + } + tlen -= off; + ti->ti_len = tlen; + if (off > (int)sizeof(struct tcphdr)) { + optlen = off - sizeof (struct tcphdr); + optp = mtod(m, char *) + sizeof (struct tcpiphdr); + } + 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 = slirp->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(&slirp->tcb, ti->ti_src, ti->ti_sport, - ti->ti_dst, ti->ti_dport); - if (so) - slirp->tcp_last_so = so; - } - - /* - * 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 == NULL) { - if (slirp->restricted) { + lhost.ss_family = af; + fhost.ss_family = af; + switch (af) { + case AF_INET: + lhost4 = (struct sockaddr_in *)&lhost; + lhost4->sin_addr = ti->ti_src; + lhost4->sin_port = ti->ti_sport; + fhost4 = (struct sockaddr_in *)&fhost; + fhost4->sin_addr = ti->ti_dst; + fhost4->sin_port = ti->ti_dport; + break; + case AF_INET6: + lhost6 = (struct sockaddr_in6 *)&lhost; + lhost6->sin6_addr = ti->ti_src6; + lhost6->sin6_port = ti->ti_sport; + fhost6 = (struct sockaddr_in6 *)&fhost; + fhost6->sin6_addr = ti->ti_dst6; + fhost6->sin6_port = ti->ti_dport; + break; + default: + slirplog_error("Unknown protocol"); + } + + so = solookup(&slirp->tcp_last_so, &slirp->tcb, &lhost, &fhost); + + /* + * 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 == NULL) { + /* TODO: IPv6 */ + if (slirp->restricted) { /* Any hostfwds will have an existing socket, so we only get here * for non-hostfwd connections. These should be dropped, unless it * happens to be a guestfwd. */ - for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for (ex_ptr = slirp->guestfwd_list; ex_ptr; + ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_fport == ti->ti_dport && ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) { break; @@ -364,1087 +397,1102 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) if (!ex_ptr) { goto dropwithreset; } - } + } + + if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN) + goto dropwithreset; + + so = socreate(slirp, IPPROTO_TCP); + tcp_attach(so); + + sbreserve(&so->so_snd, TCP_SNDSPACE); + sbreserve(&so->so_rcv, TCP_RCVSPACE); + + so->lhost.ss = lhost; + so->fhost.ss = fhost; + + so->so_iptos = tcp_tos(so); + if (so->so_iptos == 0) { + switch (af) { + case AF_INET: + so->so_iptos = ((struct ip *)ti)->ip_tos; + break; + case AF_INET6: + break; + default: + slirplog_error("Unknown protocol"); + } + } + + 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 == NULL) + goto dropwithreset; + if (tp->t_state == TCPS_CLOSED) + goto drop; + + tiwin = ti->ti_win; + + /* + * Segment received on connection. + * Reset idle time and keep-alive timer. + */ + tp->t_idle = 0; + if (slirp_do_keepalive) + tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; + else + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; + + /* + * 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, (uint8_t *)optp, optlen, ti); + + /* + * 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 && + ti->ti_seq == tp->rcv_nxt && tiwin && tiwin == tp->snd_wnd && + tp->snd_nxt == tp->snd_max) { + 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. + */ + 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; + sodrop(so, acked); + tp->snd_una = ti->ti_ack; + m_free(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; + + /* + * 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) + tcp_output(tp); + + return; + } + } else if (ti->ti_ack == tp->snd_una && tcpfrag_list_empty(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. + */ + tp->rcv_nxt += ti->ti_len; + /* + * Add data to socket buffer. + */ + if (so->so_emu) { + if (tcp_emu(so,m)) + sbappend(so, m); + } else + sbappend(so, m); + + /* + * 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; - if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN) - goto dropwithreset; + /* + * This has way too many gotos... + * But a bit of spaghetti code never hurt anybody :) + */ - if ((so = socreate(slirp)) == NULL) - goto dropwithreset; - if (tcp_attach(so) < 0) { - free(so); /* Not sofree (if it failed, it's not insqued) */ - goto dropwithreset; - } + /* + * If this is destined for the control address, then flag to + * tcp_ctl once connected, otherwise connect + */ + /* TODO: IPv6 */ + if (af == AF_INET && + (so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == + slirp->vnetwork_addr.s_addr) { + if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr && + so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) { + /* May be an add exec */ + for (ex_ptr = slirp->guestfwd_list; ex_ptr; + ex_ptr = ex_ptr->ex_next) { + if (ex_ptr->ex_fport == so->so_fport && + so->so_faddr.s_addr == ex_ptr->ex_addr.s_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, so->so_ffamily) == -1) && (errno != EAGAIN) && + (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { + uint8_t code = ICMP_UNREACH_NET; + DEBUG_MISC(" tcp fconnect errno = %d-%s", errno, strerror(errno)); + if (errno == ECONNREFUSED) { + /* 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, af); + } else { + switch (af) { + case AF_INET: + code = ICMP_UNREACH_NET; + if (errno == EHOSTUNREACH) { + code = ICMP_UNREACH_HOST; + } + break; + case AF_INET6: + code = ICMP6_UNREACH_NO_ROUTE; + if (errno == EHOSTUNREACH) { + code = ICMP6_UNREACH_ADDRESS; + } + break; + default: + slirplog_error("Unknown protocol"); + } + 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); + switch (af) { + case AF_INET: + m->m_data += sizeof(struct tcpiphdr) - sizeof(struct ip) - + sizeof(struct tcphdr); + m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct ip) - + sizeof(struct tcphdr); + *ip = save_ip; + icmp_send_error(m, ICMP_UNREACH, code, 0, strerror(errno)); + break; + case AF_INET6: + m->m_data += sizeof(struct tcpiphdr) - + (sizeof(struct ip6) + sizeof(struct tcphdr)); + m->m_len -= sizeof(struct tcpiphdr) - + (sizeof(struct ip6) + sizeof(struct tcphdr)); + *ip6 = save_ip6; + icmp6_send_error(m, ICMP6_UNREACH, code); + break; + default: + slirplog_error("Unknown protocol"); + } + } + tcp_close(tp); + m_free(m); + } else { + /* + * 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; + /* + * Initialize receive sequence numbers now so that we can send a + * valid RST if the remote end rejects our connection. + */ + tp->irs = ti->ti_seq; + tcp_rcvseqinit(tp); + tcp_template(tp); + } + 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, (uint8_t *)optp, optlen, ti); + + if (iss) + tp->iss = iss; + else + tp->iss = slirp->tcp_iss; + slirp->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; + 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) { + 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)) { + soisfconnected(so); + tp->t_state = TCPS_ESTABLISHED; + + 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; - sbreserve(&so->so_snd, TCP_SNDSPACE); - sbreserve(&so->so_rcv, TCP_RCVSPACE); +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; + } + 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. + * 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. + */ + 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; - so->so_laddr = ti->ti_src; - so->so_lport = ti->ti_sport; - so->so_faddr = ti->ti_dst; - so->so_fport = ti->ti_dport; + /* + * 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; + } + 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); + 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) { + if (todrop >= 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; + } else { + goto dropafterack; + } + } + m_adj(m, -todrop); + ti->ti_len -= todrop; + tiflags &= ~(TH_PUSH|TH_FIN); + } + + /* + * 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: + case TCPS_ESTABLISHED: + case TCPS_FIN_WAIT_1: + case TCPS_FIN_WAIT_2: + case TCPS_CLOSE_WAIT: + tp->t_state = TCPS_CLOSED; + tcp_close(tp); + goto drop; - if ((so->so_iptos = tcp_tos(so)) == 0) - so->so_iptos = ((struct ip *)ti)->ip_tos; + case TCPS_CLOSING: + case TCPS_LAST_ACK: + case TCPS_TIME_WAIT: + 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; + 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_PERSISTENT_MASK; + so->so_state |= SS_NOFDREF; /* CTL_CMD */ + } else { + needoutput = 1; + tp->t_state = TCPS_FIN_WAIT_1; + } + } else { + soisfconnected(so); + } + + 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) { + DEBUG_MISC(" dup ack m = %p so = %p", m, 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; + unsigned 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; + 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; + 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)) { + goto dropafterack; + } + acked = ti->ti_ack - tp->snd_una; - tp = sototcpcb(so); - tp->t_state = TCPS_LISTEN; - } + /* + * If 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 (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) + tcp_xmit_timer(tp,tp->t_rtt); /* - * 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 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 (so->so_state & SS_ISFCONNECTING) - goto drop; + 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). + */ + { + unsigned cw = tp->snd_cwnd; + unsigned incr = tp->t_maxseg; + + if (cw > tp->snd_ssthresh) + incr = incr * incr / cw; + tp->snd_cwnd = MIN((int)(cw + incr), TCP_MAXWIN << tp->snd_scale); + } + if (acked > (int)so->so_snd.sb_cc) { + tp->snd_wnd -= so->so_snd.sb_cc; + sodrop(so, (int)so->so_snd.sb_cc); + ourfinisacked = 1; + } else { + sodrop(so, acked); + tp->snd_wnd -= acked; + ourfinisacked = 0; + } + 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) { + tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE; + } + tp->t_state = TCPS_FIN_WAIT_2; + } + break; - tp = sototcpcb(so); - - /* XXX Should never fail */ - if (tp == NULL) - goto dropwithreset; - if (tp->t_state == TCPS_CLOSED) - goto drop; - - 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] = TCPTV_KEEPINTVL; - else - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; - - /* - * 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); - - /* - * 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 && - ti->ti_seq == tp->rcv_nxt && - tiwin && tiwin == tp->snd_wnd && - tp->snd_nxt == tp->snd_max) { - 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. - */ - 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; - sbdrop(&so->so_snd, acked); - tp->snd_una = ti->ti_ack; - m_free(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; - - /* - * 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 && - tcpfrag_list_empty(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. - */ - tp->rcv_nxt += ti->ti_len; - /* - * Add data to socket buffer. - */ - if (so->so_emu) { - if (tcp_emu(so,m)) sbappend(so, m); - } else - sbappend(so, m); - - /* - * 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 & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { - if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr && - so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) { - /* May be an add exec */ - for (ex_ptr = slirp->exec_list; ex_ptr; - ex_ptr = ex_ptr->ex_next) { - if(ex_ptr->ex_fport == so->so_fport && - so->so_faddr.s_addr == ex_ptr->ex_addr.s_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) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { - u_char code=ICMP_UNREACH_NET; - DEBUG_MISC((dfd, " tcp fconnect errno = %d-%s\n", - errno,strerror(errno))); - if(errno == ECONNREFUSED) { - /* 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(errno == EHOSTUNREACH) 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)); - } - tcp_close(tp); - m_free(m); - } else { - /* - * 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; - tcp_template(tp); - } - 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); - - if (iss) - tp->iss = iss; - else - tp->iss = slirp->tcp_iss; - slirp->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; - 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) { - 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)) { - soisfconnected(so); - tp->t_state = TCPS_ESTABLISHED; - - (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; + /* + * 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; + } + break; -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; - } - 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. - * 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. - */ - 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; - } - 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); - 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) { - if (todrop >= 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; - } else { - goto dropafterack; - } - } - m_adj(m, -todrop); - ti->ti_len -= todrop; - tiflags &= ~(TH_PUSH|TH_FIN); - } - - /* - * 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: - case TCPS_ESTABLISHED: - case TCPS_FIN_WAIT_1: - case TCPS_FIN_WAIT_2: - case TCPS_CLOSE_WAIT: - tp->t_state = TCPS_CLOSED; - tcp_close(tp); - goto drop; - - case TCPS_CLOSING: - case TCPS_LAST_ACK: - case TCPS_TIME_WAIT: - 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; - 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_PERSISTENT_MASK; - so->so_state |= SS_NOFDREF; /* CTL_CMD */ - } else { - needoutput = 1; - tp->t_state = TCPS_FIN_WAIT_1; - } - } else { - soisfconnected(so); - } - - (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) { - 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)) { - goto dropafterack; - } - acked = ti->ti_ack - tp->snd_una; - - /* - * If 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 (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). - */ - { - u_int cw = tp->snd_cwnd; - u_int incr = tp->t_maxseg; - - if (cw > tp->snd_ssthresh) - incr = incr * incr / cw; - tp->snd_cwnd = min((int)(cw + incr), TCP_MAXWIN<snd_scale); - } - if (acked > (int)so->so_snd.sb_cc) { - tp->snd_wnd -= so->so_snd.sb_cc; - sbdrop(&so->so_snd, (int )so->so_snd.sb_cc); - ourfinisacked = 1; - } else { - sbdrop(&so->so_snd, acked); - tp->snd_wnd -= acked; - ourfinisacked = 0; - } - 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) { - 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; - } - 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) { + /* + * 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) { 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) */ + 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))))) { - 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; + /* + * 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))))) { + 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: - /* - * If this is a small packet, then ACK now - with Nagel - * congestion avoidance sender won't send more until - * he gets an ACK. - */ - if (ti->ti_len && (unsigned)ti->ti_len <= 5 && - ((struct tcpiphdr_2 *)ti)->first_char == (char)27) { - tp->t_flags |= TF_ACKNOW; - } - - /* - * 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); - } 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. - */ - 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; - 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; - } - } - - /* - * Return any desired output. - */ - if (needoutput || (tp->t_flags & TF_ACKNOW)) { - (void) tcp_output(tp); - } - return; + /* + * If this is a small packet, then ACK now - with Nagel + * congestion avoidance sender won't send more until + * he gets an ACK. + */ + if (ti->ti_len && (unsigned)ti->ti_len <= 5 && + ((struct tcpiphdr_2 *)ti)->first_char == (char)27) { + tp->t_flags |= TF_ACKNOW; + } + + /* + * 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) { -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_free(m); - tp->t_flags |= TF_ACKNOW; - (void) tcp_output(tp); - return; + /* + * segment is the next to be received on an established + * connection, and the queue is empty, avoid linkage into and + * removal from the queue and repetition of various + * conversions from tcp_reass(). + */ + if (ti->ti_seq == tp->rcv_nxt && tcpfrag_list_empty(tp) && + tp->t_state == TCPS_ESTABLISHED) { + tp->t_flags |= TF_DELACK; + tp->rcv_nxt += ti->ti_len; + tiflags = ti->ti_flags & TH_FIN; + if (so->so_emu) { + if (tcp_emu(so, m)) + sbappend(so, m); + } else + sbappend(so, m); + } else { + tiflags = tcp_reass(tp, ti, m); + tp->t_flags |= TF_ACKNOW; + } + } 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. + */ + sofwdrain(so); -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); - } + 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; - return; + /* + * 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; -drop: - /* - * Drop space held by incoming segment and return. - */ - m_free(m); -} + /* + * 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; + break; -static void -tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti) -{ - uint16_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); - (void) tcp_mss(tp, mss); /* sets t_maxseg */ - 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; + } + } + + /* + * Return any desired output. + */ + if (needoutput || (tp->t_flags & TF_ACKNOW)) { + 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_free(m); + tp->t_flags |= TF_ACKNOW; + tcp_output(tp); + return; -/* - * 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. - */ +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, af); + 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, af); + } + + return; -#ifdef notdef +drop: + /* + * Drop space held by incoming segment and return. + */ + m_free(m); +} -void -tcp_pulloutofband(so, ti, m) - struct socket *so; - struct tcpiphdr *ti; - struct mbuf *m; +static void tcp_dooptions(struct tcpcb *tp, uint8_t *cp, int cnt, + struct tcpiphdr *ti) { - 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"); + uint16_t mss; + int opt, optlen; + + DEBUG_CALL("tcp_dooptions"); + DEBUG_ARG("tp = %p cnt=%i", 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; + } + } } -#endif /* notdef */ - /* * Collect new round-trip time estimate * and update averages and current timeout. */ -static void -tcp_xmit_timer(struct tcpcb *tp, int rtt) +static void tcp_xmit_timer(struct tcpcb *tp, int rtt) { - short delta; - - DEBUG_CALL("tcp_xmit_timer"); - DEBUG_ARG("tp = %lx", (long)tp); - DEBUG_ARG("rtt = %d", rtt); - - 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; + short delta; + + DEBUG_CALL("tcp_xmit_timer"); + DEBUG_ARG("tp = %p", tp); + DEBUG_ARG("rtt = %d", rtt); + + 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; } /* @@ -1463,35 +1511,46 @@ tcp_xmit_timer(struct tcpcb *tp, int rtt) * parameters from pre-set or cached values in the routing entry. */ -int -tcp_mss(struct tcpcb *tp, u_int offer) +int tcp_mss(struct tcpcb *tp, unsigned offer) { - struct socket *so = tp->t_socket; - 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, (int)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; + struct socket *so = tp->t_socket; + int mss = 0; + + DEBUG_CALL("tcp_mss"); + DEBUG_ARG("tp = %p", tp); + DEBUG_ARG("offer = %d", offer); + + switch (so->so_ffamily) { + case AF_INET: + mss = MIN(so->slirp->if_mtu, so->slirp->if_mru) - + sizeof(struct tcphdr) - sizeof(struct ip); + break; + case AF_INET6: + mss = MIN(so->slirp->if_mtu, so->slirp->if_mru) - + sizeof(struct tcphdr) - sizeof(struct ip6); + break; + default: + slirplog_error("Unknown protocol"); + } + + if (offer) + mss = MIN(mss, (int)offer); + mss = MAX(mss, 32); + if (mss < tp->t_maxseg || offer != 0) + tp->t_maxseg = MIN(mss, TCP_MAXSEG_MAX); + + 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(" returning mss = %d", mss); + + return mss; } #endif diff --git a/bochs/iodev/network/slirp/tcp_output.cc b/bochs/iodev/network/slirp/tcp_output.cc index 6d963b5a19..475dda7b66 100644 --- a/bochs/iodev/network/slirp/tcp_output.cc +++ b/bochs/iodev/network/slirp/tcp_output.cc @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,472 +27,491 @@ * 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 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 "slirp.h" #if BX_NETWORKING && BX_NETMOD_SLIRP -static const 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, +static const uint8_t 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, }; #undef MAX_TCPOPTLEN -#define MAX_TCPOPTLEN 32 /* max # bytes that go in options */ +#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(struct tcpcb *tp) +int tcp_output(struct tcpcb *tp) { - struct socket *so = tp->t_socket; - long len, win; - int off, flags, error; - struct mbuf *m; - 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; + struct socket *so = tp->t_socket; + long len, win; + int off, flags, error; + struct mbuf *m; + struct tcpiphdr *ti, tcpiph_save; + struct ip *ip; + struct ip6 *ip6; + uint8_t opt[MAX_TCPOPTLEN]; + unsigned optlen, hdrlen; + int idle, sendalot; + + DEBUG_CALL("tcp_output"); + DEBUG_ARG("tp = %p", 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((long)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 >= (long)so->so_snd.sb_cc) - goto send; - if (tp->t_force) - goto send; - if (len >= (long)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. - */ - long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) - - (tp->rcv_adv - tp->rcv_nxt); - - if (adv >= (long) (2 * tp->t_maxseg)) - goto send; - if (2 * adv >= (long) 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. - */ - return (0); + 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(" --- tcp_output flags = 0x%x",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((long)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 >= (long)so->so_snd.sb_cc) + goto send; + if (tp->t_force) + goto send; + if (len >= (long)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. + */ + long adv = MIN(win, (long)TCP_MAXWIN << tp->rcv_scale) - + (tp->rcv_adv - tp->rcv_nxt); + + if (adv >= (long) (2 * tp->t_maxseg)) + goto send; + if (2 * adv >= (long) 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. + */ + 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) { - uint16_t mss; - - opt[0] = TCPOPT_MAXSEG; - opt[1] = 4; - mss = htons((uint16_t) tcp_mss(tp, 0)); - memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss)); - optlen = 4; - } - } - - hdrlen += optlen; - - /* - * Adjust data length if insertion of options will - * bump the packet length beyond the t_maxseg length. - */ - if (len > (long)(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) { - m = m_get(so->slirp); - if (m == NULL) { - error = 1; - goto out; - } - m->m_data += IF_MAXLINKHDR; - m->m_len = hdrlen; - - sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen); - m->m_len += len; - - /* - * 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 == (long)so->so_snd.sb_cc) - flags |= TH_PUSH; - } else { - m = m_get(so->slirp); - if (m == NULL) { - 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 < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg) - win = 0; - if (win > (long)TCP_MAXWIN << tp->rcv_scale) - win = (long)TCP_MAXWIN << tp->rcv_scale; - if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) - win = (long)(tp->rcv_adv - tp->rcv_nxt); - ti->ti_win = htons((uint16_t) (win>>tp->rcv_scale)); - - if (SEQ_GT(tp->snd_up, tp->snd_una)) { - ti->ti_urp = htons((uint16_t)(tp->snd_up - ntohl(ti->ti_seq))); - 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((uint16_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; - } - } - - /* - * 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 = m->m_len; - - ((struct ip *)ti)->ip_ttl = IPDEFTTL; - ((struct ip *)ti)->ip_tos = so->so_iptos; - - error = ip_output(so, m); + /* + * 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) { + uint16_t mss; + + opt[0] = TCPOPT_MAXSEG; + opt[1] = 4; + mss = htons((uint16_t) tcp_mss(tp, 0)); + memcpy((char *)(opt + 2), (char *)&mss, sizeof(mss)); + optlen = 4; + } } - if (error) { + + hdrlen += optlen; + + /* + * Adjust data length if insertion of options will + * bump the packet length beyond the t_maxseg length. + */ + if (len > (long)(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) { + m = m_get(so->slirp); + if (m == NULL) { + error = 1; + goto out; + } + m->m_data += IF_MAXLINKHDR; + m->m_len = hdrlen; + + sbcopy(&so->so_snd, off, (int) len, mtod(m, char *) + hdrlen); + m->m_len += len; + + /* + * 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 == (long)so->so_snd.sb_cc) + flags |= TH_PUSH; + } else { + m = m_get(so->slirp); + if (m == NULL) { + error = 1; + goto out; + } + m->m_data += IF_MAXLINKHDR; + m->m_len = hdrlen; + } + + ti = mtod(m, struct tcpiphdr *); + + memcpy((char *)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((char *)(ti + 1), (char *)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 < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg) + win = 0; + if (win > (long)TCP_MAXWIN << tp->rcv_scale) + win = (long)TCP_MAXWIN << tp->rcv_scale; + if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) + win = (long)(tp->rcv_adv - tp->rcv_nxt); + ti->ti_win = htons((uint16_t) (win>>tp->rcv_scale)); + + if (SEQ_GT(tp->snd_up, tp->snd_una)) { + ti->ti_urp = htons((uint16_t)(tp->snd_up - ntohl(ti->ti_seq))); + 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((uint16_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; + } + } + + /* + * 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 */ + tcpiph_save = *mtod(m, struct tcpiphdr *); + + switch (so->so_ffamily) { + case AF_INET: + m->m_data += + sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip); + m->m_len -= + sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip); + ip = mtod(m, struct ip *); + + ip->ip_len = m->m_len; + ip->ip_dst = tcpiph_save.ti_dst; + ip->ip_src = tcpiph_save.ti_src; + ip->ip_p = tcpiph_save.ti_pr; + + ip->ip_ttl = IPDEFTTL; + ip->ip_tos = so->so_iptos; + error = ip_output(so, m); + break; + + case AF_INET6: + m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - + sizeof(struct ip6); + m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - + sizeof(struct ip6); + ip6 = mtod(m, struct ip6 *); + + ip6->ip_pl = tcpiph_save.ti_len; + ip6->ip_dst = tcpiph_save.ti_dst6; + ip6->ip_src = tcpiph_save.ti_src6; + ip6->ip_nh = tcpiph_save.ti_nh6; + + error = ip6_output(so, m, 0); + break; + + default: + slirplog_error("Unknown protocol"); + } + + if (error) { out: - return (error); - } - - /* - * 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); + return (error); + } + + /* + * 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(struct tcpcb *tp) +void tcp_setpersist(struct tcpcb *tp) { int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; - /* - * 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++; + 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++; } #endif diff --git a/bochs/iodev/network/slirp/tcp_subr.cc b/bochs/iodev/network/slirp/tcp_subr.cc index efbccbfd21..3d7fca9d56 100644 --- a/bochs/iodev/network/slirp/tcp_subr.cc +++ b/bochs/iodev/network/slirp/tcp_subr.cc @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,16 +27,13 @@ * 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 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. */ #include "slirp.h" @@ -52,10 +47,9 @@ /* * Tcp initialization */ -void -tcp_init(Slirp *slirp) +void tcp_init(Slirp *slirp) { - slirp->tcp_iss = 1; /* wrong */ + slirp->tcp_iss = 1; /* wrong */ slirp->tcb.so_next = slirp->tcb.so_prev = &slirp->tcb; slirp->tcp_last_so = &slirp->tcb; } @@ -67,35 +61,45 @@ void tcp_cleanup(Slirp *slirp) } } -/* - * 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. - */ -void -tcp_template(struct tcpcb *tp) +void tcp_template(struct tcpcb *tp) { - struct socket *so = tp->t_socket; - struct tcpiphdr *n = &tp->t_template; - - n->ti_mbuf = NULL; - 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; + struct socket *so = tp->t_socket; + struct tcpiphdr *n = &tp->t_template; + + n->ti_mbuf = NULL; + memset(&n->ti, 0, sizeof(n->ti)); + n->ti_x0 = 0; + switch (so->so_ffamily) { + case AF_INET: + n->ti_pr = IPPROTO_TCP; + n->ti_len = htons(sizeof(struct tcphdr)); + n->ti_src = so->so_faddr; + n->ti_dst = so->so_laddr; + n->ti_sport = so->so_fport; + n->ti_dport = so->so_lport; + break; + + case AF_INET6: + n->ti_nh6 = IPPROTO_TCP; + n->ti_len = htons(sizeof(struct tcphdr)); + n->ti_src6 = so->so_faddr6; + n->ti_dst6 = so->so_laddr6; + n->ti_sport = so->so_fport6; + n->ti_dport = so->so_lport6; + break; + + default: + slirplog_error("Unknown protocol"); + } + + 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; } /* @@ -111,169 +115,218 @@ tcp_template(struct tcpcb *tp) * In any case the ack and sequence number of the transmitted * segment are as specified by the parameters. */ -void -tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, - tcp_seq ack, tcp_seq seq, int flags) +void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, + tcp_seq ack, tcp_seq seq, int flags, unsigned short af) { - int tlen; - int win = 0; - - DEBUG_CALL("tcp_respond"); - DEBUG_ARG("tp = %p", tp); - DEBUG_ARG("ti = %p", ti); - DEBUG_ARG("m = %p", 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 == NULL) { - if (!tp || (m = m_get(tp->t_socket->slirp)) == NULL) - return; - tlen = 0; - 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, uint32_t); - xchg(ti->ti_dport, ti->ti_sport, uint16_t); + int tlen; + int win = 0; + + DEBUG_CALL("tcp_respond"); + DEBUG_ARG("tp = %p", tp); + DEBUG_ARG("ti = %p", ti); + DEBUG_ARG("m = %p", 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 == NULL) { + if (!tp || (m = m_get(tp->t_socket->slirp)) == NULL) + return; + tlen = 0; + m->m_data += IF_MAXLINKHDR; + *mtod(m, struct tcpiphdr *) = *ti; + ti = mtod(m, struct tcpiphdr *); + switch (af) { + case AF_INET: + ti->ti.ti_i4.ih_x1 = 0; + break; + case AF_INET6: + ti->ti.ti_i6.ih_x1 = 0; + break; + default: + slirplog_error("Unknown protocol"); + } + flags = TH_ACK; + } else { + /* + * ti points into m so the next line is just making + * the mbuf point to ti + */ + m->m_data = (char *)ti; + + m->m_len = sizeof (struct tcpiphdr); + tlen = 0; +#define xchg(a, b, type) \ + { \ + type t; \ + t = a; \ + a = b; \ + b = t; \ + } + switch (af) { + case AF_INET: + xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t); + xchg(ti->ti_dport, ti->ti_sport, uint16_t); + break; + case AF_INET6: + xchg(ti->ti_dst6, ti->ti_src6, struct in6_addr); + xchg(ti->ti_dport, ti->ti_sport, uint16_t); + break; + default: + slirplog_error("Unknown protocol"); + } #undef xchg - } - ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen)); - tlen += sizeof (struct tcpiphdr); - m->m_len = tlen; + } + ti->ti_len = htons((uint16_t)(sizeof (struct tcphdr) + tlen)); + tlen += sizeof (struct tcpiphdr); + m->m_len = tlen; ti->ti_mbuf = NULL; - 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((uint16_t) (win >> tp->rcv_scale)); - else - ti->ti_win = htons((uint16_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 = IPDEFTTL; - - (void) ip_output((struct socket *)0, m); + ti->ti_x0 = 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((uint16_t) (win >> tp->rcv_scale)); + else + ti->ti_win = htons((uint16_t)win); + ti->ti_urp = 0; + ti->ti_sum = 0; + ti->ti_sum = cksum(m, tlen); + + struct tcpiphdr tcpiph_save = *(mtod(m, struct tcpiphdr *)); + struct ip *ip; + struct ip6 *ip6; + + switch (af) { + case AF_INET: + m->m_data += + sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip); + m->m_len -= + sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip); + ip = mtod(m, struct ip *); + ip->ip_len = m->m_len; + ip->ip_dst = tcpiph_save.ti_dst; + ip->ip_src = tcpiph_save.ti_src; + ip->ip_p = tcpiph_save.ti_pr; + + if (flags & TH_RST) { + ip->ip_ttl = MAXTTL; + } else { + ip->ip_ttl = IPDEFTTL; + } + + ip_output(NULL, m); + break; + + case AF_INET6: + m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - + sizeof(struct ip6); + m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - + sizeof(struct ip6); + ip6 = mtod(m, struct ip6 *); + ip6->ip_pl = tcpiph_save.ti_len; + ip6->ip_dst = tcpiph_save.ti_dst6; + ip6->ip_src = tcpiph_save.ti_src6; + ip6->ip_nh = tcpiph_save.ti_nh6; + + ip6_output(NULL, m, 0); + break; + + default: + slirplog_error("Unknown protocol"); + } } -/* - * 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) +struct tcpcb *tcp_newtcpcb(struct socket *so) { - struct tcpcb *tp; + struct tcpcb *tp; - tp = (struct tcpcb *)malloc(sizeof(*tp)); - if (tp == NULL) - return ((struct tcpcb *)0); + 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 = (struct tcpiphdr*)tp; - tp->t_maxseg = TCP_MSS; + memset((char *) tp, 0, sizeof(struct tcpcb)); + tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp; + /* + * 40: length of IPv4 header (20) + TCP header (20) + * 60: length of IPv6 header (40) + TCP header (20) + */ + tp->t_maxseg = + MIN(so->slirp->if_mtu - ((so->so_ffamily == AF_INET) ? 40 : 60), + TCP_MAXSEG_MAX); - tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; - tp->t_socket = so; + 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 = TCPTV_SRTTDFLT << 2; - tp->t_rttmin = TCPTV_MIN; + /* + * 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 = TCPTV_SRTTDFLT << 2; + tp->t_rttmin = TCPTV_MIN; - TCPT_RANGESET(tp->t_rxtcur, - ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1, - TCPTV_MIN, TCPTV_REXMTMAX); + 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; + 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; + so->so_tcpcb = tp; - return (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) { - 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); - } - return (tcp_close(tp)); + DEBUG_CALL("tcp_drop"); + DEBUG_ARG("tp = %p", tp); + DEBUG_ARG("errno = %d", errno); + + if (TCPS_HAVERCVDSYN(tp->t_state)) { + tp->t_state = TCPS_CLOSED; + tcp_output(tp); + } + 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(struct tcpcb *tp) +struct tcpcb *tcp_close(struct tcpcb *tp) { - struct tcpiphdr *t; - struct socket *so = tp->t_socket; - Slirp *slirp = so->slirp; - struct mbuf *m; - - DEBUG_CALL("tcp_close"); - DEBUG_ARG("tp = %lx", (long )tp); - - /* free the reassembly queue, if any */ - t = tcpfrag_list_first(tp); - while (!tcpfrag_list_end(t, tp)) { - t = tcpiphdr_next(t); - m = tcpiphdr_prev(t)->ti_mbuf; - remque(tcpiphdr2qlink(tcpiphdr_prev(t))); - m_free(m); - } - free(tp); - so->so_tcpcb = NULL; - /* clobber input socket cache if we're closing the cached connection */ - if (so == slirp->tcp_last_so) - slirp->tcp_last_so = &slirp->tcb; - closesocket(so->s); - sbfree(&so->so_rcv); - sbfree(&so->so_snd); - sofree(so); - return ((struct tcpcb *)0); + struct tcpiphdr *t; + struct socket *so = tp->t_socket; + Slirp *slirp = so->slirp; + struct mbuf *m; + + DEBUG_CALL("tcp_close"); + DEBUG_ARG("tp = %p", tp); + + /* free the reassembly queue, if any */ + t = tcpfrag_list_first(tp); + while (!tcpfrag_list_end(t, tp)) { + t = tcpiphdr_next(t); + m = tcpiphdr_prev(t)->ti_mbuf; + slirp_remque(tcpiphdr2qlink(tcpiphdr_prev(t))); + m_free(m); + } + free(tp); + so->so_tcpcb = NULL; +/* clobber input socket cache if we're closing the cached connection */ + if (so == slirp->tcp_last_so) + slirp->tcp_last_so = &slirp->tcb; + so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); + closesocket(so->s); + sbfree(&so->so_rcv); + sbfree(&so->so_snd); + sofree(so); + return ((struct tcpcb *)0); } /* @@ -290,38 +343,36 @@ tcp_close(struct tcpcb *tp) * 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) +void tcp_sockclosed(struct tcpcb *tp) { + DEBUG_CALL("tcp_sockclosed"); + DEBUG_ARG("tp = %p", tp); + + if (!tp) { + return; + } - 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; - } - if (tp) - tcp_output(tp); + switch (tp->t_state) { + case TCPS_CLOSED: + case TCPS_LISTEN: + case TCPS_SYN_SENT: + tp->t_state = TCPS_CLOSED; + tcp_close(tp); + return; + + 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; + } + 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 @@ -329,56 +380,56 @@ tcp_sockclosed(struct tcpcb *tp) * nonblocking. Connect returns after the SYN is sent, and does * not wait for ACK+SYN. */ -int tcp_fconnect(struct socket *so) +int tcp_fconnect(struct socket *so, unsigned short af) { - Slirp *slirp = so->slirp; - int ret=0; - - DEBUG_CALL("tcp_fconnect"); - DEBUG_ARG("so = %lx", (long )so); + int ret = 0; + + DEBUG_CALL("tcp_fconnect"); + DEBUG_ARG("so = %p", so); + + ret = so->s = slirp_socket(af, SOCK_STREAM, 0); + if (ret >= 0) { + ret = slirp_bind_outbound(so, af); + if (ret < 0) { + // bind failed - close socket + closesocket(so->s); + so->s = -1; + return (ret); + } + } - if( (ret = so->s = qemu_socket(AF_INET,SOCK_STREAM,0)) >= 0) { - int opt, s=so->s; - struct sockaddr_in addr; + if (ret >= 0) { + int opt, s = so->s; + struct sockaddr_storage addr; + + slirp_set_nonblock(s); + so->slirp->cb->register_poll_fd(s, so->slirp->opaque); + slirp_socket_set_fast_reuse(s); + opt = 1; + setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); + opt = 1; + setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); + + addr = so->fhost.ss; + DEBUG_CALL(" connect()ing"); + if (sotranslate_out(so, &addr) < 0) { + return -1; + } - qemu_set_nonblock(s); - socket_set_fast_reuse(s); - opt = 1; - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); - - addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { - /* It's an alias */ - if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { - if (get_dns_addr(&addr.sin_addr) < 0) - addr.sin_addr = loopback_addr; - } else { - addr.sin_addr = loopback_addr; - } - } else - addr.sin_addr = so->so_faddr; - addr.sin_port = so->so_fport; - - DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, " - "addr.sin_addr.s_addr=%.16s\n", - ntohs(addr.sin_port), inet_ntoa(addr.sin_addr))); - /* We don't care what port we get */ - ret = connect(s,(struct sockaddr *)&addr,sizeof (addr)); + /* We don't care what port we get */ + ret = connect(s, (struct sockaddr *)&addr, sockaddr_size(&addr)); - /* - * If it's not in progress, it failed, so we just return 0, - * without clearing SS_NOFDREF - */ - soisfconnecting(so); - } + /* + * If it's not in progress, it failed, so we just return 0, + * without clearing SS_NOFDREF + */ + soisfconnecting(so); + } - return(ret); + 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. @@ -392,13 +443,55 @@ void tcp_connect(struct socket *inso) { Slirp *slirp = inso->slirp; struct socket *so; - struct sockaddr_in addr; - socklen_t addrlen = sizeof(struct sockaddr_in); + struct sockaddr_storage addr; + socklen_t addrlen; struct tcpcb *tp; - int s, opt; + int s, opt, ret; + /* AF_INET6 addresses are bigger than AF_INET, so this is big enough. */ + char addrstr[INET6_ADDRSTRLEN]; + char portstr[6]; DEBUG_CALL("tcp_connect"); - DEBUG_ARG("inso = %lx", (long)inso); + DEBUG_ARG("inso = %p", inso); + switch (inso->lhost.ss.ss_family) { + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; + default: + slirplog_error("Unknown protocol"); + } + ret = getnameinfo((const struct sockaddr *) &inso->lhost.ss, addrlen, addrstr, sizeof(addrstr), portstr, sizeof(portstr), NI_NUMERICHOST|NI_NUMERICSERV); + assert(ret == 0); + DEBUG_ARG("ip = [%s]:%s", addrstr, portstr); + DEBUG_ARG("so_state = 0x%x", inso->so_state); + + /* Perform lazy guest IP address resolution if needed. */ + if (inso->so_state & SS_HOSTFWD) { + /* + * We can only reject the connection request by accepting it and + * then immediately closing it. Note that SS_FACCEPTONCE sockets can't + * get here. + */ + if (soassign_guest_addr_if_needed(inso) < 0) { + /* + * Guest address isn't available yet. We could either try to defer + * completing this connection request until the guest address is + * available, or punt. It's easier to punt. Otherwise we need to + * complicate the mechanism by which we're called to defer calling + * us again until the guest address is available. + */ + DEBUG_MISC(" guest address not available yet"); + addrlen = sizeof(addr); + s = accept(inso->s, (struct sockaddr *)&addr, &addrlen); + if (s >= 0) { + close(s); + } + return; + } + } /* * If it's an SS_ACCEPTONCE socket, no need to socreate() @@ -408,45 +501,34 @@ void tcp_connect(struct socket *inso) /* FACCEPTONCE already have a tcpcb */ so = inso; } else { - so = socreate(slirp); - if (so == 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; + so = socreate(slirp, IPPROTO_TCP); + tcp_attach(so); + so->lhost = inso->lhost; + so->so_ffamily = inso->so_ffamily; } tcp_mss(sototcpcb(so), 0); + addrlen = sizeof(addr); s = accept(inso->s, (struct sockaddr *)&addr, &addrlen); if (s < 0) { tcp_close(sototcpcb(so)); /* This will sofree() as well */ return; } - qemu_set_nonblock(s); - socket_set_fast_reuse(s); + slirp_set_nonblock(s); + so->slirp->cb->register_poll_fd(s, so->slirp->opaque); + slirp_socket_set_fast_reuse(s); opt = 1; - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); - socket_set_nodelay(s); - - 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_mask) == - (loopback_addr.s_addr & loopback_mask)) { - so->so_faddr = slirp->vhost_addr; - } + setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); + slirp_socket_set_nodelay(s); + + so->fhost.ss = addr; + sotranslate_accept(so); /* Close the accept() socket, set right state */ if (inso->so_state & SS_FACCEPTONCE) { /* If we only accept once, close the accept() socket */ + so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); closesocket(so->s); /* Don't select it yet, even though we have an FD */ @@ -469,82 +551,55 @@ void tcp_connect(struct socket *inso) tcp_output(tp); } -/* - * Attach a TCPCB to a socket. - */ -int -tcp_attach(struct socket *so) +void tcp_attach(struct socket *so) { - if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) - return -1; - - insque(so, &so->slirp->tcb); - - return 0; + so->so_tcpcb = tcp_newtcpcb(so); + slirp_insque(so, &so->slirp->tcb); } /* * Set the socket's type of service field */ static const 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} + {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, 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} }; -static struct emu_t *tcpemu = NULL; - -/* - * Return TOS according to the above table - */ -uint8_t -tcp_tos(struct socket *so) +uint8_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 i = 0; + + 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))) { + if (so->slirp->enable_emu) + so->so_emu = tcptos[i].emu; + return tcptos[i].tos; + } + i++; + } + return 0; } /* - * 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 If there is more than one command in the packet, the others may + * be truncated. + * XXX If the command is too long, it may be truncated. * * XXX Some ftp clients will have their TOS set to * LOWDELAY and so Nagel will kick in. Because of this, @@ -558,338 +613,344 @@ tcp_tos(struct socket *so) * * NOTE: if you return 0 you MUST m_free() the mbuf! */ -int -tcp_emu(struct socket *so, struct mbuf *m) +int tcp_emu(struct socket *so, struct mbuf *m) { - Slirp *slirp = so->slirp; - u_int n1, n2, n3, n4, n5, n6; + Slirp *slirp = so->slirp; + unsigned n1, n2, n3, n4, n5, n6; char buff[257]; - uint32_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, "%u%*[ ,]%u", &n1, &n2) == 2) { - HTONS(n1); - HTONS(n2); - /* n2 is the one on our host */ - for (tmpso = slirp->tcb.so_next; - tmpso != &slirp->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 = snprintf(so_rcv->sb_data, - so_rcv->sb_datalen, - "%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; - } + uint32_t laddr; + unsigned lport; + char *bptr; + + DEBUG_CALL("tcp_emu"); + DEBUG_ARG("so = %p", so); + DEBUG_ARG("m = %p", m); + + switch(so->so_emu) { + int x, i; + + /* TODO: IPv6 */ + 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, "%u%*[ ,]%u", &n1, &n2) == 2) { + HTONS(n1); + HTONS(n2); + /* n2 is the one on our host */ + for (tmpso = slirp->tcb.so_next; tmpso != &slirp->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 = addr.sin_port; + break; + } + } + NTOHS(n1); + NTOHS(n2); + } + so_rcv->sb_cc = snprintf(so_rcv->sb_data, so_rcv->sb_datalen, + "%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; + } case EMU_FTP: /* ftp */ - *(m->m_data+m->m_len) = 0; /* NUL terminate for strstr */ - if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) { - /* - * Need to emulate the PORT command - */ - x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\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 = tcp_listen(slirp, INADDR_ANY, 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 += snprintf(bptr, m->m_size - m->m_len, - "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 (%u,%u,%u,%u,%u,%u)\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 = tcp_listen(slirp, INADDR_ANY, 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 += snprintf(bptr, m->m_size - m->m_len, - "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 < 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 = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, - htons(lport), SS_FACCEPTONCE)) != NULL) - m->m_len = snprintf(m->m_data, m->m_size, "%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 = tcp_listen(slirp, INADDR_ANY, 0, - htonl(laddr), htons(lport), - SS_FACCEPTONCE)) == NULL) { - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += snprintf(bptr, m->m_size, - "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 = tcp_listen(slirp, INADDR_ANY, 0, - htonl(laddr), htons(lport), - SS_FACCEPTONCE)) == NULL) { - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += snprintf(bptr, m->m_size, - "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 = tcp_listen(slirp, INADDR_ANY, 0, - htonl(laddr), htons(lport), - SS_FACCEPTONCE)) == NULL) { - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += snprintf(bptr, m->m_size, - "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: + m_inc(m, m->m_len + 1); + *(m->m_data+m->m_len) = 0; /* NUL terminate for strstr */ + if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) { + /* + * Need to emulate the PORT command + */ + x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\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 = tcp_listen(slirp, INADDR_ANY, 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 += slirp_fmt(bptr, M_FREEROOM(m), + "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 (%u,%u,%u,%u,%u,%u)\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 = tcp_listen(slirp, INADDR_ANY, 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 += slirp_fmt(bptr, M_FREEROOM(m), + "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 < 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 = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, + htons(lport), SS_FACCEPTONCE)) != NULL) + m->m_len = slirp_fmt0(m->m_data, M_ROOM(m), + "%d", ntohs(so->so_fport)); + return 1; + + case EMU_IRC: + /* + * Need to emulate DCC CHAT, DCC SEND and DCC MOVE + */ + m_inc(m, m->m_len + 1); + *(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 = tcp_listen(slirp, INADDR_ANY, 0, htonl(laddr), + htons(lport), SS_FACCEPTONCE)) == NULL) { + return 1; + } + m->m_len = bptr - m->m_data; /* Adjust length */ + m->m_len += slirp_fmt(bptr, M_FREEROOM(m), + "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 = tcp_listen(slirp, INADDR_ANY, 0, htonl(laddr), + htons(lport), SS_FACCEPTONCE)) == NULL) { + return 1; + } + m->m_len = bptr - m->m_data; /* Adjust length */ + m->m_len += slirp_fmt(bptr, M_FREEROOM(m), + "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 = tcp_listen(slirp, INADDR_ANY, 0, htonl(laddr), + htons(lport), SS_FACCEPTONCE)) == NULL) { + return 1; + } + m->m_len = bptr - m->m_data; /* Adjust length */ + m->m_len += slirp_fmt(bptr, M_FREEROOM(m), + "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(slirp, INADDR_ANY, - 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; - } + * 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) { + uint16_t 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: + if (bptr == m->m_data + m->m_len - 1) + return 1; /* We need two bytes */ + + /* + * 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. + */ + + if (bptr == m->m_data + m->m_len - 1) + return 1; /* We need two bytes */ + + lport = (((uint8_t*)bptr)[0] << 8) + ((uint8_t *)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(slirp, INADDR_ANY, htons(p), + so->so_laddr.s_addr, htons(lport), + SS_FACCEPTONCE)) { + break; + } + } + if (p == 7071) + p = 0; + *(uint8_t *)bptr++ = (p >> 8) & 0xff; + *(uint8_t *)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; + } } /* @@ -901,31 +962,32 @@ int tcp_ctl(struct socket *so) { Slirp *slirp = so->slirp; struct sbuf *sb = &so->so_snd; - struct ex_list *ex_ptr; - int do_pty; + struct gfwd_list *ex_ptr; DEBUG_CALL("tcp_ctl"); - DEBUG_ARG("so = %lx", (long )so); + DEBUG_ARG("so = %p", so); + /* TODO: IPv6 */ if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) { /* Check if it's pty_exec */ - for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_fport == so->so_fport && so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) { - if (ex_ptr->ex_pty == 3) { + if (ex_ptr->write_cb) { so->s = -1; - so->extra = (void *)ex_ptr->ex_exec; + so->guestfwd = ex_ptr; return 1; } - do_pty = ex_ptr->ex_pty; - DEBUG_MISC((dfd, " executing %s\n", ex_ptr->ex_exec)); - return fork_exec(so, ex_ptr->ex_exec, do_pty); + DEBUG_MISC(" executing %s", ex_ptr->ex_exec); + if (ex_ptr->ex_unix) + return open_unix(so, ex_ptr->ex_unix); + else + return fork_exec(so, ex_ptr->ex_exec); } } } - sb->sb_cc = - snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data), - "Error: No application configured.\r\n"); + sb->sb_cc = slirp_fmt(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data), + "Error: No application configured.\r\n"); sb->sb_wptr += sb->sb_cc; return 0; } diff --git a/bochs/iodev/network/slirp/tcp_timer.cc b/bochs/iodev/network/slirp/tcp_timer.cc index 9311c56a82..8fc0044a52 100644 --- a/bochs/iodev/network/slirp/tcp_timer.cc +++ b/bochs/iodev/network/slirp/tcp_timer.cc @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,7 +27,7 @@ * 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 8.1 (Berkeley) 6/10/93 * tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp */ @@ -42,23 +40,22 @@ static struct tcpcb *tcp_timers(struct tcpcb *tp, int timer); /* * Fast timeout routine for processing delayed acks */ -void -tcp_fasttimo(Slirp *slirp) +void tcp_fasttimo(Slirp *slirp) { - struct socket *so; - struct tcpcb *tp; + struct socket *so; + struct tcpcb *tp; - DEBUG_CALL("tcp_fasttimo"); + DEBUG_CALL("tcp_fasttimo"); - so = slirp->tcb.so_next; - if (so) - for (; so != &slirp->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; - (void) tcp_output(tp); - } + so = slirp->tcb.so_next; + if (so) + for (; so != &slirp->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; + tcp_output(tp); + } } /* @@ -66,234 +63,225 @@ tcp_fasttimo(Slirp *slirp) * Updates the timers in all active tcb's and * causes finite state machine actions if timers expire. */ -void -tcp_slowtimo(Slirp *slirp) +void tcp_slowtimo(Slirp *slirp) { - struct socket *ip, *ipnxt; - struct tcpcb *tp; - int i; + struct socket *ip, *ipnxt; + struct tcpcb *tp; + int i; - DEBUG_CALL("tcp_slowtimo"); + DEBUG_CALL("tcp_slowtimo"); - /* - * Search through tcb's and update active timers. - */ - ip = slirp->tcb.so_next; - if (ip == NULL) { - return; + /* + * Search through tcb's and update active timers. + */ + ip = slirp->tcb.so_next; + if (ip == NULL) { + return; + } + for (; ip != &slirp->tcb; ip = ipnxt) { + ipnxt = ip->so_next; + tp = sototcpcb(ip); + if (tp == NULL) { + continue; } - for (; ip != &slirp->tcb; ip = ipnxt) { - ipnxt = ip->so_next; - tp = sototcpcb(ip); - if (tp == NULL) { - 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: - ; - } - slirp->tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ - slirp->tcp_now++; /* for timestamps */ + 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:; + } + slirp->tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ + slirp->tcp_now++; /* for timestamps */ } -/* - * Cancel all timers for TCP tp. - */ -void -tcp_canceltimers(struct tcpcb *tp) +void tcp_canceltimers(struct tcpcb *tp) { - int i; + int i; - for (i = 0; i < TCPT_NTIMERS; i++) - tp->t_timer[i] = 0; + for (i = 0; i < TCPT_NTIMERS; i++) + tp->t_timer[i] = 0; } -const int tcp_backoff[TCP_MAXRXTSHIFT + 1] = - { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; +const int tcp_backoff[TCP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, + 64, 64, 64, 64, 64, 64 }; /* * TCP timer processing. */ -static struct tcpcb * -tcp_timers(struct tcpcb *tp, int timer) +static struct tcpcb *tcp_timers(struct tcpcb *tp, int timer) { - int rexmt; - - DEBUG_CALL("tcp_timers"); + int rexmt; - switch (timer) { + DEBUG_CALL("tcp_timers"); - /* - * 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] = TCPTV_KEEPINTVL; - else - tp = tcp_close(tp); - break; + 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] = TCPTV_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: + /* + * 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. - */ + /* + * 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* - */ + 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; - tp = tcp_drop(tp, tp->t_softerror); - /* tp->t_softerror : ETIMEDOUT); */ /* XXX */ - return (tp); /* XXX */ - } + tp->t_maxseg >>= 1; + if (tp->t_maxseg < 32) { + /* + * We tried our best, now the connection must die! + */ + tp->t_rxtshift = TCP_MAXRXTSHIFT; + 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; - } - 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) { - 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; + /* + * Set rxtshift to 6, which is still at the maximum + * backoff time + */ + tp->t_rxtshift = 6; + } + 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) { + 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.) + */ + { + unsigned 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; + } + tcp_output(tp); + break; - /* - * Persistence timer into zero window. - * Force a byte to be output, if possible. - */ - case TCPT_PERSIST: - tcp_setpersist(tp); - tp->t_force = 1; - (void) tcp_output(tp); - tp->t_force = 0; - break; + /* + * Persistence timer into zero window. + * Force a byte to be output, if possible. + */ + case TCPT_PERSIST: + tcp_setpersist(tp); + tp->t_force = 1; + 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: - if (tp->t_state < TCPS_ESTABLISHED) - goto dropit; + /* + * Keep-alive timer went off; send something + * or drop connection if idle for too long. + */ + case TCPT_KEEP: + if (tp->t_state < TCPS_ESTABLISHED) + goto dropit; - if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) { - if (tp->t_idle >= TCPTV_KEEP_IDLE + 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. - */ - tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, - tp->rcv_nxt, tp->snd_una - 1, 0); - tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; - } else - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; - break; + if (slirp_do_keepalive && tp->t_state <= TCPS_CLOSE_WAIT) { + if (tp->t_idle >= TCPTV_KEEP_IDLE + 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. + */ + tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, tp->rcv_nxt, + tp->snd_una - 1, 0, tp->t_socket->so_ffamily); + tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; + } else + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; + break; - dropit: - tp = tcp_drop(tp, 0); - break; - } + dropit: + tp = tcp_drop(tp, 0); + break; + } - return (tp); + return (tp); } #endif diff --git a/bochs/iodev/network/slirp/tcp_timer.h b/bochs/iodev/network/slirp/tcp_timer.h index ad64f1518e..8cb7e964db 100644 --- a/bochs/iodev/network/slirp/tcp_timer.h +++ b/bochs/iodev/network/slirp/tcp_timer.h @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,23 +27,23 @@ * 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 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_ +#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_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 */ +#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. @@ -76,7 +74,7 @@ * 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 @@ -88,22 +86,23 @@ */ #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_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_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_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 ( 12*PR_SLOWHZ) /* max allowable REXMT value */ +#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */ +#define TCPTV_REXMTMAX ( 12*PR_SLOWHZ) /* max allowable REXMT value */ -#define TCP_LINGERTIME 120 /* linger at most 2 minutes */ +#define TCP_LINGERTIME 120 /* linger at most 2 minutes */ #define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ @@ -111,20 +110,24 @@ /* * 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); \ -} +#define TCPT_RANGESET(tv, value, tvmin, tvmax) \ + { \ + (tv) = (value); \ + if ((tv) < (tvmin)) \ + (tv) = (tvmin); \ + else if ((tv) > (tvmax)) \ + (tv) = (tvmax); \ + } extern const int tcp_backoff[]; struct tcpcb; +/* Process fast time-outs */ void tcp_fasttimo(Slirp *); +/* Process slow time-outs */ void tcp_slowtimo(Slirp *); +/* Cancel all timers for TCP tp */ void tcp_canceltimers(struct tcpcb *); #endif diff --git a/bochs/iodev/network/slirp/tcp_var.h b/bochs/iodev/network/slirp/tcp_var.h index a09f6adfc8..604c8bcdf6 100644 --- a/bochs/iodev/network/slirp/tcp_var.h +++ b/bochs/iodev/network/slirp/tcp_var.h @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1993, 1994 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,12 +27,12 @@ * 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 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_ +#ifndef TCP_VAR_H +#define TCP_VAR_H #include "tcpip.h" #include "tcp_timer.h" @@ -43,93 +41,93 @@ * Tcp control block, one per tcp; fields: */ struct tcpcb { - struct tcpiphdr *seg_next; /* sequencing queue */ - struct tcpiphdr *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 */ + struct tcpiphdr *seg_next; /* sequencing queue */ + struct tcpiphdr *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 */ + uint16_t t_maxseg; /* maximum segment size */ + uint8_t t_force; /* 1 if forcing out a byte */ + uint16_t 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 */ - struct tcpiphdr t_template; /* static skeletal packet for xmit */ + struct tcpiphdr t_template; /* static skeletal packet for xmit */ - struct socket *t_socket; /* back pointer to socket */ + 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 */ - uint32_t snd_wnd; /* send window */ + 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 */ + uint32_t snd_wnd; /* send window */ /* receive sequence variables */ - uint32_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 */ + uint32_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 */ + 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) */ - uint32_t snd_cwnd; /* congestion-controlled window */ - uint32_t snd_ssthresh; /* snd_cwnd size threshold for - * for slow start exponential to - * linear switch - */ + tcp_seq snd_max; /* highest sequence number sent; + * used to recognize retransmits + */ + /* congestion control (for slow start, source quench, retransmit after loss) + */ + uint32_t snd_cwnd; /* congestion-controlled window */ + uint32_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 */ - uint32_t max_sndwnd; /* largest window peer has offered */ + 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 */ + uint16_t t_rttmin; /* minimum rtt allowed */ + uint32_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 */ + /* out-of-band data */ + uint8_t t_oobflags; /* have some */ + uint8_t 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; - uint32_t ts_recent; /* timestamp echo data */ - uint32_t ts_recent_age; /* when last updated */ - tcp_seq last_ack_sent; - + uint8_t snd_scale; /* window scaling for send window */ + uint8_t rcv_scale; /* window scaling for recv window */ + uint8_t request_r_scale; /* pending window scaling */ + uint8_t requested_s_scale; + uint32_t ts_recent; /* timestamp echo data */ + uint32_t ts_recent_age; /* when last updated */ + tcp_seq last_ack_sent; }; -#define sototcpcb(so) ((so)->so_tcpcb) +#define sototcpcb(so) ((so)->so_tcpcb) /* * The smoothed round-trip time and estimated variance @@ -140,10 +138,10 @@ struct tcpcb { * 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 */ +#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. @@ -158,7 +156,6 @@ struct tcpcb { * 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) +#define TCP_REXMTVAL(tp) (((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) #endif diff --git a/bochs/iodev/network/slirp/tcpip.h b/bochs/iodev/network/slirp/tcpip.h index 1ef703aea5..222a46388a 100644 --- a/bochs/iodev/network/slirp/tcpip.h +++ b/bochs/iodev/network/slirp/tcpip.h @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,52 +27,79 @@ * 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 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_ +#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 */ + struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */ + union { + struct { + struct in_addr ih_src; /* source internet address */ + struct in_addr ih_dst; /* destination internet address */ + uint8_t ih_x1; /* (unused) */ + uint8_t ih_pr; /* protocol */ + } ti_i4; + struct { + struct in6_addr ih_src; + struct in6_addr ih_dst; + uint8_t ih_x1; + uint8_t ih_nh; + } ti_i6; + } ti; + uint16_t ti_x0; + uint16_t ti_len; /* protocol length */ + struct tcphdr ti_t; /* tcp header */ }; -#define ti_mbuf ti_i.ih_mbuf.mptr -#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 +#define ti_mbuf ih_mbuf.mptr +#define ti_pr ti.ti_i4.ih_pr +#define ti_src ti.ti_i4.ih_src +#define ti_dst ti.ti_i4.ih_dst +#define ti_src6 ti.ti_i6.ih_src +#define ti_dst6 ti.ti_i6.ih_dst +#define ti_nh6 ti.ti_i6.ih_nh +#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 -#define tcpiphdr2qlink(T) ((struct qlink*)(((char*)(T)) - sizeof(struct qlink))) -#define qlink2tcpiphdr(Q) ((struct tcpiphdr*)(((char*)(Q)) + sizeof(struct qlink))) +#define tcpiphdr2qlink(T) \ + ((struct qlink *)(((char *)(T)) - sizeof(struct qlink))) +#define qlink2tcpiphdr(Q) \ + ((struct tcpiphdr *)(((char *)(Q)) + sizeof(struct qlink))) #define tcpiphdr_next(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->next) #define tcpiphdr_prev(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->prev) #define tcpfrag_list_first(T) qlink2tcpiphdr((T)->seg_next) -#define tcpfrag_list_end(F, T) (tcpiphdr2qlink(F) == (struct qlink*)(T)) -#define tcpfrag_list_empty(T) ((T)->seg_next == (struct tcpiphdr*)(T)) +#define tcpfrag_list_end(F, T) (tcpiphdr2qlink(F) == (struct qlink *)(T)) +#define tcpfrag_list_empty(T) ((T)->seg_next == (struct tcpiphdr *)(T)) + +/* This is the difference between the size of a tcpiphdr structure, and the + * size of actual ip+tcp headers, rounded up since we need to align data. */ +#define TCPIPHDR_DELTA \ + (MAX(0, ((int) sizeof(struct qlink) + \ + (int) sizeof(struct tcpiphdr) - (int) sizeof(struct ip) - \ + (int) sizeof(struct tcphdr) + 7) & \ + ~7)) /* * Just a clean way to get to the first byte * of the packet */ struct tcpiphdr_2 { - struct tcpiphdr dummy; - char first_char; + struct tcpiphdr dummy; + char first_char; }; #endif diff --git a/bochs/iodev/network/slirp/tftp.cc b/bochs/iodev/network/slirp/tftp.cc index 443d06bf16..258ff0daa2 100644 --- a/bochs/iodev/network/slirp/tftp.cc +++ b/bochs/iodev/network/slirp/tftp.cc @@ -1,11 +1,10 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: MIT */ /* - * A simple TFTP server (ported from Qemu) + * tftp.c - a simple, read-only tftp server for qemu * Bochs additions: write support, 'blksize' and 'timeout' options * - * Copyright (c) 2004 Magnus Damm + * Copyright (C) 2004 Magnus Damm + * Copyright (C) 2014-2024 The Bochs Project * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,6 +29,10 @@ #if BX_NETWORKING && BX_NETMOD_SLIRP +#include +#include +#include + // Missing defines for open (copied from osdep.h) #ifndef S_IRUSR #define S_IRUSR 0400 @@ -40,21 +43,6 @@ #define S_IWGRP 0020 #endif -// internal TFTP defines -#define TFTP_RRQ 1 -#define TFTP_WRQ 2 -#define TFTP_DATA 3 -#define TFTP_ACK 4 -#define TFTP_ERROR 5 -#define TFTP_OPTACK 6 - -#define TFTP_FILENAME_MAX 512 - -#define TFTP_OPTION_OCTET 0x1 -#define TFTP_OPTION_BLKSIZE 0x2 -#define TFTP_OPTION_TSIZE 0x4 -#define TFTP_OPTION_TIMEOUT 0x8 - #define TFTP_DEFAULT_BLKSIZE 512 #define TFTP_DEFAULT_TIMEOUT 5 @@ -78,60 +66,76 @@ static void tftp_session_terminate(struct tftp_session *spt) spt->slirp = NULL; } -static tftp_session *tftp_session_allocate(Slirp *slirp, struct tftp_t *tp) +static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas, + struct tftphdr *hdr) { - struct tftp_session *spt; - int k; + struct tftp_session *spt; + int k; - for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &slirp->tftp_sessions[k]; + for (k = 0; k < TFTP_SESSIONS_MAX; k++) { + spt = &slirp->tftp_sessions[k]; - if (!tftp_session_in_use(spt)) - goto found; + if (!tftp_session_in_use(spt)) + goto found; - /* sessions time out after 5 inactive seconds */ - if ((curtime - spt->timestamp) > (spt->timeout_val * 1000)) { - tftp_session_terminate(spt); - goto found; + /* sessions time out after 5 inactive seconds */ + if ((curtime - spt->timestamp) > (spt->timeout_val * 1000)) { + tftp_session_terminate(spt); + goto found; + } } - } - return NULL; + return -1; - found: - memset(spt, 0, sizeof(*spt)); - memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); - spt->fd = -1; - spt->client_port = tp->udp.uh_sport; - spt->slirp = slirp; - spt->write = (ntohs(tp->tp_op) == TFTP_WRQ); - spt->options = 0; - spt->blksize_val = TFTP_DEFAULT_BLKSIZE; - spt->timeout_val = TFTP_DEFAULT_TIMEOUT; +found: + memset(spt, 0, sizeof(*spt)); + memcpy(&spt->client_addr, srcsas, sockaddr_size(srcsas)); + spt->fd = -1; + spt->client_port = hdr->udp.uh_sport; + spt->slirp = slirp; + spt->write = (ntohs(hdr->tp_op) == TFTP_WRQ); + spt->nb_options = 0; + spt->blksize_val = TFTP_DEFAULT_BLKSIZE; + spt->timeout_val = TFTP_DEFAULT_TIMEOUT; - tftp_session_update(spt); + tftp_session_update(spt); + + return k; +} + +static int tftp_session_find(Slirp *slirp, struct sockaddr_storage *srcsas, + struct tftphdr *hdr) +{ + struct tftp_session *spt; + int k; + + for (k = 0; k < TFTP_SESSIONS_MAX; k++) { + spt = &slirp->tftp_sessions[k]; + + if (tftp_session_in_use(spt)) { + if (sockaddr_equal(&spt->client_addr, srcsas)) { + if (spt->client_port == hdr->udp.uh_sport) { + return k; + } + } + } + } - return spt; + return -1; } -static tftp_session *tftp_session_find(Slirp *slirp, struct tftp_t *tp) +void tftp_cleanup(Slirp *slirp) { - struct tftp_session *spt; - int k; + struct tftp_session *spt; + int k; - for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &slirp->tftp_sessions[k]; + for (k = 0; k < TFTP_SESSIONS_MAX; k++) { + spt = &slirp->tftp_sessions[k]; - if (tftp_session_in_use(spt)) { - if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) { - if (spt->client_port == tp->udp.uh_sport) { - return spt; + if (tftp_session_in_use(spt)) { + tftp_session_terminate(spt); } - } } - } - - return NULL; } static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr, @@ -148,7 +152,9 @@ static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr, } if (len) { - lseek(spt->fd, block_nr * spt->blksize_val, SEEK_SET); + if (lseek(spt->fd, block_nr * spt->blksize_val, SEEK_SET) == (off_t)-1) { + return -1; + } bytes_read = read(spt->fd, buf, len); } @@ -156,54 +162,70 @@ static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr, return bytes_read; } -static int tftp_send_optack(struct tftp_session *spt, - struct tftp_t *recv_tp) +static struct tftp_t *tftp_prep_mbuf_data(struct tftp_session *spt, + struct mbuf *m) +{ + struct tftp_t *tp; + + memset(m->m_data, 0, m->m_size); + + m->m_data += IF_MAXLINKHDR; + if (spt->client_addr.ss_family == AF_INET6) { + m->m_data += sizeof(struct ip6); + } else { + m->m_data += sizeof(struct ip); + } + tp = (struct tftp_t *)m->m_data; + m->m_data += sizeof(struct udphdr); + + return tp; +} + +static void tftp_udp_output(struct tftp_session *spt, struct mbuf *m, + struct tftphdr *hdr) +{ + if (spt->client_addr.ss_family == AF_INET6) { + struct sockaddr_in6 sa6, da6; + + sa6.sin6_addr = spt->slirp->vhost_addr6; + sa6.sin6_port = hdr->udp.uh_dport; + da6.sin6_addr = ((struct sockaddr_in6 *)&spt->client_addr)->sin6_addr; + da6.sin6_port = spt->client_port; + + udp6_output(NULL, m, &sa6, &da6); + } else { + struct sockaddr_in sa4, da4; + + sa4.sin_addr = spt->slirp->vhost_addr; + sa4.sin_port = hdr->udp.uh_dport; + da4.sin_addr = ((struct sockaddr_in *)&spt->client_addr)->sin_addr; + da4.sin_port = spt->client_port; + + udp_output(NULL, m, &sa4, &da4, IPTOS_LOWDELAY); + } +} + +static int tftp_send_oack(struct tftp_session *spt, struct tftp_t *recv_tp) { - struct sockaddr_in saddr, daddr; struct mbuf *m; struct tftp_t *tp; - int n = 0; + int i, n = 0; m = m_get(spt->slirp); if (!m) return -1; - memset(m->m_data, 0, m->m_size); - - m->m_data += IF_MAXLINKHDR; - tp = (tftp_t*)m->m_data; - m->m_data += sizeof(struct udpiphdr); + tp = tftp_prep_mbuf_data(spt, m); - tp->tp_op = htons(TFTP_OPTACK); - if (spt->options & TFTP_OPTION_TSIZE) { - n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", - "tsize") + 1; - n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u", - (unsigned)spt->tsize_val) + 1; - } - if (spt->options & TFTP_OPTION_BLKSIZE) { - n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", - "blksize") + 1; - n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u", - (unsigned)spt->blksize_val) + 1; + tp->hdr.tp_op = htons(TFTP_OACK); + for (i = 0; i < spt->nb_options; i++) { + n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", spt->option_name[i]) + 1; + n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u", spt->option_value[i]) + 1; } - if (spt->options & TFTP_OPTION_TIMEOUT) { - n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", - "timeout") + 1; - n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u", - (unsigned)spt->timeout_val) + 1; - } - - 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; - - m->m_len = sizeof(struct tftp_t) - 514 + n - - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + m->m_len = G_SIZEOF_MEMBER(struct tftp_t, hdr.tp_op) + n; + tftp_udp_output(spt, m, &recv_tp->hdr); return 0; } @@ -211,7 +233,6 @@ static int tftp_send_optack(struct tftp_session *spt, static int tftp_send_ack(struct tftp_session *spt, struct tftp_t *recv_tp) { - struct sockaddr_in saddr, daddr; struct mbuf *m; struct tftp_t *tp; @@ -220,71 +241,49 @@ static int tftp_send_ack(struct tftp_session *spt, if (!m) return -1; - memset(m->m_data, 0, m->m_size); - - m->m_data += IF_MAXLINKHDR; - tp = (tftp_t*)m->m_data; - m->m_data += sizeof(struct udpiphdr); + tp = tftp_prep_mbuf_data(spt, m); - tp->tp_op = htons(TFTP_ACK); + tp->hdr.tp_op = htons(TFTP_ACK); tp->x.tp_data.tp_block_nr = htons(spt->block_nr & 0xffff); - 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; - - m->m_len = sizeof(struct tftp_t) - 514 + 2 - - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + m->m_len = G_SIZEOF_MEMBER(struct tftp_t, hdr.tp_op) + 2; + tftp_udp_output(spt, m, &recv_tp->hdr); return 0; } -static void tftp_send_error(struct tftp_session *spt, - uint16_t errorcode, const char *msg, - struct tftp_t *recv_tp) +static void tftp_send_error(struct tftp_session *spt, uint16_t errorcode, + const char *msg, struct tftp_t *recv_tp) { - struct sockaddr_in saddr, daddr; struct mbuf *m; struct tftp_t *tp; + DEBUG_TFTP("tftp error msg: %s", msg); + m = m_get(spt->slirp); if (!m) { goto out; } - memset(m->m_data, 0, m->m_size); - - m->m_data += IF_MAXLINKHDR; - tp = (tftp_t*)m->m_data; - m->m_data += sizeof(struct udpiphdr); + tp = tftp_prep_mbuf_data(spt, m); - tp->tp_op = htons(TFTP_ERROR); + tp->hdr.tp_op = htons(TFTP_ERROR); tp->x.tp_error.tp_error_code = htons(errorcode); - pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), msg); - - 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; - - m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) - - sizeof(struct ip) - sizeof(struct udphdr); + slirp_pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), + msg); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + 3 + + strlen(msg) - sizeof(struct udphdr); + tftp_udp_output(spt, m, &recv_tp->hdr); out: tftp_session_terminate(spt); } static void tftp_send_next_block(struct tftp_session *spt, - struct tftp_t *recv_tp) + struct tftphdr *hdr) { - struct sockaddr_in saddr, daddr; struct mbuf *m; struct tftp_t *tp; int nobytes; @@ -295,37 +294,26 @@ static void tftp_send_next_block(struct tftp_session *spt, return; } - memset(m->m_data, 0, m->m_size); + tp = tftp_prep_mbuf_data(spt, m); - m->m_data += IF_MAXLINKHDR; - tp = (tftp_t*)m->m_data; - m->m_data += sizeof(struct udpiphdr); - - tp->tp_op = htons(TFTP_DATA); + tp->hdr.tp_op = htons(TFTP_DATA); tp->x.tp_data.tp_block_nr = htons((spt->block_nr + 1) & 0xffff); - 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, spt->block_nr, tp->x.tp_data.tp_buf, spt->blksize_val); if (nobytes < 0) { - m_free(m); - /* send "file not found" error back */ tftp_send_error(spt, 1, "File not found", tp); + m_free(m); + return; } - m->m_len = sizeof(struct tftp_t) - (TFTP_BUFFER_SIZE - nobytes) - - sizeof(struct ip) - sizeof(struct udphdr); - - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX - nobytes) - + sizeof(struct udphdr); + tftp_udp_output(spt, m, hdr); if (nobytes == (int)spt->blksize_val) { tftp_session_update(spt); @@ -341,303 +329,358 @@ static void tftp_parse_options(struct tftp_session *spt, struct tftp_t *tp, int const char *key, *value; while (k < pktlen) { - key = &tp->x.tp_buf[k]; - k += strlen(key) + 1; - - if (k < pktlen) { - value = &tp->x.tp_buf[k]; - k += strlen(value) + 1; - } else { - value = NULL; - } + key = &tp->x.tp_buf[k]; + k += strlen(key) + 1; - if (strcasecmp(key, "octet") == 0) { - spt->options |= TFTP_OPTION_OCTET; - } else if (strcasecmp(key, "tsize") == 0) { - spt->options |= TFTP_OPTION_TSIZE; - if (spt->write && (value != NULL)) { - spt->tsize_val = atoi(value); - } - } else if (strcasecmp(key, "blksize") == 0) { - if (value != NULL) { - spt->options |= TFTP_OPTION_BLKSIZE; - spt->blksize_val = atoi(value); - if (spt->blksize_val > TFTP_BUFFER_SIZE) { - spt->blksize_val = TFTP_DEFAULT_BLKSIZE; - } - } - } else if (strcasecmp(key, "timeout") == 0) { - if (value != NULL) { - spt->options |= TFTP_OPTION_TIMEOUT; - spt->timeout_val = atoi(value); - if ((spt->timeout_val < 1) || (spt->timeout_val > 255)) { - spt->timeout_val = TFTP_DEFAULT_TIMEOUT; - } + if (k < pktlen) { + value = &tp->x.tp_buf[k]; + k += strlen(value) + 1; + } else { + break; + } + + if (strcasecmp(key, "tsize") == 0) { + int tsize = atoi(value); + struct stat stat_p; + + if (tsize == 0) { + if (spt->write) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } else { + if (stat(spt->filename, &stat_p) == 0) + tsize = stat_p.st_size; + else { + tftp_send_error(spt, 1, "File not found", tp); + return; } + } + } if (spt->write) { + spt->tsize_val = tsize; } + + spt->option_name[spt->nb_options] = "tsize"; + spt->option_value[spt->nb_options] = tsize; + spt->nb_options++; + } else if (strcasecmp(key, "blksize") == 0) { + int blksize = atoi(value); + spt->blksize_val = blksize; + if (spt->blksize_val > TFTP_BLOCKSIZE_MAX) { + spt->blksize_val = TFTP_DEFAULT_BLKSIZE; + } + + spt->option_name[spt->nb_options] = "blksize"; + spt->option_value[spt->nb_options] = spt->blksize_val; + spt->nb_options++; + } else if (strcasecmp(key, "timeout") == 0) { + int timeout = atoi(value); + spt->timeout_val = timeout; + if ((spt->timeout_val < 1) || (spt->timeout_val > 255)) { + spt->timeout_val = TFTP_DEFAULT_TIMEOUT; + } + + spt->option_name[spt->nb_options] = "timeout"; + spt->option_value[spt->nb_options] = spt->timeout_val; + spt->nb_options++; + } } } -static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) +static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas, + struct tftp_t *tp, int pktlen) { - struct tftp_session *spt; - int k; - size_t prefix_len; - char *req_fname; - - /* check if a session already exists and if so terminate it */ - spt = tftp_session_find(slirp, tp); - if (spt != NULL) { - tftp_session_terminate(spt); - } + struct tftp_session *spt; + int s, k; + size_t prefix_len; + char *req_fname; + + /* check if a session already exists and if so terminate it */ + s = tftp_session_find(slirp, srcsas, &tp->hdr); + if (s >= 0) { + tftp_session_terminate(&slirp->tftp_sessions[s]); + } - spt = tftp_session_allocate(slirp, tp); - if (spt == NULL) { - return; - } + s = tftp_session_allocate(slirp, srcsas, &tp->hdr); - /* unspecified prefix means service disabled */ - if (!slirp->tftp_prefix) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } + if (s < 0) { + return; + } - /* skip header fields */ - k = 0; - pktlen -= offsetof(struct tftp_t, x.tp_buf); + spt = &slirp->tftp_sessions[s]; - /* prepend tftp_prefix */ - prefix_len = strlen(slirp->tftp_prefix); - spt->filename = (char*)malloc(prefix_len + TFTP_FILENAME_MAX + 2); - memcpy(spt->filename, slirp->tftp_prefix, prefix_len); - spt->filename[prefix_len] = '/'; + /* unspecified prefix means service disabled */ + if (!slirp->tftp_prefix) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } + + /* skip header fields */ + k = 0; + pktlen -= offsetof(struct tftp_t, x.tp_buf); + + /* prepend tftp_prefix */ + prefix_len = strlen(slirp->tftp_prefix); + spt->filename = (char*)malloc(prefix_len + TFTP_FILENAME_MAX + 2); + memcpy(spt->filename, slirp->tftp_prefix, prefix_len); + spt->filename[prefix_len] = '/'; - /* get name */ - req_fname = spt->filename + prefix_len + 1; + /* get name */ + req_fname = spt->filename + prefix_len + 1; - while (1) { - if (k >= TFTP_FILENAME_MAX || k >= pktlen) { - tftp_send_error(spt, 2, "Access violation", tp); - return; + while (1) { + if (k >= TFTP_FILENAME_MAX || k >= pktlen) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } + req_fname[k] = tp->x.tp_buf[k]; + if (req_fname[k++] == '\0') { + break; + } } - req_fname[k] = tp->x.tp_buf[k]; - if (req_fname[k++] == '\0') { - break; + + DEBUG_TFTP("tftp rrq file: %s", req_fname); + + /* check mode */ + if ((pktlen - k) < 6) { + tftp_send_error(spt, 2, "Access violation", tp); + return; } - } - tftp_parse_options(spt, tp, k, pktlen); - if (!(spt->options & TFTP_OPTION_OCTET)) { - tftp_send_error(spt, 4, "Unsupported transfer mode", tp); - return; - } + if (strcasecmp(&tp->x.tp_buf[k], "octet") != 0) { + tftp_send_error(spt, 4, "Unsupported transfer mode", tp); + return; + } - /* do sanity checks on the filename */ - if (!strncmp(req_fname, "../", 3) || - req_fname[strlen(req_fname) - 1] == '/' || - strstr(req_fname, "/../")) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } + k += 6; /* skipping octet */ - /* check if the file exists */ - if (tftp_read_data(spt, 0, NULL, 0) < 0) { - tftp_send_error(spt, 1, "File not found", tp); - return; - } + /* do sanity checks on the filename */ + if ( +#ifdef _WIN32 + strstr(req_fname, "..\\") || + req_fname[strlen(req_fname) - 1] == '\\' || +#endif + strstr(req_fname, "../") || + req_fname[strlen(req_fname) - 1] == '/') { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } - if (tp->x.tp_buf[pktlen - 1] != 0) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } + /* check if the file exists */ + if (tftp_read_data(spt, 0, NULL, 0) < 0) { + tftp_send_error(spt, 1, "File not found", tp); + return; + } - if (spt->options & TFTP_OPTION_TSIZE) { - struct stat stat_p; - if (stat(spt->filename, &stat_p) == 0) { - spt->tsize_val = stat_p.st_size; - } else { - tftp_send_error(spt, 1, "File not found", tp); - return; - } - } + if (tp->x.tp_buf[pktlen - 1] != 0) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } - if ((spt->options & ~TFTP_OPTION_OCTET) > 0) { - tftp_send_optack(spt, tp); - } else { - spt->block_nr = 0; - tftp_send_next_block(spt, tp); - } + tftp_parse_options(spt, tp, k, pktlen); + + if (spt->nb_options > 0) { + tftp_send_oack(spt, tp); + } else { + spt->block_nr = 0; + tftp_send_next_block(spt, &tp->hdr); + } } -static void tftp_handle_wrq(Slirp *slirp, struct tftp_t *tp, int pktlen) +static void tftp_handle_wrq(Slirp *slirp, struct sockaddr_storage *srcsas, + struct tftp_t *tp, int pktlen) { - struct tftp_session *spt; - int k, fd; - size_t prefix_len; - char *req_fname; - - /* check if a session already exists and if so terminate it */ - spt = tftp_session_find(slirp, tp); - if (spt != NULL) { - tftp_session_terminate(spt); - } + struct tftp_session *spt; + int s, k; + size_t prefix_len; + char *req_fname; + + /* check if a session already exists and if so terminate it */ + s = tftp_session_find(slirp, srcsas, &tp->hdr); + if (s >= 0) { + tftp_session_terminate(&slirp->tftp_sessions[s]); + } - spt = tftp_session_allocate(slirp, tp); - if (spt == NULL) { - return; - } + s = tftp_session_allocate(slirp, srcsas, &tp->hdr); - /* unspecified prefix means service disabled */ - if (!slirp->tftp_prefix) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } + if (s < 0) { + return; + } + + spt = &slirp->tftp_sessions[s]; - /* skip header fields */ - k = 0; - pktlen -= offsetof(struct tftp_t, x.tp_buf); + /* unspecified prefix means service disabled */ + if (!slirp->tftp_prefix) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } - /* prepend tftp_prefix */ - prefix_len = strlen(slirp->tftp_prefix); - spt->filename = (char*)malloc(prefix_len + TFTP_FILENAME_MAX + 2); - memcpy(spt->filename, slirp->tftp_prefix, prefix_len); - spt->filename[prefix_len] = '/'; + /* skip header fields */ + k = 0; + pktlen -= offsetof(struct tftp_t, x.tp_buf); - /* get name */ - req_fname = spt->filename + prefix_len + 1; + /* prepend tftp_prefix */ + prefix_len = strlen(slirp->tftp_prefix); + spt->filename = (char*)malloc(prefix_len + TFTP_FILENAME_MAX + 2); + memcpy(spt->filename, slirp->tftp_prefix, prefix_len); + spt->filename[prefix_len] = '/'; - while (1) { - if (k >= TFTP_FILENAME_MAX || k >= pktlen) { - tftp_send_error(spt, 2, "Access violation", tp); - return; + /* get name */ + req_fname = spt->filename + prefix_len + 1; + + while (1) { + if (k >= TFTP_FILENAME_MAX || k >= pktlen) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } + req_fname[k] = tp->x.tp_buf[k]; + if (req_fname[k++] == '\0') { + break; + } } - req_fname[k] = tp->x.tp_buf[k]; - if (req_fname[k++] == '\0') { - break; + + DEBUG_TFTP("tftp wrq file: %s", req_fname); + + /* do sanity checks on the filename */ + if ( +#ifdef _WIN32 + strstr(req_fname, "..\\") || + req_fname[strlen(req_fname) - 1] == '\\' || +#endif + strstr(req_fname, "../") || + req_fname[strlen(req_fname) - 1] == '/') { + tftp_send_error(spt, 2, "Access violation", tp); + return; } - } - tftp_parse_options(spt, tp, k, pktlen); - if (!(spt->options & TFTP_OPTION_OCTET)) { - tftp_send_error(spt, 4, "Unsupported transfer mode", tp); - return; - } + /* check if the file exists */ + if (tftp_read_data(spt, 0, NULL, 0) >= 0) { + close(spt->fd); + tftp_send_error(spt, 6, "File exists", tp); + return; + } - /* do sanity checks on the filename */ - if (!strncmp(req_fname, "../", 3) || - req_fname[strlen(req_fname) - 1] == '/' || - strstr(req_fname, "/../")) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } + if (tp->x.tp_buf[pktlen - 1] != 0) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } - /* check if the file exists */ - fd = open(spt->filename, O_RDONLY | O_BINARY); - if (fd >= 0) { - close(fd); - tftp_send_error(spt, 6, "File exists", tp); - return; - } - /* create new file */ - spt->fd = open(spt->filename, O_CREAT | O_WRONLY + tftp_parse_options(spt, tp, k, pktlen); + + /* create new file */ + spt->fd = open(spt->filename, O_CREAT | O_WRONLY #ifdef O_BINARY - | O_BINARY + | O_BINARY #endif - , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP); - if (spt->fd < 0) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } - - if (tp->x.tp_buf[pktlen - 1] != 0) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } + , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP); + if (spt->fd < 0) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } - spt->block_nr = 0; - if ((spt->options & ~TFTP_OPTION_OCTET) > 0) { - tftp_send_optack(spt, tp); - } else { - tftp_send_ack(spt, tp); - } + spt->block_nr = 0; + if (spt->nb_options > 0) { + tftp_send_oack(spt, tp); + } else { + tftp_send_ack(spt, tp); + } } -static void tftp_handle_data(Slirp *slirp, struct tftp_t *tp, int pktlen) +static void tftp_handle_data(Slirp *slirp, struct sockaddr_storage *srcsas, + struct tftp_t *tp, int pktlen) { - struct tftp_session *spt; - int nobytes; + struct tftp_session *spt; + int s, nobytes; - spt = tftp_session_find(slirp, tp); - if (spt == NULL) { - return; - } + /* check if the session exists */ + s = tftp_session_find(slirp, srcsas, &tp->hdr); + if (s < 0) { + return; + } - if (spt->write == 1) { - spt->block_nr = ntohs(tp->x.tp_data.tp_block_nr); - nobytes = pktlen - offsetof(struct tftp_t, x.tp_data.tp_buf); - if (nobytes <= (int)spt->blksize_val) { - lseek(spt->fd, (spt->block_nr - 1) * spt->blksize_val, SEEK_SET); - write(spt->fd, tp->x.tp_data.tp_buf, nobytes); - tftp_send_ack(spt, tp); - if (nobytes == (int)spt->blksize_val) { - tftp_session_update(spt); - } else { - tftp_session_terminate(spt); - } + spt = &slirp->tftp_sessions[s]; + + if (spt->write == 1) { + spt->block_nr = ntohs(tp->x.tp_data.tp_block_nr); + nobytes = pktlen - offsetof(struct tftp_t, x.tp_data.tp_buf); + if (nobytes <= (int)spt->blksize_val) { + lseek(spt->fd, (spt->block_nr - 1) * spt->blksize_val, SEEK_SET); + write(spt->fd, tp->x.tp_data.tp_buf, nobytes); + tftp_send_ack(spt, tp); + if (nobytes == (int)spt->blksize_val) { + tftp_session_update(spt); + } else { + tftp_session_terminate(spt); + } + } else { + tftp_send_error(spt, 2, "Access violation", tp); + } } else { - tftp_send_error(spt, 2, "Access violation", tp); + tftp_send_error(spt, 2, "Access violation", tp); } - } else { - tftp_send_error(spt, 2, "Access violation", tp); - } } -static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen) +static void tftp_handle_ack(Slirp *slirp, struct sockaddr_storage *srcsas, + struct tftphdr *hdr) { - struct tftp_session *spt; + int s; - spt = tftp_session_find(slirp, tp); - if (spt == NULL) { - return; - } - tftp_send_next_block(spt, tp); + s = tftp_session_find(slirp, srcsas, hdr); + + if (s < 0) { + return; + } + + tftp_send_next_block(&slirp->tftp_sessions[s], hdr); } -static void tftp_handle_error(Slirp *slirp, struct tftp_t *tp, int pktlen) +static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas, + struct tftphdr *hdr) { - struct tftp_session *spt; + int s; - spt = tftp_session_find(slirp, tp); - if (spt == NULL) { - return; - } - tftp_session_terminate(spt); + s = tftp_session_find(slirp, srcsas, hdr); + + if (s < 0) { + return; + } + + tftp_session_terminate(&slirp->tftp_sessions[s]); } -void tftp_input(struct mbuf *m) +void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m) { - struct tftp_t *tp = (struct tftp_t *)m->m_data; + struct tftphdr *hdr = (struct tftphdr *)mtod_check(m, sizeof(struct tftphdr)); + + if (hdr == NULL) { + return; + } - switch (ntohs(tp->tp_op)) { + switch (ntohs(hdr->tp_op)) { case TFTP_RRQ: - tftp_handle_rrq(m->slirp, tp, m->m_len); - break; + tftp_handle_rrq(m->slirp, srcsas, + mtod(m, struct tftp_t *), + m->m_len); + break; case TFTP_WRQ: - tftp_handle_wrq(m->slirp, tp, m->m_len); + tftp_handle_wrq(m->slirp, srcsas, + mtod(m, struct tftp_t *), + m->m_len); break; case TFTP_DATA: - tftp_handle_data(m->slirp, tp, m->m_len); + tftp_handle_data(m->slirp, srcsas, + mtod(m, struct tftp_t *), + m->m_len); break; case TFTP_ACK: - tftp_handle_ack(m->slirp, tp, m->m_len); - break; + tftp_handle_ack(m->slirp, srcsas, hdr); + break; case TFTP_ERROR: - tftp_handle_error(m->slirp, tp, m->m_len); - break; + tftp_handle_error(m->slirp, srcsas, hdr); + break; } } diff --git a/bochs/iodev/network/slirp/tftp.h b/bochs/iodev/network/slirp/tftp.h index b3713fd7f2..39ace2661a 100644 --- a/bochs/iodev/network/slirp/tftp.h +++ b/bochs/iodev/network/slirp/tftp.h @@ -1,51 +1,70 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// - +/* SPDX-License-Identifier: BSD-3-Clause */ /* tftp defines */ + #ifndef SLIRP_TFTP_H -#define SLIRP_TFTP_H 1 +#define SLIRP_TFTP_H -#define TFTP_SESSIONS_MAX 3 +#include "util.h" + +#define TFTP_SESSIONS_MAX 20 #define TFTP_SERVER 69 -#define TFTP_BUFFER_SIZE 1432 +#define TFTP_RRQ 1 +#define TFTP_WRQ 2 +#define TFTP_DATA 3 +#define TFTP_ACK 4 +#define TFTP_ERROR 5 +#define TFTP_OACK 6 + +#define TFTP_FILENAME_MAX 512 +#define TFTP_BLOCKSIZE_MAX 1428 +SLIRP_PACKED_BEGIN +struct tftphdr { + struct udphdr udp; + uint16_t tp_op; +} SLIRP_PACKED_END; + +SLIRP_PACKED_BEGIN struct tftp_t { - struct ip ip; - struct udphdr udp; - uint16_t tp_op; + struct tftphdr hdr; union { struct { uint16_t tp_block_nr; - uint8_t tp_buf[TFTP_BUFFER_SIZE]; + uint8_t tp_buf[TFTP_BLOCKSIZE_MAX]; } tp_data; struct { uint16_t tp_error_code; - uint8_t tp_msg[TFTP_BUFFER_SIZE]; + uint8_t tp_msg[TFTP_BLOCKSIZE_MAX]; } tp_error; - char tp_buf[TFTP_BUFFER_SIZE + 2]; + char tp_buf[TFTP_BLOCKSIZE_MAX + 2]; } x; -}; +} SLIRP_PACKED_END; struct tftp_session { Slirp *slirp; char *filename; int fd; - struct in_addr client_ip; + struct sockaddr_storage client_addr; uint16_t client_port; uint32_t block_nr; bool write; - unsigned options; + int nb_options; + const char* option_name[3]; + uint32_t option_value[3]; + uint16_t blksize_val; size_t tsize_val; - unsigned blksize_val; unsigned timeout_val; int timestamp; }; -void tftp_input(struct mbuf *m); +/* Process TFTP packet coming from the guest */ +void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m); + +/* Clear remaining sessions */ +void tftp_cleanup(Slirp *slirp); #endif diff --git a/bochs/iodev/network/slirp/udp.cc b/bochs/iodev/network/slirp/udp.cc index bfb6d994c5..bd405f9da1 100644 --- a/bochs/iodev/network/slirp/udp.cc +++ b/bochs/iodev/network/slirp/udp.cc @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,7 +27,7 @@ * 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 8.4 (Berkeley) 1/21/94 * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp */ @@ -48,8 +46,7 @@ static uint8_t udp_tos(struct socket *so); -void -udp_init(Slirp *slirp) +void udp_init(Slirp *slirp) { slirp->udb.so_next = slirp->udb.so_prev = &slirp->udb; slirp->udp_last_so = &slirp->udb; @@ -57,8 +54,11 @@ udp_init(Slirp *slirp) void udp_cleanup(Slirp *slirp) { - while (slirp->udb.so_next != &slirp->udb) { - udp_detach(slirp->udb.so_next); + struct socket *so, *so_next; + + for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) { + so_next = so->so_next; + udp_detach(so); } } @@ -66,69 +66,81 @@ void udp_cleanup(Slirp *slirp) * m->m_len length ip packet * ip->ip_len length data (IPDU) */ -void -udp_input(struct mbuf *m, int iphlen) +void udp_input(struct mbuf *m, int iphlen) { - Slirp *slirp = m->slirp; - struct ip *ip; - struct udphdr *uh; - int len; - struct ip save_ip; - struct socket *so; - - DEBUG_CALL("udp_input"); - DEBUG_ARG("m = %lx", (long)m); - DEBUG_ARG("iphlen = %d", iphlen); - - /* - * 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 ((size_t)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((uint16_t)uh->uh_ulen); - - if (ip->ip_len != len) { - if (len > ip->ip_len) { - 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 (uh->uh_sum) { + Slirp *slirp = m->slirp; + M_DUP_DEBUG(slirp, m, 0, 0); + + struct ip *ip; + struct udphdr *uh; + int len; + struct ip save_ip; + struct socket *so; + struct sockaddr_storage lhost; + struct sockaddr_in *lhost4; + int ttl; + + DEBUG_CALL("udp_input"); + DEBUG_ARG("m = %p", m); + DEBUG_ARG("iphlen = %d", iphlen); + + /* + * 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 ((size_t)iphlen > sizeof(struct ip)) { + ip_stripoptions(m); + iphlen = sizeof(struct ip); + } + + /* + * Get IP and UDP header together in first mbuf. + */ + ip = (struct ip*)mtod_check(m, iphlen + sizeof(struct udphdr)); + if (ip == NULL) { + goto bad; + } + uh = (struct udphdr *)((char *)ip + iphlen); + + /* + * Make mbuf data length reflect UDP length. + * If not enough data to reflect UDP length, drop. + */ + len = ntohs((uint16_t)uh->uh_ulen); + + if (ip->ip_len != len) { + if (len > ip->ip_len) { + 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 (uh->uh_sum) { memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr)); - ((struct ipovly *)ip)->ih_x1 = 0; - ((struct ipovly *)ip)->ih_len = uh->uh_ulen; - if(cksum(m, len + sizeof(struct ip))) { - goto bad; - } - } + ((struct ipovly *)ip)->ih_x1 = 0; + ((struct ipovly *)ip)->ih_len = uh->uh_ulen; + if(cksum(m, len + sizeof(struct ip))) { + goto bad; + } + } + + lhost.ss_family = AF_INET; + lhost4 = (struct sockaddr_in *)&lhost; + lhost4->sin_addr = ip->ip_src; + lhost4->sin_port = uh->uh_sport; /* * handle DHCP/BOOTP @@ -145,7 +157,11 @@ udp_input(struct mbuf *m, int iphlen) */ if (ntohs(uh->uh_dport) == TFTP_SERVER && ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) { - tftp_input(m); + m->m_data += iphlen; + m->m_len -= iphlen; + tftp_input(&lhost, m); + m->m_data -= iphlen; + m->m_len += iphlen; goto bad; } @@ -153,249 +169,263 @@ udp_input(struct mbuf *m, int iphlen) goto bad; } - /* - * Locate pcb for datagram. - */ - so = slirp->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 = slirp->udb.so_next; tmp != &slirp->udb; - tmp = tmp->so_next) { - if (tmp->so_lport == uh->uh_sport && - tmp->so_laddr.s_addr == ip->ip_src.s_addr) { - so = tmp; - break; - } - } - if (tmp == &slirp->udb) { - so = NULL; - } else { - slirp->udp_last_so = so; - } - } - - if (so == NULL) { - /* - * If there's no socket for this packet, - * create one - */ - so = socreate(slirp); - if (!so) { - 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 - */ - 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. - */ - } + /* + * Locate pcb for datagram. + */ + so = solookup(&slirp->udp_last_so, &slirp->udb, &lhost, NULL); + + if (so == NULL) { + /* + * If there's no socket for this packet, + * create one + */ + so = socreate(slirp, IPPROTO_UDP); + if (udp_attach(so, AF_INET) == -1) { + DEBUG_MISC(" udp_attach errno = %d-%s", errno, strerror(errno)); + sofree(so); + goto bad; + } + + /* + * Setup fields + */ + so->so_lfamily = AF_INET; + 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_ffamily = AF_INET; 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(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; + iphlen += sizeof(struct udphdr); + m->m_len -= iphlen; + m->m_data += iphlen; + + /* + * Check for TTL + */ + ttl = save_ip.ip_ttl-1; + if (ttl <= 0) { + m->m_len += iphlen; + m->m_data -= iphlen; + *ip = save_ip; + DEBUG_MISC("udp ttl exceeded"); + icmp_send_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, NULL); + goto bad; + } + setsockopt(so->s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); + + /* + * Now we sendto() the packet. + */ + if(sosendto(so,m) == -1) { + m->m_len += iphlen; + m->m_data -= iphlen; + *ip = save_ip; + DEBUG_MISC("udp tx errno = %d-%s",errno,strerror(errno)); + icmp_send_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); + goto bad; + } + + 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_free(m); + m_free(m); } -int udp_output2(struct socket *so, struct mbuf *m, - struct sockaddr_in *saddr, struct sockaddr_in *daddr, - int iptos) +int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, + struct sockaddr_in *daddr, int iptos) { - 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 *); + Slirp *slirp = m->slirp; + char addr[INET_ADDRSTRLEN]; + + M_DUP_DEBUG(slirp, m, 0, (int)sizeof(struct udpiphdr)); + + struct udpiphdr *ui; + int error = 0; + + DEBUG_CALL("udp_output"); + DEBUG_ARG("so = %p", so); + DEBUG_ARG("m = %p", m); + DEBUG_ARG("saddr = %s", inet_ntop(AF_INET, &saddr->sin_addr, addr, sizeof(addr))); + DEBUG_ARG("daddr = %s", inet_ntop(AF_INET, &daddr->sin_addr, addr, sizeof(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 *); memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); - ui->ui_x1 = 0; - ui->ui_pr = IPPROTO_UDP; - ui->ui_len = htons(m->m_len - sizeof(struct ip)); - /* 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 ((ui->ui_sum = cksum(m, m->m_len)) == 0) - ui->ui_sum = 0xffff; - ((struct ip *)ui)->ip_len = m->m_len; - - ((struct ip *)ui)->ip_ttl = IPDEFTTL; - ((struct ip *)ui)->ip_tos = iptos; - - error = ip_output(so, m); - - return (error); + ui->ui_x1 = 0; + ui->ui_pr = IPPROTO_UDP; + ui->ui_len = htons(m->m_len - sizeof(struct ip)); + /* 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 ((ui->ui_sum = cksum(m, m->m_len)) == 0) + ui->ui_sum = 0xffff; + ((struct ip *)ui)->ip_len = m->m_len; + + ((struct ip *)ui)->ip_ttl = IPDEFTTL; + ((struct ip *)ui)->ip_tos = iptos; + + error = ip_output(so, m); + + return (error); } -int udp_output(struct socket *so, struct mbuf *m, - struct sockaddr_in *addr) - +int udp_attach(struct socket *so, unsigned short af) { - Slirp *slirp = so->slirp; - struct sockaddr_in saddr, daddr; - - saddr = *addr; - if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { - uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr; - - if ((so->so_faddr.s_addr & inv_mask) == inv_mask) { - saddr.sin_addr = slirp->vhost_addr; - } else if (addr->sin_addr.s_addr == loopback_addr.s_addr || - so->so_faddr.s_addr != slirp->vhost_addr.s_addr) { - saddr.sin_addr = so->so_faddr; + so->s = slirp_socket(af, SOCK_DGRAM, 0); + if (so->s != -1) { + if (slirp_bind_outbound(so, af) != 0) { + // bind failed - close socket + closesocket(so->s); + so->s = -1; + return -1; } - } - daddr.sin_addr = so->so_laddr; - daddr.sin_port = so->so_lport; - return udp_output2(so, m, &saddr, &daddr, so->so_iptos); +#ifdef __linux__ + { + int opt = 1; + switch (af) { + case AF_INET: + setsockopt(so->s, IPPROTO_IP, IP_RECVERR, &opt, sizeof(opt)); + break; + case AF_INET6: + setsockopt(so->s, IPPROTO_IPV6, IPV6_RECVERR, &opt, sizeof(opt)); + break; + default: + slirplog_error("Unknown protocol"); + } + } +#endif + + so->so_expire = curtime + SO_EXPIRE; + slirp_insque(so, &so->slirp->udb); + } + so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque); + return (so->s); } -int -udp_attach(struct socket *so) +void udp_detach(struct socket *so) { - if((so->s = qemu_socket(AF_INET,SOCK_DGRAM,0)) != -1) { - so->so_expire = curtime + SO_EXPIRE; - insque(so, &so->slirp->udb); - } - return(so->s); + so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); + closesocket(so->s); + sofree(so); } -void -udp_detach(struct socket *so) +static const struct tos_t udptos[] = {{0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ + {0, 0, 0, 0} }; + +static uint8_t udp_tos(struct socket *so) { - closesocket(so->s); - sofree(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)) { + if (so->slirp->enable_emu) + so->so_emu = udptos[i].emu; + return udptos[i].tos; + } + i++; + } -static const struct tos_t udptos[] = { - {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ - {0, 0, 0, 0} -}; + return 0; +} -static uint8_t -udp_tos(struct socket *so) +struct socket *udpx_listen(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + const struct sockaddr *laddr, socklen_t laddrlen, + int flags) { - 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; + struct socket *so; + socklen_t addrlen; + int save_errno; + + so = socreate(slirp, IPPROTO_UDP); + so->s = slirp_socket(haddr->sa_family, SOCK_DGRAM, 0); + if (so->s < 0) { + save_errno = errno; + sofree(so); + errno = save_errno; + return NULL; + } + if (haddr->sa_family == AF_INET6) + slirp_socket_set_v6only(so->s, (flags & SS_HOSTFWD_V6ONLY) != 0); + so->so_expire = curtime + SO_EXPIRE; + slirp_insque(so, &slirp->udb); + + if (bind(so->s, haddr, haddrlen) < 0) { + save_errno = errno; + udp_detach(so); + errno = save_errno; + return NULL; + } + slirp_socket_set_fast_reuse(so->s); + + addrlen = sizeof(so->fhost); + getsockname(so->s, &so->fhost.sa, &addrlen); + sotranslate_accept(so); + + sockaddr_copy(&so->lhost.sa, sizeof(so->lhost), laddr, laddrlen); + + if (flags != SS_FACCEPTONCE) + so->so_expire = 0; + so->so_state &= SS_PERSISTENT_MASK; + so->so_state |= SS_ISFCONNECTED | flags; + + return so; } -struct socket * -udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, - u_int lport, int flags) +struct socket *udp_listen(Slirp *slirp, uint32_t haddr, unsigned hport, + uint32_t laddr, unsigned lport, int flags) { - struct sockaddr_in addr; - struct socket *so; - socklen_t addrlen = sizeof(struct sockaddr_in); - - so = socreate(slirp); - if (!so) { - return NULL; - } - so->s = qemu_socket(AF_INET,SOCK_DGRAM,0); - so->so_expire = curtime + SO_EXPIRE; - insque(so, &slirp->udb); - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = haddr; - addr.sin_port = hport; - - if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) { - udp_detach(so); - return NULL; - } - socket_set_fast_reuse(so->s); - - 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 = slirp->vhost_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_PERSISTENT_MASK; - so->so_state |= SS_ISFCONNECTED | flags; - - return so; + struct sockaddr_in hsa, lsa; + + memset(&hsa, 0, sizeof(hsa)); + hsa.sin_family = AF_INET; + hsa.sin_addr.s_addr = haddr; + hsa.sin_port = hport; + + memset(&lsa, 0, sizeof(lsa)); + lsa.sin_family = AF_INET; + lsa.sin_addr.s_addr = laddr; + lsa.sin_port = lport; + + return udpx_listen(slirp, (const struct sockaddr *) &hsa, sizeof(hsa), (struct sockaddr *) &lsa, sizeof(lsa), flags); } #endif diff --git a/bochs/iodev/network/slirp/udp.h b/bochs/iodev/network/slirp/udp.h index 3a5c625cd4..7fa2b40238 100644 --- a/bochs/iodev/network/slirp/udp.h +++ b/bochs/iodev/network/slirp/udp.h @@ -1,9 +1,7 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -///////////////////////////////////////////////////////////////////////// +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -29,15 +27,16 @@ * 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 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_ +#ifndef UDP_H +#define UDP_H + +#include "socket.h" #define UDP_TTL 0x60 -#define UDP_UDPDATALEN 16192 /* * Udp protocol header. @@ -54,8 +53,8 @@ struct udphdr { * UDP kernel structures and variables. */ struct udpiphdr { - struct ipovly ui_i; /* overlaid ip structure */ - struct udphdr ui_u; /* udp header */ + struct ipovly ui_i; /* overlaid ip structure */ + struct udphdr ui_u; /* udp header */ }; #define ui_mbuf ui_i.ih_mbuf.mptr #define ui_x1 ui_i.ih_x1 @@ -76,15 +75,32 @@ struct udpiphdr { struct mbuf; +/* Called from slirp_init */ void udp_init(Slirp *); +/* Called from slirp_cleanup */ void udp_cleanup(Slirp *); +/* Process UDP datagram coming from the guest */ void udp_input(struct mbuf *, int); -int udp_output(struct socket *, struct mbuf *, struct sockaddr_in *); -int udp_attach(struct socket *); +/* Create a host UDP socket, bound to this socket */ +int udp_attach(struct socket *, unsigned short af); +/* Destroy socket */ void udp_detach(struct socket *); -struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int, - int); -int udp_output2(struct socket *so, struct mbuf *m, - struct sockaddr_in *saddr, struct sockaddr_in *daddr, - int iptos); + +/* Listen for incoming UDP datagrams on this haddr+hport */ +struct socket *udp_listen(Slirp *, uint32_t haddr, unsigned hport, uint32_t laddr, unsigned lport, int flags); +/* Listen for incoming UDP datagrams on this haddr */ +struct socket *udpx_listen(Slirp *, + const struct sockaddr *haddr, socklen_t haddrlen, + const struct sockaddr *laddr, socklen_t laddrlen, + int flags); +/* Send UDP datagram to the guest */ +int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, + struct sockaddr_in *daddr, int iptos); + +/* Process UDPv6 datagram coming from the guest */ +void udp6_input(struct mbuf *); +/* Send UDPv6 datagram to the guest */ +int udp6_output(struct socket *so, struct mbuf *m, struct sockaddr_in6 *saddr, + struct sockaddr_in6 *daddr); + #endif diff --git a/bochs/iodev/network/slirp/udp6.cc b/bochs/iodev/network/slirp/udp6.cc new file mode 100644 index 0000000000..8aa733a96f --- /dev/null +++ b/bochs/iodev/network/slirp/udp6.cc @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2013 + * Guillaume Subiron + */ + +#include "slirp.h" +#include "udp.h" +#include "dhcpv6.h" + +#if BX_NETWORKING && BX_NETMOD_SLIRP + +void udp6_input(struct mbuf *m) +{ + Slirp *slirp = m->slirp; + M_DUP_DEBUG(slirp, m, 0, 0); + + struct ip6 *ip, save_ip; + struct udphdr *uh; + int iphlen = sizeof(struct ip6); + int len; + struct socket *so; + struct sockaddr_in6 lhost; + int hop_limit; + + DEBUG_CALL("udp6_input"); + DEBUG_ARG("m = %p", m); + + if (slirp->restricted) { + goto bad; + } + + ip = mtod(m, struct ip6 *); + m->m_len -= iphlen; + m->m_data += iphlen; + uh = (struct udphdr*)mtod_check(m, sizeof(struct udphdr)); + if (uh == NULL) { + goto bad; + } + m->m_len += iphlen; + m->m_data -= iphlen; + + if (ip6_cksum(m)) { + goto bad; + } + + len = ntohs((uint16_t)uh->uh_ulen); + + /* + * Make mbuf data length reflect UDP length. + * If not enough data to reflect UDP length, drop. + */ + if (ntohs(ip->ip_pl) != len) { + if (len > ntohs(ip->ip_pl)) { + goto bad; + } + m_adj(m, len - ntohs(ip->ip_pl)); + ip->ip_pl = htons(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; + + /* Locate pcb for datagram. */ + lhost.sin6_family = AF_INET6; + lhost.sin6_addr = ip->ip_src; + lhost.sin6_port = uh->uh_sport; + + /* handle DHCPv6 */ + if (ntohs(uh->uh_dport) == DHCPV6_SERVER_PORT && + (in6_equal(&ip->ip_dst, &slirp->vhost_addr6) || + in6_dhcp_multicast(&ip->ip_dst))) { + m->m_data += iphlen; + m->m_len -= iphlen; + dhcpv6_input(&lhost, m); + m->m_data -= iphlen; + m->m_len += iphlen; + goto bad; + } + + /* handle TFTP */ + if (ntohs(uh->uh_dport) == TFTP_SERVER && + !memcmp(ip->ip_dst.s6_addr, slirp->vhost_addr6.s6_addr, 16)) { + m->m_data += iphlen; + m->m_len -= iphlen; + tftp_input((struct sockaddr_storage *)&lhost, m); + m->m_data -= iphlen; + m->m_len += iphlen; + goto bad; + } + + so = solookup(&slirp->udp_last_so, &slirp->udb, + (struct sockaddr_storage *)&lhost, NULL); + + if (so == NULL) { + /* If there's no socket for this packet, create one. */ + so = socreate(slirp, IPPROTO_UDP); + if (udp_attach(so, AF_INET6) == -1) { + DEBUG_MISC(" udp6_attach errno = %d-%s", errno, strerror(errno)); + sofree(so); + goto bad; + } + + /* Setup fields */ + so->so_lfamily = AF_INET6; + so->so_laddr6 = ip->ip_src; + so->so_lport6 = uh->uh_sport; + } + + so->so_ffamily = AF_INET6; + so->so_faddr6 = ip->ip_dst; /* XXX */ + so->so_fport6 = uh->uh_dport; /* XXX */ + + iphlen += sizeof(struct udphdr); + m->m_len -= iphlen; + m->m_data += iphlen; + + /* + * Check for TTL + */ + hop_limit = save_ip.ip_hl-1; + if (hop_limit <= 0) { + m->m_len += iphlen; + m->m_data -= iphlen; + *ip = save_ip; + DEBUG_MISC("udp ttl exceeded"); + icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS); + goto bad; + } + setsockopt(so->s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, sizeof(hop_limit)); + + /* + * Now we sendto() the packet. + */ + if (sosendto(so, m) == -1) { + m->m_len += iphlen; + m->m_data -= iphlen; + *ip = save_ip; + DEBUG_MISC("udp tx errno = %d-%s", errno, strerror(errno)); + icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE); + goto bad; + } + + 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; + + return; +bad: + m_free(m); +} + +int udp6_output(struct socket *so, struct mbuf *m, struct sockaddr_in6 *saddr, + struct sockaddr_in6 *daddr) +{ + Slirp *slirp = m->slirp; + M_DUP_DEBUG(slirp, m, 0, (int)(sizeof(struct ip6) + sizeof(struct udphdr))); + + struct ip6 *ip; + struct udphdr *uh; + + DEBUG_CALL("udp6_output"); + DEBUG_ARG("so = %p", so); + DEBUG_ARG("m = %p", m); + + /* adjust for header */ + m->m_data -= sizeof(struct udphdr); + m->m_len += sizeof(struct udphdr); + uh = mtod(m, struct udphdr *); + m->m_data -= sizeof(struct ip6); + m->m_len += sizeof(struct ip6); + ip = mtod(m, struct ip6 *); + + /* Build IP header */ + ip->ip_pl = htons(m->m_len - sizeof(struct ip6)); + ip->ip_nh = IPPROTO_UDP; + ip->ip_src = saddr->sin6_addr; + ip->ip_dst = daddr->sin6_addr; + + /* Build UDP header */ + uh->uh_sport = saddr->sin6_port; + uh->uh_dport = daddr->sin6_port; + uh->uh_ulen = ip->ip_pl; + uh->uh_sum = 0; + uh->uh_sum = ip6_cksum(m); + if (uh->uh_sum == 0) { + uh->uh_sum = 0xffff; + } + + return ip6_output(so, m, 0); +} + +#endif diff --git a/bochs/iodev/network/slirp/util.cc b/bochs/iodev/network/slirp/util.cc new file mode 100644 index 0000000000..6b2afd5575 --- /dev/null +++ b/bochs/iodev/network/slirp/util.cc @@ -0,0 +1,452 @@ +/* SPDX-License-Identifier: MIT */ +/* + * util.c (mostly based on QEMU os-win32.c) + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2010-2016 Red Hat, Inc. + * + * QEMU library functions for win32 which are shared between QEMU and + * the QEMU tools. + * + * 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. + */ +#ifdef __CYGWIN__ +#define __USE_W32_SOCKETS +#define _WIN32 +#endif + +#include "config.h" + +#if BX_NETWORKING && BX_NETMOD_SLIRP + +#include "util.h" +#include "compat.h" + +#include +#include +#include + +#if defined(_WIN32) +int slirp_inet_aton(const char *cp, struct in_addr *ia) +{ + uint32_t addr; + +#if defined(_MSC_VER) + if (!inet_pton(AF_INET, cp, &addr)) { + return 0; + } +#else + addr = inet_addr(cp); +#endif + if (addr == 0xffffffff) { + return 0; + } + ia->s_addr = addr; + return 1; +} +#endif + +void slirp_set_nonblock(int fd) +{ +#ifndef _WIN32 + int f; + f = fcntl(fd, F_GETFL); + assert(f != -1); + f = fcntl(fd, F_SETFL, f | O_NONBLOCK); + assert(f != -1); +#else + unsigned long opt = 1; + ioctlsocket(fd, FIONBIO, &opt); +#endif +} + +static void slirp_set_cloexec(int fd) +{ +#ifndef _WIN32 + int f; + f = fcntl(fd, F_GETFD); + assert(f != -1); + f = fcntl(fd, F_SETFD, f | FD_CLOEXEC); + assert(f != -1); +#endif +} + +/* + * Opens a socket with FD_CLOEXEC set + * On failure errno contains the reason. + */ +int slirp_socket(int domain, int type, int protocol) +{ + int ret; + +#ifdef SOCK_CLOEXEC + ret = socket(domain, type | SOCK_CLOEXEC, protocol); + if (ret != -1 || errno != EINVAL) { + return ret; + } +#endif + ret = socket(domain, type, protocol); + if (ret >= 0) { + slirp_set_cloexec(ret); + } + + return ret; +} + +#ifdef _WIN32 +static int socket_error(void) +{ + switch (WSAGetLastError()) { + case 0: + return 0; + case WSAEINTR: + return EINTR; + case WSAEINVAL: + return EINVAL; + case WSA_INVALID_HANDLE: + return EBADF; + case WSA_NOT_ENOUGH_MEMORY: + return ENOMEM; + case WSA_INVALID_PARAMETER: + return EINVAL; + case WSAENAMETOOLONG: + return ENAMETOOLONG; + case WSAENOTEMPTY: + return ENOTEMPTY; + case WSAEWOULDBLOCK: + /* not using EWOULDBLOCK as we don't want code to have + * to check both EWOULDBLOCK and EAGAIN */ + return EAGAIN; + case WSAEINPROGRESS: + return EINPROGRESS; + case WSAEALREADY: + return EALREADY; + case WSAENOTSOCK: + return ENOTSOCK; + case WSAEDESTADDRREQ: + return EDESTADDRREQ; + case WSAEMSGSIZE: + return EMSGSIZE; + case WSAEPROTOTYPE: + return EPROTOTYPE; + case WSAENOPROTOOPT: + return ENOPROTOOPT; + case WSAEPROTONOSUPPORT: + return EPROTONOSUPPORT; + case WSAEOPNOTSUPP: + return EOPNOTSUPP; + case WSAEAFNOSUPPORT: + return EAFNOSUPPORT; + case WSAEADDRINUSE: + return EADDRINUSE; + case WSAEADDRNOTAVAIL: + return EADDRNOTAVAIL; + case WSAENETDOWN: + return ENETDOWN; + case WSAENETUNREACH: + return ENETUNREACH; + case WSAENETRESET: + return ENETRESET; + case WSAECONNABORTED: + return ECONNABORTED; + case WSAECONNRESET: + return ECONNRESET; + case WSAENOBUFS: + return ENOBUFS; + case WSAEISCONN: + return EISCONN; + case WSAENOTCONN: + return ENOTCONN; + case WSAETIMEDOUT: + return ETIMEDOUT; + case WSAECONNREFUSED: + return ECONNREFUSED; + case WSAELOOP: + return ELOOP; + case WSAEHOSTUNREACH: + return EHOSTUNREACH; + default: + return EIO; + } +} + +#undef ioctlsocket +int slirp_ioctlsocket_wrap(int fd, int req, void *val) +{ + int ret; +#ifdef __CYGWIN__ + ret = ioctlsocket(fd, req, (__ms_u_long*)val); +#else + ret = ioctlsocket(fd, req, (u_long*)val); +#endif + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef closesocket +int slirp_closesocket_wrap(int fd) +{ + int ret; + ret = closesocket(fd); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef connect +int slirp_connect_wrap(int sockfd, const struct sockaddr *addr, int addrlen) +{ + int ret; + ret = connect(sockfd, addr, addrlen); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef listen +int slirp_listen_wrap(int sockfd, int backlog) +{ + int ret; + ret = listen(sockfd, backlog); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef bind +int slirp_bind_wrap(int sockfd, const struct sockaddr *addr, int addrlen) +{ + int ret; + ret = bind(sockfd, addr, addrlen); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef socket +int slirp_socket_wrap(int domain, int type, int protocol) +{ + int ret; + ret = socket(domain, type, protocol); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef accept +int slirp_accept_wrap(int sockfd, struct sockaddr *addr, int *addrlen) +{ + int ret; + ret = accept(sockfd, addr, addrlen); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef shutdown +int slirp_shutdown_wrap(int sockfd, int how) +{ + int ret; + ret = shutdown(sockfd, how); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef getsockopt +int slirp_getsockopt_wrap(int sockfd, int level, int optname, void *optval, + int *optlen) +{ + int ret; + ret = getsockopt(sockfd, level, optname, (char*)optval, optlen); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef setsockopt +int slirp_setsockopt_wrap(int sockfd, int level, int optname, + const void *optval, int optlen) +{ + int ret; + ret = setsockopt(sockfd, level, optname, (const char*)optval, optlen); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef getpeername +int slirp_getpeername_wrap(int sockfd, struct sockaddr *addr, int *addrlen) +{ + int ret; + ret = getpeername(sockfd, addr, addrlen); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef getsockname +int slirp_getsockname_wrap(int sockfd, struct sockaddr *addr, int *addrlen) +{ + int ret; + ret = getsockname(sockfd, addr, addrlen); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef send +slirp_ssize_t slirp_send_wrap(int sockfd, const void *buf, size_t len, int flags) +{ + int ret; + ret = send(sockfd, (const char*)buf, len, flags); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef sendto +slirp_ssize_t slirp_sendto_wrap(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *addr, int addrlen) +{ + int ret; + ret = sendto(sockfd, (const char*)buf, len, flags, addr, addrlen); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef recv +slirp_ssize_t slirp_recv_wrap(int sockfd, void *buf, size_t len, int flags) +{ + int ret; + ret = recv(sockfd, (char*)buf, len, flags); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef recvfrom +slirp_ssize_t slirp_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags, + struct sockaddr *addr, int *addrlen) +{ + int ret; + ret = recvfrom(sockfd, (char*)buf, len, flags, addr, addrlen); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} +#endif /* WIN32 */ + +void slirp_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'; +} + +/* + * A snprintf()-like function that: + * - returns the number of bytes written (excluding optional \0-ending) + * - dies on error + * - warn on truncation + */ +int slirp_fmt(char *str, size_t size, const char *format, ...) +{ + va_list args; + int rv; + + va_start(args, format); + rv = vsnprintf(str, size, format, args); + va_end(args); + + if (rv >= (int)size) { + fprintf(stderr, "slirp_fmt() truncation\n"); + } + + return MIN(rv, (int)size); +} + +/* + * A snprintf()-like function that: + * - always \0-end (unless size == 0) + * - returns the number of bytes actually written, including \0 ending + * - dies on error + * - warn on truncation + */ +int slirp_fmt0(char *str, size_t size, const char *format, ...) +{ + va_list args; + int rv; + + va_start(args, format); + rv = vsnprintf(str, size, format, args); + va_end(args); + + if (rv >= (int)size) { + fprintf(stderr, "slirp_fmt0() truncation\n"); + if (size > 0) + str[size - 1] = '\0'; + rv = size; + } else { + rv += 1; /* include \0 */ + } + + return rv; +} + +const char *slirp_ether_ntoa(const uint8_t *addr, char *out_str, + size_t out_str_size) +{ + assert(out_str_size >= ETH_ADDRSTRLEN); + + slirp_fmt0(out_str, out_str_size, "%02x:%02x:%02x:%02x:%02x:%02x", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + return out_str; +} + +#endif diff --git a/bochs/iodev/network/slirp/util.h b/bochs/iodev/network/slirp/util.h new file mode 100644 index 0000000000..7dcdafb8c8 --- /dev/null +++ b/bochs/iodev/network/slirp/util.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2010-2019 Red Hat, Inc. + * + * 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. + */ +#ifndef UTIL_H_ +#define UTIL_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include "libslirp.h" + +#ifdef __GNUC__ +#define SLIRP_PACKED_BEGIN +#if defined(_WIN32) && (defined(__x86_64__) || defined(__i386__)) +#define SLIRP_PACKED_END __attribute__((gcc_struct, packed)) +#else +#define SLIRP_PACKED_END __attribute__((packed)) +#endif +#elif defined(_MSC_VER) +#define SLIRP_PACKED_BEGIN __pragma(pack(push, 1)) +#define SLIRP_PACKED_END __pragma(pack(pop)) +#endif + +#ifndef DIV_ROUND_UP +#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) +#endif + +#ifndef container_of +#define container_of(ptr, type, member) \ + ((type *) (((char *)(ptr)) - offsetof(type, member))) +#endif + +#ifndef G_SIZEOF_MEMBER +#define G_SIZEOF_MEMBER(type, member) sizeof(((type *)0)->member) +#endif + +#if defined(_WIN32) /* CONFIG_IOVEC */ +#if !defined(IOV_MAX) /* XXX: to avoid duplicate with QEMU osdep.h */ +struct iovec { + void *iov_base; + size_t iov_len; +}; +#endif +#else +#include +#endif + +#define stringify(s) tostring(s) +#define tostring(s) #s + +#define SCALE_MS 1000000 + +#define ETH_ALEN 6 +#define ETH_ADDRSTRLEN 18 /* "xx:xx:xx:xx:xx:xx", with trailing NUL */ +#define ETH_HLEN 14 +#define ETH_MINLEN 60 +#define ETH_P_IP (0x0800) /* Internet Protocol packet */ +#define ETH_P_ARP (0x0806) /* Address Resolution packet */ +#define ETH_P_IPV6 (0x86dd) +#define ETH_P_VLAN (0x8100) +#define ETH_P_DVLAN (0x88a8) +#define ETH_P_NCSI (0x88f8) +#define ETH_P_UNKNOWN (0xffff) + +/* FIXME: remove me when made standalone */ +#ifdef _WIN32 +#undef accept +#undef bind +#undef closesocket +#undef connect +#undef getpeername +#undef getsockname +#undef getsockopt +#undef ioctlsocket +#undef listen +#undef recv +#undef recvfrom +#undef send +#undef sendto +#undef setsockopt +#undef shutdown +#undef socket +#endif + +#ifdef _WIN32 +#define connect slirp_connect_wrap +int slirp_connect_wrap(int fd, const struct sockaddr *addr, int addrlen); +#define listen slirp_listen_wrap +int slirp_listen_wrap(int fd, int backlog); +#define bind slirp_bind_wrap +int slirp_bind_wrap(int fd, const struct sockaddr *addr, int addrlen); +#define socket slirp_socket_wrap +int slirp_socket_wrap(int domain, int type, int protocol); +#define accept slirp_accept_wrap +int slirp_accept_wrap(int fd, struct sockaddr *addr, int *addrlen); +#define shutdown slirp_shutdown_wrap +int slirp_shutdown_wrap(int fd, int how); +#define getpeername slirp_getpeername_wrap +int slirp_getpeername_wrap(int fd, struct sockaddr *addr, int *addrlen); +#define getsockname slirp_getsockname_wrap +int slirp_getsockname_wrap(int fd, struct sockaddr *addr, int *addrlen); +#define send slirp_send_wrap +slirp_ssize_t slirp_send_wrap(int fd, const void *buf, size_t len, int flags); +#define sendto slirp_sendto_wrap +slirp_ssize_t slirp_sendto_wrap(int fd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, int addrlen); +#define recv slirp_recv_wrap +slirp_ssize_t slirp_recv_wrap(int fd, void *buf, size_t len, int flags); +#define recvfrom slirp_recvfrom_wrap +slirp_ssize_t slirp_recvfrom_wrap(int fd, void *buf, size_t len, int flags, + struct sockaddr *src_addr, int *addrlen); +#define closesocket slirp_closesocket_wrap +int slirp_closesocket_wrap(int fd); +#define ioctlsocket slirp_ioctlsocket_wrap +int slirp_ioctlsocket_wrap(int fd, int req, void *val); +#define getsockopt slirp_getsockopt_wrap +int slirp_getsockopt_wrap(int sockfd, int level, int optname, void *optval, + int *optlen); +#define setsockopt slirp_setsockopt_wrap +int slirp_setsockopt_wrap(int sockfd, int level, int optname, + const void *optval, int optlen); +#define inet_aton slirp_inet_aton +int slirp_inet_aton(const char *cp, struct in_addr *ia); +#else +#define closesocket(s) close(s) +#define ioctlsocket(s, r, v) ioctl(s, r, v) +#endif + +int slirp_socket(int domain, int type, int protocol); +void slirp_set_nonblock(int fd); + +static inline int slirp_socket_set_v6only(int fd, int v) +{ + return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v, sizeof(v)); +} + +static inline int slirp_socket_set_nodelay(int fd) +{ + int v = 1; + return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); +} + +static inline int slirp_socket_set_fast_reuse(int fd) +{ +#ifndef _WIN32 + int v = 1; + return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)); +#else + /* Enabling the reuse of an endpoint that was used by a socket still in + * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows + * fast reuse is the default and SO_REUSEADDR does strange things. So we + * don't have to do anything here. More info can be found at: + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ + return 0; +#endif +} + +void slirp_pstrcpy(char *buf, int buf_size, const char *str); + +int slirp_fmt(char *str, size_t size, const char *format, ...) BX_CPP_AttrPrintf(3, 4); +int slirp_fmt0(char *str, size_t size, const char *format, ...) BX_CPP_AttrPrintf(3, 4); + +/* + * Pretty print a MAC address into out_str. + * As a convenience returns out_str. + */ +const char *slirp_ether_ntoa(const uint8_t *addr, char *out_str, + size_t out_str_len); + +#endif diff --git a/bochs/iodev/sound/Makefile.in b/bochs/iodev/sound/Makefile.in index dcabfb5ce5..4dcc724e00 100644 --- a/bochs/iodev/sound/Makefile.in +++ b/bochs/iodev/sound/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2021 The Bochs Project +# Copyright (C) 2012-2024 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -68,6 +68,7 @@ OBJS_THAT_SUPPORT_OTHER_PLUGINS = opl.o NONPLUGIN_OBJS = @IODEV_EXT_NON_PLUGIN_OBJS@ PLUGIN_OBJS = @IODEV_EXT_PLUGIN_OBJS@ ALSA_SOUND_LINK_OPTS = @ALSA_SOUND_LINK_OPTS@ +PULSE_SOUND_LINK_OPTS = @PULSE_SOUND_LINK_OPTS@ SDL_SOUND_LINK_OPTS = @SDL_SOUND_LINK_OPTS@ WIN_SOUND_LINK_OPTS = -lwinmm WIN_SOUND_LINK_OPTS_VCPP = winmm.lib @@ -105,6 +106,9 @@ libbx_sb16.la: sb16.lo opl.lo libbx_soundalsa.la: soundalsa.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module soundalsa.lo -o libbx_soundalsa.la -rpath $(PLUGIN_PATH) $(ALSA_SOUND_LINK_OPTS) +libbx_soundpulse.la: soundpulse.lo + $(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module soundpulse.lo -o libbx_soundpulse.la -rpath $(PLUGIN_PATH) $(PULSE_SOUND_LINK_OPTS) + libbx_soundsdl.la: soundsdl.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module soundsdl.lo -o libbx_soundsdl.la -rpath $(PLUGIN_PATH) $(SDL_SOUND_LINK_OPTS) @@ -168,6 +172,10 @@ soundalsa.o: soundalsa.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ soundlow.h ../../bxthread.h soundmod.h soundalsa.h +soundpulse.o: soundpulse.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ + ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ + ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ + soundlow.h ../../bxthread.h soundmod.h soundpulse.h sounddummy.o: sounddummy.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ ../../misc/bswap.h ../../plugin.h ../../extplugin.h soundlow.h \ @@ -223,6 +231,10 @@ soundalsa.lo: soundalsa.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ soundlow.h ../../bxthread.h soundmod.h soundalsa.h +soundpulse.lo: soundpulse.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ + ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ + ../../misc/bswap.h ../../plugin.h ../../extplugin.h ../../pc_system.h \ + soundlow.h ../../bxthread.h soundmod.h soundpulse.h sounddummy.lo: sounddummy.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../gui/paramtree.h ../../logio.h ../../instrument/stubs/instrument.h \ ../../misc/bswap.h ../../plugin.h ../../extplugin.h soundlow.h \ diff --git a/bochs/iodev/sound/es1370.cc b/bochs/iodev/sound/es1370.cc index 49aefda162..8752e41171 100644 --- a/bochs/iodev/sound/es1370.cc +++ b/bochs/iodev/sound/es1370.cc @@ -45,7 +45,7 @@ bx_es1370_c* theES1370Device = NULL; -const Bit8u es1370_iomask[64] = {7, 1, 3, 1, 4, 0, 0, 0, 7, 1, 1, 0, 7, 0, 0, 0, +const Bit8u es1370_iomask[64] = {7, 1, 3, 1, 4, 1, 0, 0, 7, 1, 1, 0, 7, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 7, 1, 3, 1, 6, 0, 2, 0, 6, 0, 2, 0, 6, 0, 2, 0, 4, 0, 0, 0, 6, 0, 2, 0, 4, 0, 0, 0, 6, 0, 2, 0}; @@ -379,7 +379,7 @@ void bx_es1370_c::reset(unsigned type) BX_ES1370_THIS s.chan[i].leftover = 0; } - #ifndef ANDROID + #ifndef __ANDROID__ // Gameport is unsupported on Android DEV_gameport_set_enabled(0); #endif @@ -615,7 +615,7 @@ void bx_es1370_c::write(Bit32u address, Bit32u value, unsigned io_len) mask = (0xffffffff >> ((4 - io_len) << 3)) << shift; value = (BX_ES1370_THIS s.ctl & ~mask) | ((value << shift) & mask); if ((value ^ BX_ES1370_THIS s.ctl) & 0x04) { - #ifndef ANDROID + #ifndef __ANDROID__ // Gameport is unsupported on Android DEV_gameport_set_enabled((value & 0x04) != 0); #endif diff --git a/bochs/iodev/sound/soundlow.cc b/bochs/iodev/sound/soundlow.cc index e76e539a92..617818d4c6 100644 --- a/bochs/iodev/sound/soundlow.cc +++ b/bochs/iodev/sound/soundlow.cc @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2021 The Bochs Project +// Copyright (C) 2011-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -91,6 +91,13 @@ void bx_audio_buffer_c::delete_buffer() delete tmpbuffer; } +void bx_audio_buffer_c::flush() +{ + while (root != NULL) { + BX_MSLEEP(1); + } +} + // convert to float format for resampler static void convert_to_float(Bit8u *src, unsigned srcsize, audio_buffer_t *audiobuf) @@ -468,6 +475,7 @@ Bit32u bx_soundlow_waveout_c::resampler_common(audio_buffer_t *inbuffer, float * #else if (param.samplerate != real_pcm_param.samplerate) { real_pcm_param.samplerate = param.samplerate; + audio_buffers[1]->flush(); set_pcm_params(&real_pcm_param); } *fbuffer = new float[inbuffer->size]; diff --git a/bochs/iodev/sound/soundlow.h b/bochs/iodev/sound/soundlow.h index 7cdba516a1..40a65ea910 100644 --- a/bochs/iodev/sound/soundlow.h +++ b/bochs/iodev/sound/soundlow.h @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2021 The Bochs Project +// Copyright (C) 2011-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -75,6 +75,7 @@ class bx_audio_buffer_c { audio_buffer_t *new_buffer(Bit32u size); audio_buffer_t *get_buffer(); void delete_buffer(); + void flush(); private: Bit8u format; audio_buffer_t *root; @@ -85,7 +86,7 @@ void convert_float_to_s16le(float *src, unsigned srcsize, Bit8u *dst); BOCHSAPI_MSVCONLY Bit32u pcm_callback(void *dev, Bit16u rate, Bit8u *buffer, Bit32u len); extern BX_MUTEX(resampler_mutex); -#ifndef ANDROID +#ifndef __ANDROID__ extern BX_MUTEX(mixer_mutex); #endif diff --git a/bochs/iodev/sound/soundpulse.cc b/bochs/iodev/sound/soundpulse.cc new file mode 100644 index 0000000000..e5b04a10bd --- /dev/null +++ b/bochs/iodev/sound/soundpulse.cc @@ -0,0 +1,230 @@ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 The Bochs Project +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// Define BX_PLUGGABLE in files that can be compiled into plugins. For +// platforms that require a special tag on exported symbols, BX_PLUGGABLE +// is used to know when we are exporting symbols and when we are importing. +#define BX_PLUGGABLE + +// PCM playback/recording support using PulseAudio simple API + +#include "bochs.h" +#include "plugin.h" + +#if BX_HAVE_SOUND_PULSE && BX_SUPPORT_SOUNDLOW + +#include "pc_system.h" +#include "soundlow.h" +#include "soundpulse.h" + +#define LOG_THIS + +PLUGIN_ENTRY_FOR_SND_MODULE(pulse) +{ + if (mode == PLUGIN_PROBE) { + return (int)PLUGTYPE_SND; + } + return 0; // Success +} + +// bx_sound_pulse_c class implementation + +bx_soundlow_waveout_c* bx_sound_pulse_c::get_waveout() +{ + if (waveout == NULL) { + waveout = new bx_soundlow_waveout_pulse_c(); + } + return waveout; +} + +bx_soundlow_wavein_c* bx_sound_pulse_c::get_wavein() +{ + if (wavein == NULL) { + wavein = new bx_soundlow_wavein_pulse_c(); + } + return wavein; +} + +// bx_sound_waveout_pulse_c class implementation + +int bx_soundlow_waveout_pulse_c::openwaveoutput(const char *wavedev) +{ + set_pcm_params(&real_pcm_param); + pcm_callback_id = register_wave_callback(this, pcm_callback); + start_resampler_thread(); + start_mixer_thread(); + return BX_SOUNDLOW_OK; +} + +int bx_soundlow_waveout_pulse_c::set_pcm_params(bx_pcm_param_t *param) +{ + pa_sample_spec spec; + int signeddata = param->format & 1; + int pa_error; + + if ((param->bits == 16) && (signeddata == 1)) { + spec.format = PA_SAMPLE_S16LE; + } else if ((param->bits == 8) && (signeddata == 0)) { + spec.format = PA_SAMPLE_U8; + } else { + return BX_SOUNDLOW_ERR; + } + spec.channels = param->channels; + spec.rate = param->samplerate; + if (!(s = pa_simple_new(NULL, "bochs", PA_STREAM_PLAYBACK, NULL, "playback", &spec, NULL, NULL, &pa_error))) { + BX_ERROR(("pa_simple_new() failed: %s", pa_strerror(pa_error))); + return BX_SOUNDLOW_ERR; + } + return BX_SOUNDLOW_OK; +} + +int bx_soundlow_waveout_pulse_c::get_packetsize() +{ + return BX_SOUND_PULSE_BUFSIZE; +} + +int bx_soundlow_waveout_pulse_c::output(int length, Bit8u data[]) +{ + int pa_error; + + if (pa_simple_write(s, data, (size_t)length, &pa_error) < 0) { + BX_ERROR(("pa_simple_write() failed: %s", pa_strerror(pa_error))); + return BX_SOUNDLOW_ERR; + } + return BX_SOUNDLOW_OK; +} + +int bx_soundlow_waveout_pulse_c::closewaveoutput() +{ + int pa_error; + + if (s) { + if (pa_simple_drain(s, &pa_error) < 0) { + BX_ERROR(("pa_simple_drain() failed: %s", pa_strerror(pa_error))); + return BX_SOUNDLOW_ERR; + } + pa_simple_free(s); + } + return BX_SOUNDLOW_OK; +} + +// bx_sound_wavein_pulse_c class implementation + +bx_soundlow_wavein_pulse_c::bx_soundlow_wavein_pulse_c() + :bx_soundlow_wavein_c() +{ + s = NULL; +} + +bx_soundlow_wavein_pulse_c::~bx_soundlow_wavein_pulse_c() +{ + if (s) { + pa_simple_free(s); + s = NULL; + } +} + +int bx_soundlow_wavein_pulse_c::openwaveinput(const char *wavedev, sound_record_handler_t rh) +{ + UNUSED(wavedev); + record_handler = rh; + if (rh != NULL) { + record_timer_index = DEV_register_timer(this, record_timer_handler, 1, 1, 0, "wavein"); + // record timer: inactive, continuous, frequency variable + } + return BX_SOUNDLOW_OK; +} + +int bx_soundlow_wavein_pulse_c::startwaverecord(bx_pcm_param_t *param) +{ + pa_sample_spec spec; + int signeddata = param->format & 1; + int pa_error; + Bit64u timer_val; + Bit8u shift = 0; + + if (record_timer_index != BX_NULL_TIMER_HANDLE) { + if (param->bits == 16) shift++; + if (param->channels == 2) shift++; + record_packet_size = (param->samplerate / 10) << shift; // 0.1 sec + if (record_packet_size > BX_SOUNDLOW_WAVEPACKETSIZE) { + record_packet_size = BX_SOUNDLOW_WAVEPACKETSIZE; + } + timer_val = (Bit64u)record_packet_size * 1000000 / (param->samplerate << shift); + bx_pc_system.activate_timer(record_timer_index, (Bit32u)timer_val, 1); + } + if (memcmp(param, &wavein_param, sizeof(bx_pcm_param_t)) != 0) { + wavein_param = *param; + + if (s) { + pa_simple_free(s); + s = NULL; + } + if ((param->bits == 16) && (signeddata == 1)) { + spec.format = PA_SAMPLE_S16LE; + } else if ((param->bits == 8) && (signeddata == 0)) { + spec.format = PA_SAMPLE_U8; + } else { + return BX_SOUNDLOW_ERR; + } + spec.channels = param->channels; + spec.rate = param->samplerate; + if (!(s = pa_simple_new(NULL, "bochs", PA_STREAM_RECORD, NULL, "record", &spec, NULL, NULL, &pa_error))) { + BX_ERROR(("pa_simple_new() failed: %s", pa_strerror(pa_error))); + return BX_SOUNDLOW_ERR; + } + } + return BX_SOUNDLOW_OK; +} + +int bx_soundlow_wavein_pulse_c::getwavepacket(int length, Bit8u data[]) +{ + int pa_error; + + if (s) { + if (pa_simple_read(s, data, length, &pa_error) < 0) { + BX_ERROR(("pa_simple_read() failed: %s", pa_strerror(pa_error))); + return BX_SOUNDLOW_ERR; + } + } else { + memset(data, 0, length); + } + return BX_SOUNDLOW_OK; +} + +int bx_soundlow_wavein_pulse_c::stopwaverecord() +{ + if (record_timer_index != BX_NULL_TIMER_HANDLE) { + bx_pc_system.deactivate_timer(record_timer_index); + } + return BX_SOUNDLOW_OK; +} + +void bx_soundlow_wavein_pulse_c::record_timer_handler(void *this_ptr) +{ + bx_soundlow_wavein_pulse_c *class_ptr = (bx_soundlow_wavein_pulse_c *) this_ptr; + + class_ptr->record_timer(); +} + +void bx_soundlow_wavein_pulse_c::record_timer(void) +{ + record_handler(this, record_packet_size); +} + +#endif // BX_HAVE_SOUND_PULSE diff --git a/bochs/iodev/sound/soundpulse.h b/bochs/iodev/sound/soundpulse.h new file mode 100644 index 0000000000..aaf8625915 --- /dev/null +++ b/bochs/iodev/sound/soundpulse.h @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 The Bochs Project +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// PCM playback/recording support using PulseAudio simple API + +#if BX_HAVE_SOUND_PULSE + +#define BX_SOUND_PULSE_BUFSIZE BX_SOUNDLOW_WAVEPACKETSIZE + +#include +#include + +class bx_sound_pulse_c : public bx_sound_lowlevel_c { +public: + bx_sound_pulse_c() : bx_sound_lowlevel_c("pulse") {} + virtual ~bx_sound_pulse_c() {} + + virtual bx_soundlow_waveout_c* get_waveout(); + virtual bx_soundlow_wavein_c* get_wavein(); +} bx_sound_pulse; + +// the pulse waveout class + +class bx_soundlow_waveout_pulse_c : public bx_soundlow_waveout_c { +public: + bx_soundlow_waveout_pulse_c() : bx_soundlow_waveout_c() {} + virtual ~bx_soundlow_waveout_pulse_c() {} + + virtual int openwaveoutput(const char *wavedev); + virtual int set_pcm_params(bx_pcm_param_t *param); + virtual int get_packetsize(); + virtual int output(int length, Bit8u data[]); + virtual int closewaveoutput(); +private: + pa_simple *s; +}; + +// the pulse waveoin class + +class bx_soundlow_wavein_pulse_c : public bx_soundlow_wavein_c { +public: + bx_soundlow_wavein_pulse_c(); + virtual ~bx_soundlow_wavein_pulse_c(); + + virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh); + virtual int startwaverecord(bx_pcm_param_t *param); + virtual int getwavepacket(int length, Bit8u data[]); + virtual int stopwaverecord(); + + static void record_timer_handler(void *); + void record_timer(void); +private: + bx_pcm_param_t wavein_param; + pa_simple *s; +}; + +#endif // BX_HAVE_SOUND_PULSE diff --git a/bochs/iodev/sound/soundwin.cc b/bochs/iodev/sound/soundwin.cc index 1726f639fa..28e2899970 100644 --- a/bochs/iodev/sound/soundwin.cc +++ b/bochs/iodev/sound/soundwin.cc @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2021 The Bochs Project +// Copyright (C) 2001-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -114,9 +114,7 @@ int bx_soundlow_waveout_win_c::set_pcm_params(bx_pcm_param_t *param) BX_DEBUG(("set_pcm_params(): %u, %u, %u, %02x", param->samplerate, param->bits, param->channels, param->format)); if (WaveOutOpen != 0) { - ret = waveOutReset(hWaveOut); - ret = waveOutClose(hWaveOut); - WaveOutOpen = 0; + closewaveoutput(); } // try three times to find a suitable format @@ -216,7 +214,7 @@ int bx_soundlow_waveout_win_c::closewaveoutput() if (WaveOutOpen == 1) { waveOutReset(hWaveOut); waveOutClose(hWaveOut); - WaveOutOpen = 1; + WaveOutOpen = 0; } return BX_SOUNDLOW_OK; } diff --git a/bochs/iodev/usb/ohci_core.cc b/bochs/iodev/usb/ohci_core.cc index f373500960..b7a578517d 100644 --- a/bochs/iodev/usb/ohci_core.cc +++ b/bochs/iodev/usb/ohci_core.cc @@ -2,8 +2,8 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2009-2023 Benjamin D Lunt (fys [at] fysnet [dot] net) -// 2009-2023 The Bochs Project +// Copyright (C) 2009-2024 Benjamin D Lunt (fys [at] fysnet [dot] net) +// 2009-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -36,9 +36,6 @@ #include "pci.h" #include "usb_common.h" #include "ohci_core.h" -#if BX_USE_WIN32USBDEBUG - #include "gui/win32usb.h" -#endif #define LOG_THIS @@ -743,19 +740,21 @@ bool bx_ohci_core_c::mem_write(bx_phy_address addr, unsigned len, void *data) hub.op_regs.HcRhDescriptorA.ocpm = (value & (1<<11)) ? 1 : 0; hub.op_regs.HcRhDescriptorA.nps = (value & (1<< 9)) ? 1 : 0; hub.op_regs.HcRhDescriptorA.psm = (value & (1<< 8)) ? 1 : 0; - if (hub.op_regs.HcRhDescriptorA.psm == 0) { - - BX_INFO(("Ben: hub.op_regs.HcRhDescriptorA.psm == 0")); - // all ports have power, etc. - // hub.usb_port[p].HcRhPortStatus.pps = 1 - // Call a routine to set each ports dword (LS, Connected, etc.) - - } else { - - BX_INFO(("Ben: hub.op_regs.HcRhDescriptorA.psm == 1")); - // only ports with bit set in rhstatus have power, etc. - // Call a routine to set each ports dword (LS, Connected, etc.) - + if (hub.op_regs.HcRhDescriptorA.nps == 0) { // psm is only valid if nps == 0 + if (hub.op_regs.HcRhDescriptorA.psm == 0) { + + BX_INFO(("Ben: hub.op_regs.HcRhDescriptorA.psm == 0")); + // all ports have power, etc. + // hub.usb_port[p].HcRhPortStatus.pps = 1 + // Call a routine to set each ports dword (LS, Connected, etc.) + + } else { + + BX_INFO(("Ben: hub.op_regs.HcRhDescriptorA.psm == 1")); + // only ports with bit set in rhstatus have power, etc. + // Call a routine to set each ports dword (LS, Connected, etc.) + + } } break; @@ -774,24 +773,26 @@ bool bx_ohci_core_c::mem_write(bx_phy_address addr, unsigned len, void *data) if (value & (1<<15)) hub.op_regs.HcRhStatus.drwe = 1; if (value & (1<<17)) hub.op_regs.HcRhStatus.ocic = 1; - if (value & (1<<16)) { - if (hub.op_regs.HcRhDescriptorA.psm == 0) { - for (p=0; pusb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0); #endif break; #endif case 0x5C: // HcRhPortStatus[2] #if (USB_OHCI_PORTS < 3) - #if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0); + #if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0); #endif break; #endif case 0x58: // HcRhPortStatus[1] #if (USB_OHCI_PORTS < 2) - #if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0); + #if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0); #endif break; #endif @@ -828,8 +829,8 @@ bool bx_ohci_core_c::mem_write(bx_phy_address addr, unsigned len, void *data) if (hub.usb_port[p].HcRhPortStatus.ccs == 0) hub.usb_port[p].HcRhPortStatus.csc = 1; else { -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_ENABLE, 0, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_ENABLE, 0, 0); #endif hub.usb_port[p].HcRhPortStatus.pes = 1; } @@ -847,8 +848,8 @@ bool bx_ohci_core_c::mem_write(bx_phy_address addr, unsigned len, void *data) if (hub.usb_port[p].HcRhPortStatus.ccs == 0) hub.usb_port[p].HcRhPortStatus.csc = 1; else { -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_RESET, 0, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_RESET, 0, 0); #endif reset_port(p); hub.usb_port[p].HcRhPortStatus.pps = 1; @@ -917,8 +918,8 @@ void bx_ohci_core_c::ohci_timer(void) Bit16u zero = 0; if (hub.op_regs.HcControl.hcfs == OHCI_USB_OPERATIONAL) { -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_FRAME, 0, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_FRAME, 0, 0); #endif // set remaining to the interval amount. hub.op_regs.HcFmRemainingToggle = hub.op_regs.HcFmInterval.fit; @@ -1159,8 +1160,8 @@ int bx_ohci_core_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed, int toggl return 0; } -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_COMMAND, 0, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_COMMAND, 0, 0); #endif // The td->cc field should be 111x if it hasn't been processed yet. diff --git a/bochs/iodev/usb/ohci_core.h b/bochs/iodev/usb/ohci_core.h index 1c1fc05ab4..5a3a5cd09c 100644 --- a/bochs/iodev/usb/ohci_core.h +++ b/bochs/iodev/usb/ohci_core.h @@ -2,8 +2,8 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2009-2023 Benjamin D Lunt (fys [at] fysnet [dot] net) -// 2009-2023 The Bochs Project +// Copyright (C) 2009-2024 Benjamin D Lunt (fys [at] fysnet [dot] net) +// 2009-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/bochs/iodev/usb/uhci_core.cc b/bochs/iodev/usb/uhci_core.cc index 3a686270e3..90ba8c6d5b 100644 --- a/bochs/iodev/usb/uhci_core.cc +++ b/bochs/iodev/usb/uhci_core.cc @@ -55,9 +55,6 @@ #include "pci.h" #include "usb_common.h" #include "uhci_core.h" -#if BX_USE_WIN32USBDEBUG - #include "gui/win32usb.h" -#endif #define LOG_THIS @@ -392,7 +389,7 @@ void bx_uhci_core_c::write(Bit32u address, Bit32u value, unsigned io_len) case 0x00: // command register (16-bit) (R/W) if (value & 0xFF00) BX_DEBUG(("write to command register with bits 15:8 not zero: 0x%04x", value)); - + hub.usb_command.max_packet_size = (value & 0x80) ? 1: 0; hub.usb_command.configured = (value & 0x40) ? 1: 0; hub.usb_command.debug = (value & 0x20) ? 1: 0; @@ -518,9 +515,9 @@ void bx_uhci_core_c::write(Bit32u address, Bit32u value, unsigned io_len) case 0x14: // port #3 non existent, but linux systems check it to see if there are more than 2 BX_ERROR(("write to non existent offset 0x14 (port #3)")); -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER // Non existant Register Port (the next one after the last) - win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_NONEXIST, 0, 0); + SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_NONEXIST, 0, 0); #endif break; @@ -531,9 +528,9 @@ void bx_uhci_core_c::write(Bit32u address, Bit32u value, unsigned io_len) // If the ports reset bit is set, don't allow any writes unless the new write will clear the reset bit if (hub.usb_port[port].reset && ((value & (1 << 9)) != 0)) break; -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER if ((value & (1 << 9)) && !hub.usb_port[port].reset) - win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_RESET, port, 0); + SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_RESET, port, 0); #endif if (value & ((1<<5) | (1<<4) | (1<<0))) BX_DEBUG(("write to one or more read-only bits in port #%d register: 0x%04x", port+1, value)); @@ -560,8 +557,8 @@ void bx_uhci_core_c::write(Bit32u address, Bit32u value, unsigned io_len) hub.usb_port[port].reset = (value & (1<<9)) ? 1 : 0; hub.usb_port[port].resume = (value & (1<<6)) ? 1 : 0; if (!hub.usb_port[port].enabled && (value & (1<<2))) { -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_ENABLE, port, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_ENABLE, port, 0); #endif hub.usb_port[port].enable_changed = 0; } else @@ -611,7 +608,7 @@ void bx_uhci_core_c::uhci_timer_handler(void *this_ptr) // we can loop indefinitely, never ending the 1ms frame. // Therefore, we save a list of queue heads we execute, possibly updating to the // next queue head when a loop is found. -// +// // Let's try to add this queue's address to our stack of processed queues. // if the queue has already been processed, it will be in this list (return TRUE) // if the queue has not been processed yet, return FALSE @@ -637,15 +634,15 @@ bool bx_uhci_core_c::uhci_add_queue(struct USB_UHCI_QUEUE_STACK *stack, const Bi // add the queue's address stack->queue_stack[stack->queue_cnt] = addr; stack->queue_cnt++; - + return 0; } // Called once every 1ms void bx_uhci_core_c::uhci_timer(void) { -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_FRAME, 0, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_FRAME, 0, 0); #endif // If the "global reset" bit was set by software @@ -666,7 +663,7 @@ void bx_uhci_core_c::uhci_timer(void) } return; } - + // if the run bit is set, let's see if we can process a few TDs if (hub.usb_command.schedule) { // our stack of queues we have processed @@ -680,28 +677,28 @@ void bx_uhci_core_c::uhci_timer(void) struct TD td; Bit32u address = hub.usb_frame_base.frame_base + ((hub.usb_frame_num.frame_num & 0x3FF) * sizeof(Bit32u)); - + // reset our queue stack to zero queue_stack.queue_cnt = 0; - + // read in the frame pointer DEV_MEM_READ_PHYSICAL(address, sizeof(Bit32u), (Bit8u *) &item); - + //BX_DEBUG(("Start of Frame %d", hub.usb_frame_num.frame_num & 0x3FF)); - + // start the loop. we allow USB_UHCI_LOOP_COUNT queues to be processed while (count--) { // The UHCI (USB 1.1) only allows so many bytes to be transfered per frame. - // Due to control/bulk reclamation, we need to catch this and stop transferring + // Due to control/bulk reclamation, we need to catch this and stop transferring // or this code will just keep processing TDs. if (bytes_processed >= hub.max_bandwidth) { BX_DEBUG(("Process Bandwidth Limits for this frame (%d with a limit of %d).", bytes_processed, hub.max_bandwidth)); break; } - + if (!USB_UHCI_IS_LINK_VALID(item)) // the the T bit is set, we are done break; - + // is it a queue? if (USB_UHCI_IS_LINK_QUEUE(item)) { // add it to our current list of queues @@ -717,13 +714,13 @@ void bx_uhci_core_c::uhci_timer(void) uhci_add_queue(&queue_stack, item & ~0xF); } } - + // read in the queue DEV_MEM_READ_PHYSICAL(item & ~0xF, sizeof(struct QUEUE), (Bit8u *) &queue); - + // this massively populates the log file, so I keep it commented out //BX_DEBUG(("Queue at 0x%08X: horz = 0x%08X, vert = 0x%08X", item & ~0xF, queue.horz, queue.vert)); - + // if the vert pointer is valid, there are td's in it to process // else only the head pointer may be valid if (!USB_UHCI_IS_LINK_VALID(queue.vert)) { @@ -742,7 +739,7 @@ void bx_uhci_core_c::uhci_timer(void) } continue; } - + // else, we found a Transfer Descriptor address = item & ~0xF; DEV_MEM_READ_PHYSICAL(address, sizeof(struct TD), (Bit8u *) &td); @@ -767,17 +764,17 @@ void bx_uhci_core_c::uhci_timer(void) } } if (td.dword1 & (1<<22)) stalled = was_stall = 1; - + // write back the status to the TD DEV_MEM_WRITE_PHYSICAL(address + sizeof(Bit32u), sizeof(Bit32u), (Bit8u *) &td.dword1); -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER // trigger again so that the user can see the processed packet - win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_COMMAND, address, USB_LPARAM_FLAG_AFTER); + SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_COMMAND, address, USB_LPARAM_FLAG_AFTER); #endif // we processed another td within this queue line td_count++; bytes_processed += r_actlen; - + // move to the next item if (!was_stall) { item = td.dword0; @@ -803,11 +800,11 @@ void bx_uhci_core_c::uhci_timer(void) } } } - + // move to next item (no queues) or queue head (queues found) item = (queue_addr != 0) ? queue.horz : td.dword0; } // while loop - + // set the status register bit:0 to 1 if SPD is enabled // and if interrupts not masked via interrupt register, raise irq interrupt. if (shortpacket) hub.usb_status.status2 |= STATUS2_SPD; @@ -836,7 +833,7 @@ void bx_uhci_core_c::uhci_timer(void) if (interrupt || shortpacket) { hub.usb_status.interrupt = 1; } - + // if we needed to fire an interrupt now, lets do it *after* we increment the frame_num register update_irq(); } // end run schedule @@ -892,7 +889,7 @@ int bx_uhci_core_c::event_handler(int event, void *ptr, int port) case USB_EVENT_DEFAULT_SPEED: // return default speed for specified port number return USB_SPEED_FULL; - + case USB_EVENT_CHECK_SPEED: if (ptr != NULL) { usb_device_c *usb_device = (usb_device_c *) ptr; @@ -904,7 +901,7 @@ int bx_uhci_core_c::event_handler(int event, void *ptr, int port) BX_ERROR(("unknown/unsupported event (id=%d) on port #%d", event, port+1)); ret = -1; // unknown event, event not handled } - + return ret; } @@ -922,9 +919,9 @@ bool bx_uhci_core_c::DoTransfer(Bit32u address, struct TD *td) } BX_DEBUG(("TD found at address 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X", address, td->dword0, td->dword1, td->dword2, td->dword3)); - -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_COMMAND, address, USB_LPARAM_FLAG_BEFORE); + +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_COMMAND, address, USB_LPARAM_FLAG_BEFORE); #endif // check TD to make sure it is valid @@ -945,7 +942,7 @@ bool bx_uhci_core_c::DoTransfer(Bit32u address, struct TD *td) if (td->dword1 & (1 << 25)) { BX_ERROR(("UHCI Core: ISO bit is set...")); } - + // the reserved bit in the Link Pointer should be zero if (td->dword0 & (1<<3)) { BX_INFO(("UHCI Core: Reserved bit in the Link Pointer is not zero.")); diff --git a/bochs/iodev/usb/uhci_core.h b/bochs/iodev/usb/uhci_core.h index 2a96c991a7..28b339a876 100644 --- a/bochs/iodev/usb/uhci_core.h +++ b/bochs/iodev/usb/uhci_core.h @@ -3,7 +3,7 @@ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2009-2023 Benjamin D Lunt (fys [at] fysnet [dot] net) -// 2009-2023 The Bochs Project +// 2009-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -200,9 +200,7 @@ class bx_uhci_core_c : public bx_pci_device_c { int event_handler(int event, void *ptr, int port); -#if !BX_USE_WIN32USBDEBUG protected: -#endif bx_uhci_core_t hub; Bit8u global_reset; diff --git a/bochs/iodev/usb/usb_ehci.cc b/bochs/iodev/usb/usb_ehci.cc index 85d4d2b1a1..6f0818e901 100644 --- a/bochs/iodev/usb/usb_ehci.cc +++ b/bochs/iodev/usb/usb_ehci.cc @@ -4,7 +4,7 @@ // // Experimental USB EHCI adapter (partly ported from Qemu) // -// Copyright (C) 2015-2023 The Bochs Project +// Copyright (C) 2015-2024 The Bochs Project // // Copyright(c) 2008 Emutex Ltd. (address@hidden) // Copyright(c) 2011-2012 Red Hat, Inc. @@ -48,9 +48,6 @@ #include "ohci_core.h" #include "qemu-queue.h" #include "usb_ehci.h" -#if BX_USE_WIN32USBDEBUG - #include "gui/win32usb.h" -#endif #define LOG_THIS theUSB_EHCI-> @@ -242,7 +239,7 @@ void bx_usb_ehci_c::init(void) bx_param_string_c *options; bx_param_bool_c *over_current; Bit8u devfunc; - + /* If you wish to set DEBUG=report in the code, instead of * in the configuration, simply uncomment this line. I use * it when I am working on this emulation. @@ -288,6 +285,11 @@ void bx_usb_ehci_c::init(void) BX_EHCI_THIS uhci[0]->init_uhci(devfunc | 0x00, 0x8086, 0x24c2, 0x01, 0x80, BX_PCI_INTA); BX_EHCI_THIS uhci[1]->init_uhci(devfunc | 0x01, 0x8086, 0x24c4, 0x01, 0x00, BX_PCI_INTB); BX_EHCI_THIS uhci[2]->init_uhci(devfunc | 0x02, 0x8086, 0x24c7, 0x01, 0x00, BX_PCI_INTC); +#if BX_USB_DEBUGGER + if (SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get() == USB_DEBUG_UHCI) { + SIM->register_usb_debug_type(USB_DEBUG_UHCI); + } +#endif } else if (companion_type == EHCI_COMPANION_OHCI) { // initialize readonly registers // 0x8086 = vendor (Intel) @@ -304,9 +306,14 @@ void bx_usb_ehci_c::init(void) BX_EHCI_THIS ohci[0]->init_ohci(devfunc | 0x00, 0x8086, 0x880C, 0x00, 0x80, BX_PCI_INTA); BX_EHCI_THIS ohci[1]->init_ohci(devfunc | 0x01, 0x8086, 0x880D, 0x00, 0x00, BX_PCI_INTB); BX_EHCI_THIS ohci[2]->init_ohci(devfunc | 0x02, 0x8086, 0x880E, 0x00, 0x00, BX_PCI_INTC); +#if BX_USB_DEBUGGER + if (SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get() == USB_DEBUG_OHCI) { + SIM->register_usb_debug_type(USB_DEBUG_OHCI); + } +#endif } else BX_PANIC(("Unknown EHCI Companion Type found...")); - + // initialize capability registers BX_EHCI_THIS hub.cap_regs.CapLength = OPS_REGS_OFFSET; BX_EHCI_THIS hub.cap_regs.HciVersion = 0x0100; @@ -341,6 +348,12 @@ void bx_usb_ehci_c::init(void) QTAILQ_INIT(&BX_EHCI_THIS hub.aqueues); QTAILQ_INIT(&BX_EHCI_THIS hub.pqueues); +#if BX_USB_DEBUGGER + if (SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get() == USB_DEBUG_EHCI) { + SIM->register_usb_debug_type(USB_DEBUG_EHCI); + } +#endif + BX_INFO(("USB EHCI initialized")); } @@ -703,7 +716,7 @@ void bx_usb_ehci_c::change_port_owner(int port) usb_device_c *device = BX_EHCI_THIS hub.usb_port[port].device; if (BX_EHCI_THIS hub.usb_port[port].owner_change) { BX_DEBUG(("port #%d: owner change to %s", port + 1, - BX_EHCI_THIS hub.usb_port[port].portsc.po ? "EHCI" : + BX_EHCI_THIS hub.usb_port[port].portsc.po ? "EHCI" : ((BX_EHCI_THIS companion_type == EHCI_COMPANION_UHCI) ? "UHCI" : "OHCI"))); if (device != NULL) { set_connect_status(port, 0); @@ -728,7 +741,7 @@ void bx_usb_ehci_c::change_port_owner(int port) Bit64u bx_usb_ehci_c::create_port_routing(int n_cc, int n_pcc) { Bit64u ret = 0; - + #if EHCI_PORT_ROUTE // for simplicity sake, we place them in 'accending' order. for (int c = n_cc; c > 0; c--) { @@ -749,14 +762,14 @@ Bit64u bx_usb_ehci_c::create_port_routing(int n_cc, int n_pcc) BX_DEBUG(("%s", str)); } #endif - + return ret; } // returns the controller and port number on that controller of the // associated companion controller. // returns false if out of range. -// note: +// note: // this code is a little more detailed than needed. // for example. We could actually just do: // *n_cc = (int) (route >> (4 * port)) & 0xF; @@ -903,7 +916,7 @@ bool bx_usb_ehci_c::read_handler(bx_phy_address addr, unsigned len, void *data, *((Bit64u *) data) = GET64_FROM_HI32_LO32(val_hi, val); break; default: - BX_ERROR(("bx_usb_ehci_c::read_handler unsupported length %d", len)); + BX_ERROR(("bx_usb_ehci_c::read_handler unsupported length %d", len)); } #if BX_PHY_ADDRESS_LONG @@ -1027,24 +1040,24 @@ bool bx_usb_ehci_c::write_handler(bx_phy_address addr, unsigned len, void *data, BX_EHCI_THIS hub.usb_port[port].device->usb_send_msg(USB_MSG_RESET); BX_EHCI_THIS hub.usb_port[port].portsc.csc = 0; if (BX_EHCI_THIS hub.usb_port[port].device->get_speed() == USB_SPEED_HIGH) { -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_EHCI, USB_DEBUG_ENABLE, 0, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_EHCI, USB_DEBUG_ENABLE, 0, 0); #endif BX_EHCI_THIS hub.usb_port[port].portsc.ped = 1; } } } -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER if (!oldpr && BX_EHCI_THIS hub.usb_port[port].portsc.pr) { - win32_usb_trigger(USB_DEBUG_EHCI, USB_DEBUG_RESET, 0, 0); + SIM->usb_debug_trigger(USB_DEBUG_EHCI, USB_DEBUG_RESET, 0, 0); } #endif if (oldfpr && !BX_EHCI_THIS hub.usb_port[port].portsc.fpr) { BX_EHCI_THIS hub.usb_port[port].portsc.sus = 0; } -#if BX_USE_WIN32USBDEBUG +#if BX_USB_DEBUGGER } else if (port == USB_EHCI_PORTS) { - win32_usb_trigger(USB_DEBUG_EHCI, USB_DEBUG_NONEXIST, 0, 0); + SIM->usb_debug_trigger(USB_DEBUG_EHCI, USB_DEBUG_NONEXIST, 0, 0); #endif } } @@ -1475,7 +1488,7 @@ int bx_usb_ehci_c::event_handler(int event, void *ptr, int port) case USB_EVENT_DEFAULT_SPEED: // return default speed for specified port number return USB_SPEED_HIGH; - + case USB_EVENT_CHECK_SPEED: if (ptr != NULL) { usb_device_c *usb_device = (usb_device_c *) ptr; @@ -1554,7 +1567,7 @@ int bx_usb_ehci_c::execute(EHCIPacket *p) int ret; int endp; - // if we remove the device, or signal an over-current, there is a possibility + // if we remove the device, or signal an over-current, there is a possibility // that 'dev' is NULL. simply return that we transfered zero bytes. // ( we can't return USB_RET_PROCERR, since this code will then reset the HC. // On an over-current, we don't want the HC to reset... ) @@ -1909,8 +1922,8 @@ int bx_usb_ehci_c::state_fetchqtd(EHCIQueue *q) EHCIqtd qtd; int again = 0; -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_EHCI, USB_DEBUG_COMMAND, 0, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_EHCI, USB_DEBUG_COMMAND, 0, 0); #endif get_dwords(NLPTR_GET(q->qtdaddr), (Bit32u*) &qtd, sizeof(EHCIqtd) >> 2); @@ -2272,7 +2285,7 @@ void bx_usb_ehci_c::advance_async_state(void) default: /* this should only be due to a developer mistake */ // Ben: I commented this line due to the fact that after a USB_RET_ASYNC return, - // then a usb_packet_complete(p), the event handler is setting the astate to + // then a usb_packet_complete(p), the event handler is setting the astate to // EST_EXECUTE instead of EST_ACTIVE ??? //BX_PANIC(("Bad asynchronous state %d. Resetting to active", BX_EHCI_THIS hub.astate)); BX_EHCI_THIS set_state(async, EST_ACTIVE); @@ -2367,9 +2380,9 @@ void bx_usb_ehci_c::ehci_frame_timer(void) Bit64u t_now = bx_pc_system.time_usec(); usec_elapsed = t_now - BX_EHCI_THIS hub.last_run_usec; frames = (int)(usec_elapsed / FRAME_TIMER_USEC); - -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_EHCI, USB_DEBUG_FRAME, 0, 0); + +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_EHCI, USB_DEBUG_FRAME, 0, 0); #endif if (BX_EHCI_THIS periodic_enabled() || (BX_EHCI_THIS hub.pstate != EST_INACTIVE)) { diff --git a/bochs/iodev/usb/usb_ohci.cc b/bochs/iodev/usb/usb_ohci.cc index 75feb7129e..1df6d86443 100644 --- a/bochs/iodev/usb/usb_ohci.cc +++ b/bochs/iodev/usb/usb_ohci.cc @@ -3,7 +3,7 @@ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2009-2023 Benjamin D Lunt (fys [at] fysnet [dot] net) -// 2009-2023 The Bochs Project +// 2009-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -141,7 +141,7 @@ void bx_usb_ohci_c::init(void) * it when I am working on this emulation. */ //LOG_THIS setonoff(LOGLEV_DEBUG, ACT_REPORT); - + // Read in values from config interface ohci = (bx_list_c*) SIM->get_param(BXPN_USB_OHCI); // Check if the device is disabled or not configured @@ -175,6 +175,12 @@ void bx_usb_ohci_c::init(void) BX_OHCI_THIS rt_conf_id = SIM->register_runtime_config_handler(BX_OHCI_THIS_PTR, runtime_config_handler); BX_OHCI_THIS device_change = 0; +#if BX_USB_DEBUGGER + if (SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get() == USB_DEBUG_OHCI) { + SIM->register_usb_debug_type(USB_DEBUG_OHCI); + } +#endif + BX_INFO(("USB OHCI initialized")); } diff --git a/bochs/iodev/usb/usb_uhci.cc b/bochs/iodev/usb/usb_uhci.cc index 5980ce2ed2..d15daaf6f6 100644 --- a/bochs/iodev/usb/usb_uhci.cc +++ b/bochs/iodev/usb/usb_uhci.cc @@ -3,7 +3,7 @@ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2009-2023 Benjamin D Lunt (fys [at] fysnet [dot] net) -// 2009-2023 The Bochs Project +// 2009-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -111,7 +111,7 @@ bx_usb_uhci_c::~bx_usb_uhci_c() char pname[32]; SIM->unregister_runtime_config_handler(rt_conf_id); - + for (int i=0; iget_param_enum(pname, SIM->get_param(BXPN_USB_UHCI))->set_handler(NULL); @@ -121,11 +121,11 @@ bx_usb_uhci_c::~bx_usb_uhci_c() SIM->get_param_bool(pname, SIM->get_param(BXPN_USB_UHCI))->set_handler(NULL); remove_device(i); } - + SIM->get_bochs_root()->remove("usb_uhci"); bx_list_c *usb_rt = (bx_list_c *) SIM->get_param(BXPN_MENU_RUNTIME_USB); usb_rt->remove("uhci"); - + BX_DEBUG(("Exit")); } @@ -187,6 +187,12 @@ void bx_usb_uhci_c::init(void) BX_UHCI_THIS rt_conf_id = SIM->register_runtime_config_handler(BX_UHCI_THIS_PTR, runtime_config_handler); BX_UHCI_THIS device_change = 0; +#if BX_USB_DEBUGGER + if (SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get() == USB_DEBUG_UHCI) { + SIM->register_usb_debug_type(USB_DEBUG_UHCI); + } +#endif + BX_INFO(("USB UHCI initialized")); } diff --git a/bochs/iodev/usb/usb_xhci.cc b/bochs/iodev/usb/usb_xhci.cc index 54ef6f0780..231fea56d9 100644 --- a/bochs/iodev/usb/usb_xhci.cc +++ b/bochs/iodev/usb/usb_xhci.cc @@ -3,7 +3,7 @@ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2010-2023 Benjamin D Lunt (fys [at] fysnet [dot] net) -// 2011-2023 The Bochs Project +// 2011-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -70,9 +70,6 @@ #include "pci.h" #include "usb_common.h" #include "usb_xhci.h" -#if BX_USE_WIN32USBDEBUG - #include "gui/win32usb.h" -#endif #define LOG_THIS theUSB_XHCI-> @@ -298,7 +295,11 @@ void bx_usb_xhci_c::init(void) // if n_ports is not given in the Bochsrc.txt file, the number of ports // is defaulted to the controller type above Bit32s n_ports = SIM->get_param_num(BXPN_XHCI_N_PORTS)->get(); - if (n_ports > -1) BX_XHCI_THIS hub.n_ports = n_ports; + if (n_ports > -1) { + BX_XHCI_THIS hub.n_ports = n_ports; + } else { + SIM->get_param_num(BXPN_XHCI_N_PORTS)->set(BX_XHCI_THIS hub.n_ports); + } if ((BX_XHCI_THIS hub.n_ports < 2) || (BX_XHCI_THIS hub.n_ports > USB_XHCI_PORTS_MAX) || (BX_XHCI_THIS hub.n_ports & 1)) { BX_PANIC(("n_ports (%d) must be at least 2, not more than %d, and must be an even number.", BX_XHCI_THIS hub.n_ports, USB_XHCI_PORTS_MAX)); return; @@ -355,9 +356,9 @@ void bx_usb_xhci_c::init(void) // The remaining is the code to adjust all items that depend // on the count of port registers. This needs to be done at run-time // so that we can adjust the count without hard-coding anything. - // We divide the sets evenly and place the USB3 register sets + // We divide the sets evenly and place the USB3 register sets // before the USB2 register sets. - + // initialize the allowed speeds for each port // initialize the paired port number for each port // TODO: port_speed_allowed is currently unused @@ -416,6 +417,12 @@ void bx_usb_xhci_c::init(void) protocol->start_index = (BX_XHCI_THIS hub.n_ports / 2) + 1; // 1 based starting index protocol->count = BX_XHCI_THIS hub.n_ports / 2; +#if BX_USB_DEBUGGER + if (SIM->get_param_enum(BXPN_USB_DEBUG_TYPE)->get() == USB_DEBUG_XHCI) { + SIM->register_usb_debug_type(USB_DEBUG_XHCI); + } +#endif + // done initializing BX_INFO(("USB xHCI initialized")); } @@ -759,7 +766,7 @@ void bx_usb_xhci_c::reset_port_usb3(int port, int reset_type) // bit 21 = 1 if CCS = 1, bit 19 always 1 // bit 21 = 1 if CCS = 0, bit 19 always 1 if (reset_type == HOT_RESET) { - BX_XHCI_THIS hub.usb_port[port].portsc.prc = + BX_XHCI_THIS hub.usb_port[port].portsc.prc = BX_XHCI_THIS hub.usb_port[port].portsc.ccs; BX_XHCI_THIS hub.usb_port[port].portsc.wrc = 0; } else { @@ -935,6 +942,7 @@ void bx_usb_xhci_c::register_state(void) BXRS_PARAM_BOOL(reg, ca, BX_XHCI_THIS hub.op_regs.HcCrcr.ca); BXRS_PARAM_BOOL(reg, cs, BX_XHCI_THIS hub.op_regs.HcCrcr.cs); BXRS_PARAM_BOOL(reg, rcs, BX_XHCI_THIS hub.op_regs.HcCrcr.rcs); + BXRS_HEX_PARAM_FIELD(reg, actual, BX_XHCI_THIS hub.op_regs.HcCrcr.actual); BXRS_HEX_PARAM_FIELD(reg_grp, HcDCBAAP, BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap); BXRS_HEX_PARAM_FIELD(reg_grp, HcConfig_MaxSlotsEn, BX_XHCI_THIS hub.op_regs.HcConfig.MaxSlotsEn); #if ((VERSION_MAJOR == 1) && (VERSION_MINOR >= 0x10)) @@ -1196,6 +1204,7 @@ bool bx_usb_xhci_c::read_handler(bx_phy_address addr, unsigned len, void *data, #endif } } + // Operational Registers else if ((offset >= OPS_REGS_OFFSET) && (offset < (OPS_REGS_OFFSET + 0x40))) { switch (offset - OPS_REGS_OFFSET) { @@ -1296,6 +1305,7 @@ bool bx_usb_xhci_c::read_handler(bx_phy_address addr, unsigned len, void *data, break; } } + // Register Port Sets else if ((offset >= XHCI_PORT_SET_OFFSET) && (offset < (XHCI_PORT_SET_OFFSET + (BX_XHCI_THIS hub.n_ports * 16)))) { unsigned port = (((offset - XHCI_PORT_SET_OFFSET) >> 4) & 0x3F); // calculate port number @@ -1369,6 +1379,7 @@ bool bx_usb_xhci_c::read_handler(bx_phy_address addr, unsigned len, void *data, val = 0; } } + // Extended Capabilities else if ((offset >= EXT_CAPS_OFFSET) && (offset < (EXT_CAPS_OFFSET + EXT_CAPS_SIZE))) { unsigned caps_offset = (offset - EXT_CAPS_OFFSET); @@ -1393,6 +1404,7 @@ bool bx_usb_xhci_c::read_handler(bx_phy_address addr, unsigned len, void *data, break; } } + // Host Controller Runtime Registers else if ((offset >= RUNTIME_OFFSET) && (offset < (RUNTIME_OFFSET + 32 + (INTERRUPTERS * 32)))) { if (offset == RUNTIME_OFFSET) { @@ -1486,7 +1498,7 @@ bool bx_usb_xhci_c::read_handler(bx_phy_address addr, unsigned len, void *data, *((Bit64u *) data) = GET64_FROM_HI32_LO32(val_hi, val); break; default: - BX_ERROR(("bx_usb_ehci_c::read_handler unsupported length %d", len)); + BX_ERROR(("bx_usb_ehci_c::read_handler unsupported length %d", len)); } // don't populate the log file if reading from interrupter's IMAN and only INT_ENABLE is set. @@ -1550,6 +1562,7 @@ bool bx_usb_xhci_c::write_handler(bx_phy_address addr, unsigned len, void *data, break; } } + // Operational Registers else if ((offset >= OPS_REGS_OFFSET) && (offset < (OPS_REGS_OFFSET + 0x40))) { switch (offset - OPS_REGS_OFFSET) { @@ -1770,6 +1783,7 @@ bool bx_usb_xhci_c::write_handler(bx_phy_address addr, unsigned len, void *data, break; } } + // Register Port Sets else if ((offset >= XHCI_PORT_SET_OFFSET) && (offset < (XHCI_PORT_SET_OFFSET + (BX_XHCI_THIS hub.n_ports * 16)))) { unsigned port = (((offset - XHCI_PORT_SET_OFFSET) >> 4) & 0x3F); // calculate port number @@ -1836,8 +1850,8 @@ bool bx_usb_xhci_c::write_handler(bx_phy_address addr, unsigned len, void *data, if (((value & (1 << 31)) && BX_XHCI_THIS hub.usb_port[port].is_usb3) || (value & (1 << 4))) { reset_port_usb3(port, (value & (1 << 4)) ? HOT_RESET : WARM_RESET); -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_XHCI, USB_DEBUG_RESET, 0, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_XHCI, USB_DEBUG_RESET, 0, 0); #endif } } else @@ -1900,12 +1914,14 @@ bool bx_usb_xhci_c::write_handler(bx_phy_address addr, unsigned len, void *data, break; } } -#if BX_USE_WIN32USBDEBUG + +#if BX_USB_DEBUGGER // Non existant Register Port (the next one after the last) else if (offset == (XHCI_PORT_SET_OFFSET + (BX_XHCI_THIS hub.n_ports * 16))) { - win32_usb_trigger(USB_DEBUG_XHCI, USB_DEBUG_NONEXIST, 0, 0); - } + SIM->usb_debug_trigger(USB_DEBUG_XHCI, USB_DEBUG_NONEXIST, 0, 0); + } #endif + // Extended Capabilities else if ((offset >= EXT_CAPS_OFFSET) && (offset < (EXT_CAPS_OFFSET + EXT_CAPS_SIZE))) { unsigned caps_offset = (offset - EXT_CAPS_OFFSET); @@ -1925,6 +1941,7 @@ bool bx_usb_xhci_c::write_handler(bx_phy_address addr, unsigned len, void *data, qword >>= 8; } } + // Host Controller Runtime Registers else if ((offset >= RUNTIME_OFFSET) && (offset < (RUNTIME_OFFSET + 32 + (INTERRUPTERS * 32)))) { if (offset == RUNTIME_OFFSET) { @@ -2010,6 +2027,7 @@ bool bx_usb_xhci_c::write_handler(bx_phy_address addr, unsigned len, void *data, } } } + // Doorbell Registers else if ((offset >= DOORBELL_OFFSET) && (offset < (DOORBELL_OFFSET + 4 + (INTERRUPTERS * 4)))) { if (value & (0xFF << 8)) @@ -2047,7 +2065,7 @@ bool bx_usb_xhci_c::write_handler(bx_phy_address addr, unsigned len, void *data, (primary_id < PSA_MAX_SIZE_NUM(BX_XHCI_THIS hub.slots[doorbell].ep_context[ep].ep_context.max_pstreams)) && BX_XHCI_THIS hub.slots[doorbell].ep_context[ep].stream[primary_id].valid == 1) { BX_XHCI_THIS hub.slots[doorbell].ep_context[ep].stream[primary_id].tr_dequeue_pointer = - BX_XHCI_THIS process_transfer_ring(doorbell, ep, BX_XHCI_THIS hub.slots[doorbell].ep_context[ep].stream[primary_id].tr_dequeue_pointer, + BX_XHCI_THIS process_transfer_ring(doorbell, ep, BX_XHCI_THIS hub.slots[doorbell].ep_context[ep].stream[primary_id].tr_dequeue_pointer, &BX_XHCI_THIS hub.slots[doorbell].ep_context[ep].stream[primary_id].dcs, primary_id); } else { BX_ERROR(("Stream Context with bad Primary Stream ID (%d)", primary_id)); @@ -2073,7 +2091,7 @@ bool bx_usb_xhci_c::write_handler(bx_phy_address addr, unsigned len, void *data, #endif // standard trb ring BX_XHCI_THIS hub.slots[doorbell].ep_context[ep].enqueue_pointer = - BX_XHCI_THIS process_transfer_ring(doorbell, ep, BX_XHCI_THIS hub.slots[doorbell].ep_context[ep].enqueue_pointer, + BX_XHCI_THIS process_transfer_ring(doorbell, ep, BX_XHCI_THIS hub.slots[doorbell].ep_context[ep].enqueue_pointer, &BX_XHCI_THIS hub.slots[doorbell].ep_context[ep].rcs, 0); #if MAX_PSA_SIZE > 0 } @@ -2149,7 +2167,7 @@ int bx_usb_xhci_c::event_handler(int event, void *ptr, int port) if (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.max_pstreams > 0) { // specifying streams BX_DEBUG(("Event Handler: USB_EVENT_ASYNC: slot %d, ep %d, stream ID %d", slot, ep, p->packet.strm_pid)); BX_XHCI_THIS hub.slots[slot].ep_context[ep].stream[p->packet.strm_pid].tr_dequeue_pointer = - BX_XHCI_THIS process_transfer_ring(slot, ep, BX_XHCI_THIS hub.slots[slot].ep_context[ep].stream[p->packet.strm_pid].tr_dequeue_pointer, + BX_XHCI_THIS process_transfer_ring(slot, ep, BX_XHCI_THIS hub.slots[slot].ep_context[ep].stream[p->packet.strm_pid].tr_dequeue_pointer, &BX_XHCI_THIS hub.slots[slot].ep_context[ep].stream[p->packet.strm_pid].dcs, p->packet.strm_pid); } else { BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer = @@ -2170,7 +2188,7 @@ int bx_usb_xhci_c::event_handler(int event, void *ptr, int port) write_event_TRB(0, ((port + 1) << 24), TRB_SET_COMP_CODE(1), TRB_SET_TYPE(PORT_STATUS_CHANGE), 1); } break; - + // host controller events start here case USB_EVENT_DEFAULT_SPEED: // return default speed for specified port number @@ -2180,7 +2198,7 @@ int bx_usb_xhci_c::event_handler(int event, void *ptr, int port) } // else return high-speed return USB_SPEED_HIGH; - + case USB_EVENT_CHECK_SPEED: // all super-speed device must be on the first half port register sets, // while all non-super-speed device must be on the second half. @@ -2527,9 +2545,9 @@ void bx_usb_xhci_c::process_command_ring(void) Bit8u buffer[CONTEXT_SIZE + (32 * CONTEXT_SIZE)]; struct SLOT_CONTEXT slot_context; struct EP_CONTEXT ep_context; - -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_XHCI, USB_DEBUG_COMMAND, 0, 0); + +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_XHCI, USB_DEBUG_COMMAND, 0, 0); #endif if (!BX_XHCI_THIS hub.op_regs.HcCrcr.crr) @@ -2570,14 +2588,14 @@ void bx_usb_xhci_c::process_command_ring(void) * (A 16-bit value in the high-order of TRB.Command and a 16-bit value in * the low-order of TRB.Status) * I do not have permission from NEC/Renesas to show the code that calculates and - * returns the correct verification values. Therefore, this simply returns. - * As long as you are not using a compatible NEC/Renesas driver, everything + * returns the correct verification values. Therefore, this simply returns. + * As long as you are not using a compatible NEC/Renesas driver, everything * should be fine. */ case NEC_TRB_TYPE_GET_UN: BX_DEBUG(("NEC GET Verification TRB found.")); break; - + /* Bochs Dump Controller command: * This command simply dumps the controller's contents to the debug file. * This is useful for displaying the controller before and then after a given command. @@ -2646,7 +2664,7 @@ void bx_usb_xhci_c::process_command_ring(void) copy_slot_from_buffer(&slot_context, &buffer[CONTEXT_SIZE]); copy_ep_from_buffer(&ep_context, &buffer[CONTEXT_SIZE + CONTEXT_SIZE]); // check that the Input contexts are valid - if ((validate_slot_context(&slot_context, trb_command, slot) == TRB_SUCCESS) && + if ((validate_slot_context(&slot_context, trb_command, slot) == TRB_SUCCESS) && (validate_ep_context(&ep_context, trb_command, 0, slot_context.rh_port_num - 1, 1) == TRB_SUCCESS)) { if (bsr == 1) { // BSR flag set if (BX_XHCI_THIS hub.slots[slot].slot_context.slot_state == SLOT_STATE_DISABLED_ENABLED) { @@ -2747,7 +2765,7 @@ void bx_usb_xhci_c::process_command_ring(void) write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(comp_code), TRB_SET_SLOT(slot) | TRB_SET_TYPE(COMMAND_COMPLETION), 1); BX_DEBUG(("0x" FORMATADDRESS ": Command Ring: Evaluate TRB (slot = %d) (d_flags = 0x%08X) (a_flags = 0x%08X) (returning %d)", (bx_phy_address) org_addr, slot, d_flags, a_flags, comp_code)); - + break; case CONFIG_EP: { @@ -2771,7 +2789,7 @@ void bx_usb_xhci_c::process_command_ring(void) BX_XHCI_THIS hub.slots[slot].slot_context.slot_state = SLOT_STATE_ADDRESSED; update_slot_context(slot); } else - + if (BX_XHCI_THIS hub.slots[slot].slot_context.slot_state >= SLOT_STATE_ADDRESSED) { comp_code = TRB_SUCCESS; // assume good completion if ((d_flags & 3) > 0) // the D0 (slot) and D1 (ep0) bits must be cleared @@ -2781,7 +2799,7 @@ void bx_usb_xhci_c::process_command_ring(void) } else { comp_code = PARAMETER_ERROR; } - + // Check all the input context entries with an a_flag == 1 for (i=2; i<32; i++) { if (a_flags & (1< 0; BX_XHCI_THIS hub.slots[slot].ep_context[ep].edtla = 0; update_ep_context(slot, ep); @@ -3019,12 +3037,12 @@ void bx_usb_xhci_c::init_event_ring(unsigned interrupter) BX_XHCI_THIS hub.ring_members.event_rings[interrupter].entrys[0].addr; BX_XHCI_THIS hub.ring_members.event_rings[interrupter].trb_count = BX_XHCI_THIS hub.ring_members.event_rings[interrupter].entrys[0].size; - + // check that the guest uses correct segment sizes for (int i=0; i 4096)) { - BX_ERROR(("Event Ring Segment %d has a size of %d which is invalid.", i, + BX_ERROR(("Event Ring Segment %d has a size of %d which is invalid.", i, BX_XHCI_THIS hub.ring_members.event_rings[interrupter].entrys[i].size)); } } @@ -3045,13 +3063,13 @@ void bx_usb_xhci_c::write_event_TRB(unsigned interrupter, Bit64u parameter, Bit3 write_TRB((bx_phy_address) BX_XHCI_THIS hub.ring_members.event_rings[interrupter].cur_trb, parameter, status, command | (Bit32u) BX_XHCI_THIS hub.ring_members.event_rings[interrupter].rcs); // set the cycle bit -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_XHCI, USB_DEBUG_EVENT, interrupter, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_XHCI, USB_DEBUG_EVENT, interrupter, 0); #endif - + BX_DEBUG(("Write Event TRB: table index: %d, trb index: %d", BX_XHCI_THIS hub.ring_members.event_rings[interrupter].count, - BX_XHCI_THIS hub.ring_members.event_rings[interrupter].entrys[BX_XHCI_THIS hub.ring_members.event_rings[interrupter].count].size - + BX_XHCI_THIS hub.ring_members.event_rings[interrupter].entrys[BX_XHCI_THIS hub.ring_members.event_rings[interrupter].count].size - BX_XHCI_THIS hub.ring_members.event_rings[interrupter].trb_count)); BX_DEBUG(("Write Event TRB: address = 0x" FORMATADDRESS " 0x" FMT_ADDRX64 " 0x%08X 0x%08X (type = %d)", (bx_phy_address) BX_XHCI_THIS hub.ring_members.event_rings[interrupter].cur_trb, @@ -3316,7 +3334,7 @@ void bx_usb_xhci_c::copy_stream_to_buffer(Bit8u *buffer, const struct STREAM_CON // Validate a slot context // specs 1.0: sect 6.2.2.2 (p321): // specs 1.0: sect 6.2.2.3 (p321): -// "A 'valid' Input Slot Context for an Evaluate Context Command requires the Interrupter Target and +// "A 'valid' Input Slot Context for an Evaluate Context Command requires the Interrupter Target and // Max Exit Latency fields to be initialized." int bx_usb_xhci_c::validate_slot_context(const struct SLOT_CONTEXT *slot_context, int trb_command, int slot) { @@ -3324,14 +3342,14 @@ int bx_usb_xhci_c::validate_slot_context(const struct SLOT_CONTEXT *slot_context unsigned MaxIntrs; //int speed = -1; //int port_num = slot_context->rh_port_num - 1; - + //if ((port_num >= 0) && (BX_XHCI_THIS hub.usb_port[port_num].device != NULL)) { // speed = BX_XHCI_THIS hub.usb_port[port_num].device->get_speed(); //} else { // BX_ERROR(("Validate Slot Context: Invalid port_num (%d) sent.", port_num)); // return PARAMETER_ERROR; //} - + switch (trb_command) { case ADDRESS_DEVICE: case EVALUATE_CONTEXT: @@ -3339,23 +3357,23 @@ int bx_usb_xhci_c::validate_slot_context(const struct SLOT_CONTEXT *slot_context MaxIntrs = (BX_XHCI_THIS hub.cap_regs.HcSParams1 & (0x7FF << 8)) >> 8; if (slot_context->int_target > MaxIntrs) ret = PARAMETER_ERROR; - + // all high-speed and lower devices must have a Max Exit Latency value of zero // (this will fail because 'rh_port_num' hasn't been initialized yet, so 'speed' will be -1) //if ((slot_context->max_exit_latency > 0) && (speed < USB_SPEED_SUPER)) // ret = PARAMETER_ERROR; - + if (ret != TRB_SUCCESS) { - BX_ERROR(("Validate Slot Context: int_target = %d (0 -> %d), slot_context->max_exit_latency = %d", + BX_ERROR(("Validate Slot Context: int_target = %d (0 -> %d), slot_context->max_exit_latency = %d", slot_context->int_target, MaxIntrs, slot_context->max_exit_latency)); } break; - + case CONFIG_EP: // The config command needs to check the Context Entries field if (slot_context->entries < BX_XHCI_THIS hub.slots[slot].slot_context.entries) ret = PARAMETER_ERROR; - + // if 'hub' is 1 and device is a high-speed device, then the 'tt think time', 'multi-tt', // and 'number of ports' fields must be initialized. // (this will fail because 'rh_port_num' hasn't been initialized yet, so 'speed' will be -1) @@ -3368,9 +3386,9 @@ int bx_usb_xhci_c::validate_slot_context(const struct SLOT_CONTEXT *slot_context // ret = PARAMETER_ERROR; // } //} - + if (ret != TRB_SUCCESS) { - BX_ERROR(("Validate Slot Context: entry count = %d (%d), hub = %d", + BX_ERROR(("Validate Slot Context: entry count = %d (%d), hub = %d", slot_context->entries, BX_XHCI_THIS hub.slots[slot].slot_context.entries, slot_context->hub)); } @@ -3419,34 +3437,34 @@ int bx_usb_xhci_c::validate_ep_context(const struct EP_CONTEXT *ep_context, int // 1) the EP Type field = Control, if (ep_context->ep_type != 4) ret = PARAMETER_ERROR; - + // 2) the values of the Max Packet Size, Max Burst Size, and the Interval are considered // within range for endpoint type and the speed of the device, if (ep_context->max_packet_size != mps) ret = PARAMETER_ERROR; if (ep_context->interval > 15) // The legal range of 0 to 15 for all (non full/low-speed interrupt) endpoint types ret = PARAMETER_ERROR; - + // 3) the TR Dequeue Pointer field points to a valid Transfer Ring, if (ep_context->tr_dequeue_pointer == 0) ret = PARAMETER_ERROR; - + // 4) the DCS field = 1, if (ep_context->dcs != 1) ret = PARAMETER_ERROR; - + // 5) the MaxPStreams field = 0, and if (ep_context->max_pstreams != 0) ret = PARAMETER_ERROR; - + // 6) all other fields are within the valid range of values. - - // The Max Burst Size value shall be cleared to 0. + + // The Max Burst Size should be cleared to zero if (ep_context->max_burst_size != 0) ret = PARAMETER_ERROR; - + // xHCI version 1.0, section 4.6.5, pg 92, second primary dot item states: EP State value should be cleared to '0' - // xHCI version 1.1, section 4.6.5, pg 111, second to last 'Note' states it should be in the + // xHCI version 1.1, section 4.6.5, pg 111, second to last 'Note' states it should be in the // Stopped or Running State, either of these states not being equal to zero. #if ((VERSION_MAJOR < 1) || ((VERSION_MAJOR == 1) && (VERSION_MINOR < 1))) // if version is <= 1.0, the EP State value shall be cleared to 0. @@ -3464,7 +3482,7 @@ int bx_usb_xhci_c::validate_ep_context(const struct EP_CONTEXT *ep_context, int ret = PARAMETER_ERROR; } break; - + case CONFIG_EP: if ((ep_num > 1) && (a_flags & (1 << ep_num))) { // 1) the values of the Max Packet Size, Max Burst Size, and the Interval are considered within @@ -3472,7 +3490,7 @@ int bx_usb_xhci_c::validate_ep_context(const struct EP_CONTEXT *ep_context, int if (ep_context->max_packet_size > (unsigned) BX_XHCI_THIS hub.usb_port[port_num].device->get_mps(ep_num / 2)) ret = PARAMETER_ERROR; // The xhci specs are a little mis-leading. Section 6.2.3.2 states that the max_burst_size should - // be within range for the endpoint type and speed. However, section 6.2.3.4 states that the + // be within range for the endpoint type and speed. However, section 6.2.3.4 states that the // max_burst_size should match the same entry in the super-speed endpoint companion descriptor. // ( which section should we test for? I chose the former rather than the latter.) if (speed == USB_SPEED_SUPER) { @@ -3484,22 +3502,22 @@ int bx_usb_xhci_c::validate_ep_context(const struct EP_CONTEXT *ep_context, int } if (ep_context->interval > 15) // The legal range of 0 to 15 for all (non full/low-speed interrupt) endpoint types ret = PARAMETER_ERROR; - - // 2) if MaxPStreams > 0, then the TR Dequeue Pointer field points to an array of valid - // Stream Contexts, or if MaxPStreams = 0, then the TR Dequeue Pointer field points - // to a Transfer Ring, + + // 2) if MaxPStreams > 0, then the TR Dequeue Pointer field points to an array of valid + // Stream Contexts, or if MaxPStreams = 0, then the TR Dequeue Pointer field points + // to a Transfer Ring, if (ep_context->tr_dequeue_pointer == 0) ret = PARAMETER_ERROR; - + // 3) the EP State field = Disabled, and if (ep_context->ep_state != 0) ret = PARAMETER_ERROR; - + // 4) all other fields are within their valid range of values. - + } break; - + default: BX_ERROR(("Error: Unknown command on Evaluate Context: %d", trb_command)); } @@ -3549,7 +3567,7 @@ int bx_usb_xhci_c::send_set_address(int addr, int port_num, SLOT_CONTEXT& slot_c int bx_usb_xhci_c::broadcast_speed(SLOT_CONTEXT& slot_context) { int ret = -1; - + switch (slot_context.speed) { case 1: ret = USB_SPEED_FULL; @@ -3567,7 +3585,7 @@ int bx_usb_xhci_c::broadcast_speed(SLOT_CONTEXT& slot_context) default: BX_ERROR(("Invalid speed (%d) specified in Speed field of the Slot Context.", slot_context.speed)); } - + return ret; } @@ -3608,14 +3626,14 @@ void bx_usb_xhci_c::xhci_timer(void) if (BX_XHCI_THIS hub.op_regs.HcStatus.hch) return; -#if BX_USE_WIN32USBDEBUG - win32_usb_trigger(USB_DEBUG_XHCI, USB_DEBUG_FRAME, 0, 0); +#if BX_USB_DEBUGGER + SIM->usb_debug_trigger(USB_DEBUG_XHCI, USB_DEBUG_FRAME, 0, 0); #endif /* Per section 4.19.3 of the xHCI 1.0 specs, we need to present - * a "Port Status Change Event". - * Also, we should only present this event once if any other bits - * change, only presenting it again when all change bits are written + * a "Port Status Change Event". + * Also, we should only present this event once if any other bits + * change, only presenting it again when all change bits are written * back to zero, and a change bit goes from 0 to 1. */ for (unsigned port=0; portusb_debug_trigger(USB_DEBUG_XHCI, USB_DEBUG_ENABLE, 0, 0); #endif } } @@ -3849,7 +3867,7 @@ bool bx_usb_xhci_c::usb_param_enable_handler(bx_param_c *param, bool en) if (en && (BX_XHCI_THIS hub.usb_port[portnum].device != NULL)) { en = 0; } - + return en; } diff --git a/bochs/iodev/usb/usb_xhci.h b/bochs/iodev/usb/usb_xhci.h index a34bd78f0e..fd280fa802 100644 --- a/bochs/iodev/usb/usb_xhci.h +++ b/bochs/iodev/usb/usb_xhci.h @@ -3,7 +3,7 @@ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2010-2023 Benjamin D Lunt (fys [at] fysnet [dot] net) -// 2011-2023 The Bochs Project +// 2011-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -609,9 +609,7 @@ class bx_usb_xhci_c : public bx_pci_device_c { int event_handler(int event, void *ptr, int port); bx_usb_xhci_t hub; -#if !BX_USE_WIN32USBDEBUG private: -#endif Bit8u devfunc; Bit8u device_change; int rt_conf_id; diff --git a/bochs/iodev/utctime.h b/bochs/iodev/utctime.h index cf488e74be..8c16e95c32 100644 --- a/bochs/iodev/utctime.h +++ b/bochs/iodev/utctime.h @@ -2,7 +2,7 @@ // $Id: utctime.h ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2023 The Bochs Project +// Copyright (C) 2001-2024 The Bochs Project // // Portable gmtime()/timegm() clones by Michele Giacomone // @@ -107,7 +107,11 @@ char *ascutc(struct utctm *src) struct utctm *utctime_ext(const Bit64s *a,struct utctm *trgt) { - static const Bit32s monthlydays[2][13]={{0,31,59,90,120,151,181,212,243,273,304,334,365},{0,31,60,91,121,152,182,213,244,274,305,335,366}}; //Days elapsed between the start of the selected month and the start of the year + //Days elapsed between the start of the selected month and the start of the year + static const Bit32s monthlydays[2][13]={ + {0,31,59,90,120,151,181,212,243,273,304,334,365}, + {0,31,60,91,121,152,182,213,244,274,305,335,366} + }; Bit8u isleap=0; //Leap year flag struct utctm bdt; //Structure to temporary store the output Bit64s etmp=*a; //Temporary variable, epoch since 1970 @@ -123,7 +127,7 @@ struct utctm *utctime_ext(const Bit64s *a,struct utctm *trgt) tsec/=60; bdt.tm_min=tsec%60; //Set the minutes value tsec/=60; - bdt.tm_hour=tsec; //Set the hour value + bdt.tm_hour = (Bit16s)tsec; //Set the hour value bdt.tm_wday=(etmp-6)%7; if(bdt.tm_wday<0) bdt.tm_wday+=7; //Set the day of the week value @@ -144,13 +148,13 @@ struct utctm *utctime_ext(const Bit64s *a,struct utctm *trgt) isleap=(isleap?1:0); //Find out if the year is leap eyear-=1900; - bdt.tm_year=eyear; //Set the year value + bdt.tm_year = (Bit16s)eyear; //Set the year value - bdt.tm_yday=etmp; //Set the day of the year value + bdt.tm_yday = (Bit16s)etmp; //Set the day of the year value bdt.tm_mon=0; while(etmp>=monthlydays[isleap][bdt.tm_mon+1]) bdt.tm_mon++; //Set the month value etmp-=monthlydays[isleap][bdt.tm_mon]; - bdt.tm_mday=etmp+1; //Set the day of the month value + bdt.tm_mday = (Bit16s)(etmp + 1); //Set the day of the month value if(eyear != bdt.tm_year) return NULL; //If the calculated year is too high fail @@ -167,7 +171,11 @@ struct utctm *utctime_ext(const Bit64s *a,struct utctm *trgt) Bit64s timeutc(struct utctm *bdt) { - static const Bit32s monthlydays[2][13]={{0,31,59,90,120,151,181,212,243,273,304,334,365},{0,31,60,91,121,152,182,213,244,274,305,335,366}}; //Days elapsed between the start of the selected month and the start of the year + //Days elapsed between the start of the selected month and the start of the year + static const Bit32s monthlydays[2][13]={ + {0,31,59,90,120,151,181,212,243,273,304,334,365}, + {0,31,60,91,121,152,182,213,244,274,305,335,366} + }; Bit8u isleap=3; //Leap year flag Bit32s tmon; //Temporary month value Bit64s epoch=0; //Value to return diff --git a/bochs/ltdl-bochs.h b/bochs/ltdl-bochs.h deleted file mode 100644 index fda92e7faa..0000000000 --- a/bochs/ltdl-bochs.h +++ /dev/null @@ -1,398 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -// -// NOTE: The ltdl library comes from the Libtool package. Bochs uses -// ltdl and libtool to build and load plugins. The libtool -// documentation describes how to copy ltdl.c and ltdl.h into your -// distribution, so it is clearly legal to do so. -///////////////////////////////////////////////////////////////////////// - -/* ltdl.h -- generic dlopen functions - Copyright (C) 1998-2000 Free Software Foundation, Inc. - Originally by Thomas Tanner - This file is part of GNU Libtool. - -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. - -As a special exception to the GNU Lesser General Public License, -if you distribute this file as part of a program or library that -is built using GNU libtool, you may include it under the same -distribution terms that you use for the rest of that program. - -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., 51 Franklin St, Fifth Floor, Boston, MA -02110-1301 USA -*/ - -/* Only include this header file once. */ -#ifndef LTDL_H -#define LTDL_H 1 - -#ifdef __cplusplus -extern "C" { -#endif -#include /* for size_t declaration */ -#ifdef __cplusplus -}; -#endif - - -/* --- MACROS FOR PORTABILITY --- */ - - -/* Saves on those hard to debug '\0' typos.... */ -#define LT_EOS_CHAR '\0' - -/* LTDL_BEGIN_C_DECLS should be used at the beginning of your declarations, - so that C++ compilers don't mangle their names. Use LTDL_END_C_DECLS at - the end of C declarations. */ -#ifdef __cplusplus -# define LT_BEGIN_C_DECLS extern "C" { -# define LT_END_C_DECLS } -#else -# define LT_BEGIN_C_DECLS /* empty */ -# define LT_END_C_DECLS /* empty */ -#endif - -LT_BEGIN_C_DECLS - - -/* LT_PARAMS is a macro used to wrap function prototypes, so that compilers - that don't understand ANSI C prototypes still work, and ANSI C - compilers can issue warnings about type mismatches. */ -#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus) -# define LT_PARAMS(protos) protos -# define lt_ptr void* -#else -# define LT_PARAMS(protos) () -# define lt_ptr char* -#endif - -/* LT_STMT_START/END are used to create macros which expand to a - a single compound statement in a portable way. */ -#if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) -# define LT_STMT_START (void)( -# define LT_STMT_END ) -#else -# if (defined (sun) || defined (__sun__)) -# define LT_STMT_START if (1) -# define LT_STMT_END else (void)0 -# else -# define LT_STMT_START do -# define LT_STMT_END while (0) -# endif -#endif - -/* LT_CONC creates a new concatenated symbol for the compiler - in a portable way. */ -#if defined(__STDC__) || defined(__cplusplus) -# define LT_CONC(s,t) s##t -#else -# define LT_CONC(s,t) s/**/t -#endif - -/* LT_STRLEN can be used safely on NULL pointers. */ -#define LT_STRLEN(s) (((s) && (s)[0]) ? strlen (s) : 0) - - - -/* --- WINDOWS SUPPORT --- */ - - -/* Canonicalise Windows and Cygwin recognition macros. */ -#ifdef __CYGWIN32__ -# ifndef __CYGWIN__ -# define __CYGWIN__ __CYGWIN32__ -# endif -#endif -#if defined(_WIN32) || defined(WIN32) -# ifndef __WINDOWS__ -# ifdef _WIN32 -# define __WINDOWS__ _WIN32 -# else -# ifdef WIN32 -# define __WINDOWS__ WIN32 -# endif -# endif -# endif -#endif - -#ifdef __WINDOWS__ -# ifndef __CYGWIN__ -/* LT_DIRSEP_CHAR is accepted *in addition* to '/' as a directory - separator when it is set. */ -# define LT_DIRSEP_CHAR '\\' -# define LT_PATHSEP_CHAR ';' -# endif -#endif -#ifndef LT_PATHSEP_CHAR -# define LT_PATHSEP_CHAR ':' -#endif - -/* DLL building support on win32 hosts; mostly to workaround their - ridiculous implementation of data symbol exporting. */ -#ifndef LT_SCOPE -# ifdef __WINDOWS__ -# ifdef DLL_EXPORT /* defined by libtool (if required) */ -# define LT_SCOPE __declspec(dllexport) -# endif -# ifdef LIBLTDL_DLL_IMPORT /* define if linking with this dll */ -# define LT_SCOPE extern __declspec(dllimport) -# endif -# endif -# ifndef LT_SCOPE /* static linking or !__WINDOWS__ */ -# define LT_SCOPE extern -# endif -#endif - - - - -/* --- DYNAMIC MODULE LOADING API --- */ - - -typedef struct lt_dlhandle_struct *lt_dlhandle; /* A loaded module. */ - -/* Initialisation and finalisation functions for libltdl. */ -extern int lt_dlinit LT_PARAMS((void)); -extern int lt_dlexit LT_PARAMS((void)); - -/* Module search path manipulation. */ -extern int lt_dladdsearchdir LT_PARAMS((const char *search_dir)); -extern int lt_dlinsertsearchdir LT_PARAMS((const char *before, - const char *search_dir)); -extern int lt_dlsetsearchpath LT_PARAMS((const char *search_path)); -extern const char *lt_dlgetsearchpath LT_PARAMS((void)); -extern int lt_dlforeachfile LT_PARAMS(( - const char *search_path, - int (*func) (const char *filename, lt_ptr data), - lt_ptr data)); - -/* Portable libltdl versions of the system dlopen() API. */ -extern lt_dlhandle lt_dlopen LT_PARAMS((const char *filename)); -extern lt_dlhandle lt_dlopenext LT_PARAMS((const char *filename)); -extern lt_ptr lt_dlsym LT_PARAMS((lt_dlhandle handle, - const char *name)); -extern const char *lt_dlerror LT_PARAMS((void)); -extern int lt_dlclose LT_PARAMS((lt_dlhandle handle)); - -/* Module residency management. */ -extern int lt_dlmakeresident LT_PARAMS((lt_dlhandle handle)); -extern int lt_dlisresident LT_PARAMS((lt_dlhandle handle)); - - - - -/* --- MUTEX LOCKING --- */ - - -typedef void lt_dlmutex_lock LT_PARAMS((void)); -typedef void lt_dlmutex_unlock LT_PARAMS((void)); -typedef void lt_dlmutex_seterror LT_PARAMS((const char *errmsg)); -typedef const char *lt_dlmutex_geterror LT_PARAMS((void)); - -extern int lt_dlmutex_register LT_PARAMS((lt_dlmutex_lock *lock, - lt_dlmutex_unlock *unlock, - lt_dlmutex_seterror *seterror, - lt_dlmutex_geterror *geterror)); - - - - -/* --- MEMORY HANDLING --- */ - - -/* By default, the realloc function pointer is set to our internal - realloc implementation which iself uses lt_dlmalloc and lt_dlfree. - libltdl relies on a featureful realloc, but if you are sure yours - has the right semantics then you can assign it directly. Generally, - it is safe to assign just a malloc() and a free() function. */ -LT_SCOPE lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)); -LT_SCOPE lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)); -LT_SCOPE void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)); - - - - -/* --- PRELOADED MODULE SUPPORT --- */ - - -/* A preopened symbol. Arrays of this type comprise the exported - symbols for a dlpreopened module. */ -typedef struct { - const char *name; - lt_ptr address; -} lt_dlsymlist; - -extern int lt_dlpreload LT_PARAMS((const lt_dlsymlist *preloaded)); -extern int lt_dlpreload_default - LT_PARAMS((const lt_dlsymlist *preloaded)); - -#define LTDL_SET_PRELOADED_SYMBOLS() LT_STMT_START{ \ - extern const lt_dlsymlist lt_preloaded_symbols[]; \ - lt_dlpreload_default(lt_preloaded_symbols); \ - }LT_STMT_END - - - - -/* --- MODULE INFORMATION --- */ - - -/* Read only information pertaining to a loaded module. */ -typedef struct { - char *filename; /* file name */ - char *name; /* module name */ - int ref_count; /* number of times lt_dlopened minus - number of times lt_dlclosed. */ -} lt_dlinfo; - -extern const lt_dlinfo *lt_dlgetinfo LT_PARAMS((lt_dlhandle handle)); -extern lt_dlhandle lt_dlhandle_next LT_PARAMS((lt_dlhandle place)); -extern int lt_dlforeach LT_PARAMS(( - int (*func) (lt_dlhandle handle, lt_ptr data), - lt_ptr data)); - -/* Associating user data with loaded modules. */ -typedef unsigned lt_dlcaller_id; - -extern lt_dlcaller_id lt_dlcaller_register LT_PARAMS((void)); -extern lt_ptr lt_dlcaller_set_data LT_PARAMS((lt_dlcaller_id key, - lt_dlhandle handle, - lt_ptr data)); -extern lt_ptr lt_dlcaller_get_data LT_PARAMS((lt_dlcaller_id key, - lt_dlhandle handle)); - - - -/* --- USER MODULE LOADER API --- */ - - -typedef struct lt_dlloader lt_dlloader; -typedef lt_ptr lt_user_data; -typedef lt_ptr lt_module; - -/* Function pointer types for creating user defined module loaders. */ -typedef lt_module lt_module_open LT_PARAMS((lt_user_data loader_data, - const char *filename)); -typedef int lt_module_close LT_PARAMS((lt_user_data loader_data, - lt_module handle)); -typedef lt_ptr lt_find_sym LT_PARAMS((lt_user_data loader_data, - lt_module handle, - const char *symbol)); -typedef int lt_dlloader_exit LT_PARAMS((lt_user_data loader_data)); - -struct lt_user_dlloader { - const char *sym_prefix; - lt_module_open *module_open; - lt_module_close *module_close; - lt_find_sym *find_sym; - lt_dlloader_exit *dlloader_exit; - lt_user_data dlloader_data; -}; - -extern lt_dlloader *lt_dlloader_next LT_PARAMS((lt_dlloader *place)); -extern lt_dlloader *lt_dlloader_find LT_PARAMS(( - const char *loader_name)); -extern const char *lt_dlloader_name LT_PARAMS((lt_dlloader *place)); -extern lt_user_data *lt_dlloader_data LT_PARAMS((lt_dlloader *place)); -extern int lt_dlloader_add LT_PARAMS((lt_dlloader *place, - const struct lt_user_dlloader *dlloader, - const char *loader_name)); -extern int lt_dlloader_remove LT_PARAMS(( - const char *loader_name)); - - - -/* --- ERROR MESSAGE HANDLING --- */ - -/* Bryce rewrote the error table in a way that would be likely to work - on all compilers. VC++ was not able to handle it the way it was - done originally. */ - -/* ORIG COMMENT: Defining error strings alongside their symbolic names in a - macro in this way allows us to expand the macro in different contexts with - confidence that the enumeration of symbolic names will map correctly - onto the table of error strings. */ - -#define lt_dlerror_symbols_list \ - LT_ERROR_UNKNOWN, \ - LT_ERROR_DLOPEN_NOT_SUPPORTED, \ - LT_ERROR_INVALID_LOADER, \ - LT_ERROR_INIT_LOADER, \ - LT_ERROR_REMOVE_LOADER, \ - LT_ERROR_FILE_NOT_FOUND, \ - LT_ERROR_DEPLIB_NOT_FOUND, \ - LT_ERROR_NO_SYMBOLS, \ - LT_ERROR_CANNOT_OPEN, \ - LT_ERROR_CANNOT_CLOSE, \ - LT_ERROR_SYMBOL_NOT_FOUND, \ - LT_ERROR_NO_MEMORY, \ - LT_ERROR_INVALID_HANDLE, \ - LT_ERROR_BUFFER_OVERFLOW, \ - LT_ERROR_INVALID_ERRORCODE, \ - LT_ERROR_SHUTDOWN, \ - LT_ERROR_CLOSE_RESIDENT_MODULE, \ - LT_ERROR_INVALID_MUTEX_ARGS, \ - LT_ERROR_INVALID_POSITION, - -#define lt_dlerror_names_list \ - "unknown error", \ - "dlopen support not available", \ - "invalid loader", \ - "loader initialization failed", \ - "loader removal failed", \ - "file not found", \ - "dependency library not found", \ - "no symbols defined", \ - "can't open the module", \ - "can't close the module", \ - "symbol not found", \ - "not enough memory", \ - "invalid module handle", \ - "internal buffer overflow", \ - "invalid errorcode", \ - "library already shutdown", \ - "can't close resident module", \ - "invalid mutex handler registration", \ - "invalid search path insert position", - -/* Enumerate the symbolic error names. */ -enum { - lt_dlerror_symbols_list - LT_ERROR_MAX -}; - -/* These functions are only useful from inside custom module loaders. */ -extern int lt_dladderror LT_PARAMS((const char *diagnostic)); -extern int lt_dlseterror LT_PARAMS((int errorcode)); - - - - -/* --- SOURCE COMPATIBILITY WITH OLD LIBLTDL --- */ - - -#ifdef LT_NON_POSIX_NAMESPACE -# define lt_ptr_t lt_ptr -# define lt_module_t lt_module -# define lt_module_open_t lt_module_open -# define lt_module_close_t lt_module_close -# define lt_find_sym_t lt_find_sym -# define lt_dlloader_exit_t lt_dlloader_exit -# define lt_dlloader_t lt_dlloader -# define lt_dlloader_data_t lt_user_data -#endif - -LT_END_C_DECLS - -#endif /* !LTDL_H */ diff --git a/bochs/ltdl.c b/bochs/ltdl.c deleted file mode 100644 index 22ba8302a4..0000000000 --- a/bochs/ltdl.c +++ /dev/null @@ -1,4067 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id$ -// -// NOTE: The ltdl library comes from the Libtool package. Bochs uses -// ltdl and libtool to build and load plugins. The libtool -// documentation describes how to copy ltdl.c and ltdl.h into your -// distribution, so it is clearly legal to do so. -///////////////////////////////////////////////////////////////////////// - -/* ltdl.c -- system independent dlopen wrapper - Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. - Originally by Thomas Tanner - This file is part of GNU Libtool. - -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. - -As a special exception to the GNU Lesser General Public License, -if you distribute this file as part of a program or library that -is built using GNU libtool, you may include it under the same -distribution terms that you use for the rest of that program. - -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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -// ltdlconf.h added for Bochs -#include "ltdlconf.h" - -#if HAVE_CONFIG_H -# include -#endif - -#if HAVE_UNISTD_H -# include -#endif - -#if HAVE_STDIO_H -# include -#endif - -#if HAVE_STDLIB_H -# include -#endif - -#if HAVE_STRING_H -# include -#else -# if HAVE_STRINGS_H -# include -# endif -#endif - -#if HAVE_CTYPE_H -# include -#endif - -#if HAVE_MALLOC_H -# include -#endif - -#if HAVE_MEMORY_H -# include -#endif - -#if HAVE_ERRNO_H -# include -#endif - -#if HAVE_DIRENT_H -# include -# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) -#else -# define dirent direct -# define LT_D_NAMLEN(dirent) ((dirent)->d_namlen) -# if HAVE_SYS_NDIR_H -# include -# endif -# if HAVE_SYS_DIR_H -# include -# endif -# if HAVE_NDIR_H -# include -# endif -#endif - -#if HAVE_ARGZ_H -# include -#endif - -#if HAVE_ASSERT_H -# include -#else -# ifdef __GNUC__ -# warning using my own assert -# endif -# define assert(cond) while (!(cond)) { fprintf (stderr, "Assert failed at %s:%d: '%s'\n", __FILE__, __LINE__, #cond); abort(); } -#endif - -#define LTDEBUG_PRINTF(x) /* debug output disabled */ -//#define LTDEBUG_PRINTF(x) do{ printf("LT_DEBUG: "); printf x; } while (0) - -#include "ltdl-bochs.h" - - - - -/* --- WINDOWS SUPPORT --- */ - - -#ifdef DLL_EXPORT -# define LT_GLOBAL_DATA __declspec(dllexport) -#else -# define LT_GLOBAL_DATA -#endif - -/* fopen() mode flags for reading a text file */ -#undef LT_READTEXT_MODE -#ifdef __WINDOWS__ -# define LT_READTEXT_MODE "rt" -#else -# define LT_READTEXT_MODE "r" -#endif - - - - -/* --- MANIFEST CONSTANTS --- */ - - -/* Standard libltdl search path environment variable name */ -#undef LTDL_SEARCHPATH_VAR -#define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH" - -/* Standard libtool archive file extension. */ -#undef LTDL_ARCHIVE_EXT -#define LTDL_ARCHIVE_EXT ".la" - -/* max. filename length */ -#ifndef LT_FILENAME_MAX -# define LT_FILENAME_MAX 1024 -#endif - -/* This is the maximum symbol size that won't require malloc/free */ -#undef LT_SYMBOL_LENGTH -#define LT_SYMBOL_LENGTH 128 - -/* This accounts for the _LTX_ separator */ -#undef LT_SYMBOL_OVERHEAD -#define LT_SYMBOL_OVERHEAD 5 - - - - -/* --- MEMORY HANDLING --- */ - - -/* These are the functions used internally. In addition to making - use of the associated function pointers above, they also perform - error handling. */ -static char *lt_estrdup LT_PARAMS((const char *str)); -static lt_ptr lt_emalloc LT_PARAMS((size_t size)); -static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size)); - -static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); - -/* These are the pointers that can be changed by the caller: */ -LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)) - = (lt_ptr (*) LT_PARAMS((size_t))) malloc; -LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)) - = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc; -LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)) - = (void (*) LT_PARAMS((lt_ptr))) free; - -/* The following macros reduce the amount of typing needed to cast - assigned memory. */ -#define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp))) -#define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp))) -#define LT_DLFREE(p) \ - LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END - -#define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp))) -#define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp))) - -#define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \ - if ((p) != (q)) { lt_dlfree (p); (p) = (q); (q) = 0; } \ - } LT_STMT_END - - -/* --- REPLACEMENT FUNCTIONS --- */ - - -#undef strdup -#define strdup rpl_strdup - -static char *strdup LT_PARAMS((const char *str)); - -char * -strdup(str) - const char *str; -{ - char *tmp = 0; - - if (str) - { - tmp = LT_DLMALLOC (char, 1+ strlen (str)); - if (tmp) - { - strcpy(tmp, str); - } - } - - return tmp; -} - - -#if ! HAVE_STRCMP - -#undef strcmp -#define strcmp rpl_strcmp - -static int strcmp LT_PARAMS((const char *str1, const char *str2)); - -int -strcmp (str1, str2) - const char *str1; - const char *str2; -{ - if (str1 == str2) - return 0; - if (str1 == 0) - return -1; - if (str2 == 0) - return 1; - - for (;*str1 && *str2; ++str1, ++str2) - { - if (*str1 != *str2) - break; - } - - return (int)(*str1 - *str2); -} -#endif - - -#if ! HAVE_STRCHR - -# if HAVE_INDEX -# define strchr index -# else -# define strchr rpl_strchr - -static const char *strchr LT_PARAMS((const char *str, int ch)); - -const char* -strchr(str, ch) - const char *str; - int ch; -{ - const char *p; - - for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p) - /*NOWORK*/; - - return (*p == (char)ch) ? p : 0; -} - -# endif -#endif /* !HAVE_STRCHR */ - - -#if ! HAVE_STRRCHR - -# if HAVE_RINDEX -# define strrchr rindex -# else -# define strrchr rpl_strrchr - -static const char *strrchr LT_PARAMS((const char *str, int ch)); - -const char* -strrchr(str, ch) - const char *str; - int ch; -{ - const char *p, *q = 0; - - for (p = str; *p != LT_EOS_CHAR; ++p) - { - if (*p == (char) ch) - { - q = p; - } - } - - return q; -} - -# endif -#endif - -/* NOTE: Neither bcopy nor the memcpy implementation below can - reliably handle copying in overlapping areas of memory. Use - memmove (for which there is a fallback implmentation below) - if you need that behaviour. */ -#if ! HAVE_MEMCPY - -# if HAVE_BCOPY -# define memcpy(dest, src, size) bcopy (src, dest, size) -# else -# define memcpy rpl_memcpy - -static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); - -lt_ptr -memcpy (dest, src, size) - lt_ptr dest; - const lt_ptr src; - size_t size; -{ - size_t i = 0; - - for (i = 0; i < size; ++i) - { - dest[i] = src[i]; - } - - return dest; -} - -# endif /* !HAVE_BCOPY */ -#endif /* !HAVE_MEMCPY */ - -#if ! HAVE_MEMMOVE -# define memmove rpl_memmove - -static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); - -lt_ptr -memmove (dest, src, size) - lt_ptr dest; - const lt_ptr src; - size_t size; -{ - size_t i; - - if (dest < src) - for (i = 0; i < size; ++i) - { - dest[i] = src[i]; - } - else if (dest > src) - for (i = size -1; i < size; --i) - { - dest[i] = src[i]; - } - - return dest; -} - -#endif /* !HAVE_MEMMOVE */ - - -/* According to Alexandre Oliva , - ``realloc is not entirely portable'' - In any case we want to use the allocator supplied by the user without - burdening them with an lt_dlrealloc function pointer to maintain. - Instead implement our own version (with known boundary conditions) - using lt_dlmalloc and lt_dlfree. */ - -#undef realloc -#define realloc rpl_realloc - -lt_ptr -realloc (ptr, size) - lt_ptr ptr; - size_t size; -{ - if (size <= 0) - { - /* For zero or less bytes, free the original memory */ - if (ptr != 0) - { - lt_dlfree (ptr); - } - - return (lt_ptr) 0; - } - else if (ptr == 0) - { - /* Allow reallocation of a NULL pointer. */ - return lt_dlmalloc (size); - } - else - { - /* Allocate a new block, copy and free the old block. */ - lt_ptr mem = lt_dlmalloc (size); - - if (mem) - { - memcpy (mem, ptr, size); - lt_dlfree (ptr); - } - - /* Note that the contents of PTR are not damaged if there is - insufficient memory to realloc. */ - return mem; - } -} - - -#if ! HAVE_ARGZ_APPEND -# define argz_append rpl_argz_append - -static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len, - const char *buf, size_t buf_len)); - -error_t -argz_append (pargz, pargz_len, buf, buf_len) - char **pargz; - size_t *pargz_len; - const char *buf; - size_t buf_len; -{ - size_t argz_len; - char *argz; - - assert (pargz); - assert (pargz_len); - assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len)); - - /* If nothing needs to be appended, no more work is required. */ - if (buf_len == 0) - return 0; - - /* Ensure there is enough room to append BUF_LEN. */ - argz_len = *pargz_len + buf_len; - argz = LT_DLREALLOC (char, *pargz, argz_len); - if (!argz) - return ENOMEM; - - /* Copy characters from BUF after terminating '\0' in ARGZ. */ - memcpy (argz + *pargz_len, buf, buf_len); - - /* Assign new values. */ - *pargz = argz; - *pargz_len = argz_len; - - return 0; -} -#endif /* !HAVE_ARGZ_APPEND */ - - -#if ! HAVE_ARGZ_CREATE_SEP -# define argz_create_sep rpl_argz_create_sep - -static error_t argz_create_sep LT_PARAMS((const char *str, int delim, - char **pargz, size_t *pargz_len)); - -error_t -argz_create_sep (str, delim, pargz, pargz_len) - const char *str; - int delim; - char **pargz; - size_t *pargz_len; -{ - size_t argz_len; - char *argz = 0; - - assert (str); - assert (pargz); - assert (pargz_len); - - /* Make a copy of STR, but replacing each occurence of - DELIM with '\0'. */ - argz_len = 1+ LT_STRLEN (str); - if (argz_len) - { - const char *p; - char *q; - - argz = LT_DLMALLOC (char, argz_len); - if (!argz) - return ENOMEM; - - for (p = str, q = argz; *p != LT_EOS_CHAR; ++p) - { - if (*p == delim) - { - /* Ignore leading delimiters, and fold consecutive - delimiters in STR into a single '\0' in ARGZ. */ - if ((q > argz) && (q[-1] != LT_EOS_CHAR)) - *q++ = LT_EOS_CHAR; - else - --argz_len; - } - else - *q++ = *p; - } - /* Copy terminating LT_EOS_CHAR. */ - *q = *p; - } - - /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */ - if (!argz_len) - LT_DLFREE (argz); - - /* Assign new values. */ - *pargz = argz; - *pargz_len = argz_len; - - return 0; -} -#endif /* !HAVE_ARGZ_CREATE_SEP */ - - -#if ! HAVE_ARGZ_INSERT -# define argz_insert rpl_argz_insert - -static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len, - char *before, const char *entry)); - -error_t -argz_insert (pargz, pargz_len, before, entry) - char **pargz; - size_t *pargz_len; - char *before; - const char *entry; -{ - assert (pargz); - assert (pargz_len); - assert (entry && *entry); - - /* Either PARGZ/PARGZ_LEN is empty and BEFORE is NULL, - or BEFORE points into an address within the ARGZ vector. */ - assert ((!*pargz && !*pargz_len && !before) - || ((*pargz <= before) && (before < (*pargz + *pargz_len)))); - - /* No BEFORE address indicates ENTRY should be inserted after the - current last element. */ - if (!before) - return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry)); - - /* This probably indicates a programmer error, but to preserve - semantics, scan back to the start of an entry if BEFORE points - into the middle of it. */ - while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR)) - --before; - - { - size_t entry_len = 1+ LT_STRLEN (entry); - size_t argz_len = *pargz_len + entry_len; - size_t offset = before - *pargz; - char *argz = LT_DLREALLOC (char, *pargz, argz_len); - - if (!argz) - return ENOMEM; - - /* Make BEFORE point to the equivalent offset in ARGZ that it - used to have in *PARGZ incase realloc() moved the block. */ - before = argz + offset; - - /* Move the ARGZ entries starting at BEFORE up into the new - space at the end -- making room to copy ENTRY into the - resulting gap. */ - memmove (before + entry_len, before, *pargz_len - offset); - memcpy (before, entry, entry_len); - - /* Assign new values. */ - *pargz = argz; - *pargz_len = argz_len; - } - - return 0; -} -#endif /* !HAVE_ARGZ_INSERT */ - - -#if ! HAVE_ARGZ_NEXT -# define argz_next rpl_argz_next - -static char *argz_next LT_PARAMS((char *argz, size_t argz_len, - const char *entry)); - -char * -argz_next (argz, argz_len, entry) - char *argz; - size_t argz_len; - const char *entry; -{ - assert ((argz && argz_len) || (!argz && !argz_len)); - - if (entry) - { - /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address - within the ARGZ vector. */ - assert ((!argz && !argz_len) - || ((argz <= entry) && (entry < (argz + argz_len)))); - - /* Move to the char immediately after the terminating - '\0' of ENTRY. */ - entry = 1+ strchr (entry, LT_EOS_CHAR); - - /* Return either the new ENTRY, or else NULL if ARGZ is - exhausted. */ - return (entry >= argz + argz_len) ? 0 : (char *) entry; - } - else - { - /* This should probably be flagged as a programmer error, - since starting an argz_next loop with the iterator set - to ARGZ is safer. To preserve semantics, handle the NULL - case by returning the start of ARGZ (if any). */ - if (argz_len > 0) - return argz; - else - return 0; - } -} -#endif /* !HAVE_ARGZ_NEXT */ - - - -#if ! HAVE_ARGZ_STRINGIFY -# define argz_stringify rpl_argz_stringify - -static void argz_stringify LT_PARAMS((char *argz, size_t argz_len, - int sep)); - -void -argz_stringify (argz, argz_len, sep) - char *argz; - size_t argz_len; - int sep; -{ - assert ((argz && argz_len) || (!argz && !argz_len)); - - if (sep) - { - --argz_len; /* don't stringify the terminating EOS */ - while (--argz_len > 0) - { - if (argz[argz_len] == LT_EOS_CHAR) - argz[argz_len] = sep; - } - } -} -#endif /* !HAVE_ARGZ_STRINGIFY */ - - - - -/* --- TYPE DEFINITIONS -- */ - - -/* This type is used for the array of caller data sets in each handler. */ -typedef struct { - lt_dlcaller_id key; - lt_ptr data; -} lt_caller_data; - - - - -/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */ - - -/* Extract the diagnostic strings from the error table macro in the same - order as the enumerated indices in ltdl.h. */ - -static const char *lt_dlerror_strings[] = - { - lt_dlerror_names_list - 0 - }; - -/* This structure is used for the list of registered loaders. */ -struct lt_dlloader { - struct lt_dlloader *next; - const char *loader_name; /* identifying name for each loader */ - const char *sym_prefix; /* prefix for symbols */ - lt_module_open *module_open; - lt_module_close *module_close; - lt_find_sym *find_sym; - lt_dlloader_exit *dlloader_exit; - lt_user_data dlloader_data; -}; - -struct lt_dlhandle_struct { - struct lt_dlhandle_struct *next; - lt_dlloader *loader; /* dlopening interface */ - lt_dlinfo info; - int depcount; /* number of dependencies */ - lt_dlhandle *deplibs; /* dependencies */ - lt_module module; /* system module handle */ - lt_ptr system; /* system specific data */ - lt_caller_data *caller_data; /* per caller associated data */ - int flags; /* various boolean stats */ -}; - -/* Various boolean flags can be stored in the flags field of an - lt_dlhandle_struct... */ -#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag)) -#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag)) - -#define LT_DLRESIDENT_FLAG (0x01 << 0) -/* ...add more flags here... */ - -#define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG) - - -#define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)] - -static const char objdir[] = LTDL_OBJDIR; -static const char archive_ext[] = LTDL_ARCHIVE_EXT; -#ifdef LTDL_SHLIB_EXT -static const char shlib_ext[] = LTDL_SHLIB_EXT; -#endif -#ifdef LTDL_SYSSEARCHPATH -static const char sys_search_path[] = LTDL_SYSSEARCHPATH; -#endif - - - - -/* --- MUTEX LOCKING --- */ - - -/* Macros to make it easier to run the lock functions only if they have - been registered. The reason for the complicated lock macro is to - ensure that the stored error message from the last error is not - accidentally erased if the current function doesn't generate an - error of its own. */ -#define LT_DLMUTEX_LOCK() LT_STMT_START { \ - if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \ - } LT_STMT_END -#define LT_DLMUTEX_UNLOCK() LT_STMT_START { \ - if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\ - } LT_STMT_END -#define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \ - if (lt_dlmutex_seterror_func) \ - (*lt_dlmutex_seterror_func) (errormsg); \ - else lt_dllast_error = (errormsg); } LT_STMT_END -#define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \ - if (lt_dlmutex_seterror_func) \ - (errormsg) = (*lt_dlmutex_geterror_func) (); \ - else (errormsg) = lt_dllast_error; } LT_STMT_END - -/* The mutex functions stored here are global, and are necessarily the - same for all threads that wish to share access to libltdl. */ -static lt_dlmutex_lock *lt_dlmutex_lock_func = 0; -static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0; -static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0; -static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0; -static const char *lt_dllast_error = 0; - - -/* Either set or reset the mutex functions. Either all the arguments must - be valid functions, or else all can be NULL to turn off locking entirely. - The registered functions should be manipulating a static global lock - from the lock() and unlock() callbacks, which needs to be reentrant. */ -int -lt_dlmutex_register (lock, unlock, seterror, geterror) - lt_dlmutex_lock *lock; - lt_dlmutex_unlock *unlock; - lt_dlmutex_seterror *seterror; - lt_dlmutex_geterror *geterror; -{ - lt_dlmutex_unlock *old_unlock = unlock; - int errors = 0; - - /* Lock using the old lock() callback, if any. */ - LT_DLMUTEX_LOCK (); - - if ((lock && unlock && seterror && geterror) - || !(lock || unlock || seterror || geterror)) - { - lt_dlmutex_lock_func = lock; - lt_dlmutex_unlock_func = unlock; - lt_dlmutex_geterror_func = geterror; - } - else - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS)); - ++errors; - } - - /* Use the old unlock() callback we saved earlier, if any. Otherwise - record any errors using internal storage. */ - if (old_unlock) - (*old_unlock) (); - - /* Return the number of errors encountered during the execution of - this function. */ - return errors; -} - - - - -/* --- ERROR HANDLING --- */ - - -static const char **user_error_strings = 0; -static int errorcount = LT_ERROR_MAX; - -int -lt_dladderror (diagnostic) - const char *diagnostic; -{ - int errindex = 0; - int result = -1; - const char **temp = (const char **) 0; - - assert (diagnostic); - - LT_DLMUTEX_LOCK (); - - errindex = errorcount - LT_ERROR_MAX; - temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex); - if (temp) - { - user_error_strings = temp; - user_error_strings[errindex] = diagnostic; - result = errorcount++; - } - - LT_DLMUTEX_UNLOCK (); - - return result; -} - -int -lt_dlseterror (errindex) - int errindex; -{ - int errors = 0; - - LT_DLMUTEX_LOCK (); - - if (errindex >= errorcount || errindex < 0) - { - /* Ack! Error setting the error message! */ - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE)); - ++errors; - } - else if (errindex < LT_ERROR_MAX) - { - /* No error setting the error message! */ - LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]); - } - else - { - /* No error setting the error message! */ - LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]); - } - - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -lt_ptr -lt_emalloc (size) - size_t size; -{ - lt_ptr mem = lt_dlmalloc (size); - if (size && !mem) - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); - return mem; -} - -lt_ptr -lt_erealloc (addr, size) - lt_ptr addr; - size_t size; -{ - lt_ptr mem = realloc (addr, size); - if (size && !mem) - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); - return mem; -} - -char * -lt_estrdup (str) - const char *str; -{ - char *dup = strdup (str); - if (LT_STRLEN (str) && !dup) - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); - return dup; -} - - - - -/* --- DLOPEN() INTERFACE LOADER --- */ - - -/* The Cygwin dlopen implementation prints a spurious error message to - stderr if its call to LoadLibrary() fails for any reason. We can - mitigate this by not using the Cygwin implementation, and falling - back to our own LoadLibrary() wrapper. */ -#if HAVE_LIBDL && !defined(__CYGWIN__) - -/* dynamic linking with dlopen/dlsym */ - -#if HAVE_DLFCN_H -# include -#endif - -#if HAVE_SYS_DL_H -# include -#endif - -#ifdef RTLD_GLOBAL -# define LT_GLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_GLOBAL DL_GLOBAL -# endif -#endif /* !RTLD_GLOBAL */ -#ifndef LT_GLOBAL -# define LT_GLOBAL 0 -#endif /* !LT_GLOBAL */ - -/* We may have to define LT_LAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_LAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_LAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_LAZY_OR_NOW DL_LAZY -# endif -# endif /* !RTLD_LAZY */ -#endif -#ifndef LT_LAZY_OR_NOW -# ifdef RTLD_NOW -# define LT_LAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_LAZY_OR_NOW DL_NOW -# endif -# endif /* !RTLD_NOW */ -#endif -#ifndef LT_LAZY_OR_NOW -# define LT_LAZY_OR_NOW 0 -#endif /* !LT_LAZY_OR_NOW */ - -#if HAVE_DLERROR -# define DLERROR(arg) dlerror () -#else -# define DLERROR(arg) LT_DLSTRERROR (arg) -#endif - -static lt_module -sys_dl_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW); - - if (!module) - { - LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN)); - } - - return module; -} - -static int -sys_dl_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int errors = 0; - - if (dlclose (module) != 0) - { - LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE)); - ++errors; - } - - return errors; -} - -static lt_ptr -sys_dl_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = dlsym (module, symbol); - - if (!address) - { - LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND)); - } - - return address; -} - -static struct lt_user_dlloader sys_dl = - { -# ifdef NEED_USCORE - "_", -# else - 0, -# endif - sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 }; - - -#endif /* HAVE_LIBDL */ - - - -/* --- SHL_LOAD() INTERFACE LOADER --- */ - -#if HAVE_SHL_LOAD - -/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */ - -#ifdef HAVE_DL_H -# include -#endif - -/* some flags are missing on some systems, so we provide - * harmless defaults. - * - * Mandatory: - * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. - * BIND_DEFERRED - Delay code symbol resolution until actual reference. - * - * Optionally: - * BIND_FIRST - Place the library at the head of the symbol search - * order. - * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all - * unsatisfied symbols as fatal. This flag allows - * binding of unsatisfied code symbols to be deferred - * until use. - * [Perl: For certain libraries, like DCE, deferred - * binding often causes run time problems. Adding - * BIND_NONFATAL to BIND_IMMEDIATE still allows - * unresolved references in situations like this.] - * BIND_NOSTART - Do not call the initializer for the shared library - * when the library is loaded, nor on a future call to - * shl_unload(). - * BIND_VERBOSE - Print verbose messages concerning possible - * unsatisfied symbols. - * - * hp9000s700/hp9000s800: - * BIND_RESTRICTED - Restrict symbols visible by the library to those - * present at library load time. - * DYNAMIC_PATH - Allow the loader to dynamically search for the - * library specified by the path argument. - */ - -#ifndef DYNAMIC_PATH -# define DYNAMIC_PATH 0 -#endif -#ifndef BIND_RESTRICTED -# define BIND_RESTRICTED 0 -#endif - -#define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) - -static lt_module -sys_shl_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - static shl_t self = (shl_t) 0; - lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); - - /* Since searching for a symbol against a NULL module handle will also - look in everything else that was already loaded and exported with - the -E compiler flag, we always cache a handle saved before any - modules are loaded. */ - if (!self) - { - lt_ptr address; - shl_findsym (&self, "main", TYPE_UNDEFINED, &address); - } - - if (!filename) - { - module = self; - } - else - { - module = shl_load (filename, LT_BIND_FLAGS, 0L); - - if (!module) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); - } - } - - return module; -} - -static int -sys_shl_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int errors = 0; - - if (module && (shl_unload ((shl_t) (module)) != 0)) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); - ++errors; - } - - return errors; -} - -static lt_ptr -sys_shl_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = 0; - - /* sys_shl_open should never return a NULL module handle */ - if (module == (lt_module) 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - } - else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address)) - { - if (!address) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - } - } - - return address; -} - -static struct lt_user_dlloader sys_shl = { - 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 -}; - -#endif /* HAVE_SHL_LOAD */ - - - - -/* --- LOADLIBRARY() INTERFACE LOADER --- */ - -#ifdef __WINDOWS__ - -/* dynamic linking for Win32 */ - -#include - -void win32_print_last_error (char *fmtstring) -{ - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - printf (fmtstring, (char*)lpMsgBuf); - LocalFree (lpMsgBuf); -} - -/* Forward declaration; required to implement handle search below. */ -static lt_dlhandle handles; - -static lt_module -sys_wll_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - lt_dlhandle cur; - lt_module module = 0; - const char *errormsg = 0; - char *searchname = 0; - char *ext; - char self_name_buf[MAX_PATH]; - - if (!filename) - { - /* Get the name of main module */ - *self_name_buf = 0; - GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf)); - filename = ext = self_name_buf; - } - else - { - ext = strrchr (filename, '.'); - } - - if (ext) - { - /* FILENAME already has an extension. */ - searchname = lt_estrdup (filename); - } - else - { - /* Append a `.' to stop Windows from adding an - implicit `.dll' extension. */ - searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename)); - if (searchname) - sprintf (searchname, "%s.", filename); - } - if (!searchname) - return 0; - -#if __CYGWIN__ - { - char wpath[MAX_PATH]; - cygwin_conv_to_full_win32_path(searchname, wpath); - module = LoadLibrary(wpath); - } -#else - module = LoadLibrary (searchname); - if (!module) { - win32_print_last_error ("LoadLibrary failed: %s\n"); - } -#endif - LT_DLFREE (searchname); - - /* libltdl expects this function to fail if it is unable - to physically load the library. Sadly, LoadLibrary - will search the loaded libraries for a match and return - one of them if the path search load fails. - - We check whether LoadLibrary is returning a handle to - an already loaded module, and simulate failure if we - find one. */ - LT_DLMUTEX_LOCK (); - cur = handles; - while (cur) - { - if (!cur->module) - { - cur = 0; - break; - } - - if (cur->module == module) - { - break; - } - - cur = cur->next; - } - LT_DLMUTEX_UNLOCK (); - - if (cur || !module) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); - module = 0; - } - - return module; -} - -static int -sys_wll_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int errors = 0; - - if (FreeLibrary(module) == 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); - ++errors; - } - - return errors; -} - -static lt_ptr -sys_wll_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = GetProcAddress (module, symbol); - - if (!address) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - } - - return address; -} - -static struct lt_user_dlloader sys_wll = { - 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 -}; - -#endif /* __WINDOWS__ */ - - - - -/* --- LOAD_ADD_ON() INTERFACE LOADER --- */ - - -#ifdef __BEOS__ - -/* dynamic linking for BeOS */ - -#include - -static lt_module -sys_bedl_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - image_id image = 0; - - if (filename) - { - image = load_add_on (filename); - } - else - { - image_info info; - int32 cookie = 0; - if (get_next_image_info (0, &cookie, &info) == B_OK) - image = load_add_on (info.name); - } - - if (image <= 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); - image = 0; - } - - return (lt_module) image; -} - -static int -sys_bedl_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int errors = 0; - - if (unload_add_on ((image_id) module) != B_OK) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); - ++errors; - } - - return errors; -} - -static lt_ptr -sys_bedl_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = 0; - image_id image = (image_id) module; - - if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - address = 0; - } - - return address; -} - -static struct lt_user_dlloader sys_bedl = { - 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 -}; - -#endif /* __BEOS__ */ - - - - -/* --- DLD_LINK() INTERFACE LOADER --- */ - - -#if HAVE_DLD - -/* dynamic linking with dld */ - -#if HAVE_DLD_H -#include -#endif - -static lt_module -sys_dld_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - lt_module module = strdup (filename); - - if (dld_link (filename) != 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); - LT_DLFREE (module); - module = 0; - } - - return module; -} - -static int -sys_dld_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int errors = 0; - - if (dld_unlink_by_file ((char*)(module), 1) != 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); - ++errors; - } - else - { - LT_DLFREE (module); - } - - return errors; -} - -static lt_ptr -sys_dld_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = dld_get_func (symbol); - - if (!address) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - } - - return address; -} - -static struct lt_user_dlloader sys_dld = { - 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 -}; - -#endif /* HAVE_DLD */ - - - - -/* --- DLPREOPEN() INTERFACE LOADER --- */ - - -/* emulate dynamic linking using preloaded_symbols */ - -typedef struct lt_dlsymlists_t -{ - struct lt_dlsymlists_t *next; - const lt_dlsymlist *syms; -} lt_dlsymlists_t; - -static const lt_dlsymlist *default_preloaded_symbols = 0; -static lt_dlsymlists_t *preloaded_symbols = 0; - -static int -presym_init (loader_data) - lt_user_data loader_data; -{ - int errors = 0; - - LT_DLMUTEX_LOCK (); - - preloaded_symbols = 0; - if (default_preloaded_symbols) - { - errors = lt_dlpreload (default_preloaded_symbols); - } - - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -static int -presym_free_symlists () -{ - lt_dlsymlists_t *lists; - - LT_DLMUTEX_LOCK (); - - lists = preloaded_symbols; - while (lists) - { - lt_dlsymlists_t *tmp = lists; - - lists = lists->next; - LT_DLFREE (tmp); - } - preloaded_symbols = 0; - - LT_DLMUTEX_UNLOCK (); - - return 0; -} - -static int -presym_exit (loader_data) - lt_user_data loader_data; -{ - presym_free_symlists (); - return 0; -} - -static int -presym_add_symlist (preloaded) - const lt_dlsymlist *preloaded; -{ - lt_dlsymlists_t *tmp; - lt_dlsymlists_t *lists; - int errors = 0; - - LT_DLMUTEX_LOCK (); - - lists = preloaded_symbols; - while (lists) - { - if (lists->syms == preloaded) - { - goto done; - } - lists = lists->next; - } - - tmp = LT_EMALLOC (lt_dlsymlists_t, 1); - if (tmp) - { - memset (tmp, 0, sizeof(lt_dlsymlists_t)); - tmp->syms = preloaded; - tmp->next = preloaded_symbols; - preloaded_symbols = tmp; - } - else - { - ++errors; - } - - done: - LT_DLMUTEX_UNLOCK (); - return errors; -} - -static lt_module -presym_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - lt_dlsymlists_t *lists; - lt_module module = (lt_module) 0; - - LT_DLMUTEX_LOCK (); - lists = preloaded_symbols; - - if (!lists) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS)); - goto done; - } - - /* Can't use NULL as the reflective symbol header, as NULL is - used to mark the end of the entire symbol list. Self-dlpreopened - symbols follow this magic number, chosen to be an unlikely - clash with a real module name. */ - if (!filename) - { - filename = "@PROGRAM@"; - } - - while (lists) - { - const lt_dlsymlist *syms = lists->syms; - - while (syms->name) - { - if (!syms->address && strcmp(syms->name, filename) == 0) - { - module = (lt_module) syms; - goto done; - } - ++syms; - } - - lists = lists->next; - } - - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); - - done: - LT_DLMUTEX_UNLOCK (); - return module; -} - -static int -presym_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - /* Just to silence gcc -Wall */ - module = 0; - return 0; -} - -static lt_ptr -presym_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_dlsymlist *syms = (lt_dlsymlist*) module; - - ++syms; - while (syms->address) - { - if (strcmp(syms->name, symbol) == 0) - { - return syms->address; - } - - ++syms; - } - - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - - return 0; -} - -static struct lt_user_dlloader presym = { - 0, presym_open, presym_close, presym_sym, presym_exit, 0 -}; - - - - - -/* --- DYNAMIC MODULE LOADING --- */ - - -/* The type of a function used at each iteration of foreach_dirinpath(). */ -typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1, - lt_ptr data2)); - -static int foreach_dirinpath LT_PARAMS((const char *search_path, - const char *base_name, - foreach_callback_func *func, - lt_ptr data1, lt_ptr data2)); - -static int find_file_callback LT_PARAMS((char *filename, lt_ptr data, - lt_ptr ignored)); -static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data, - lt_ptr ignored)); -static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1, - lt_ptr data2)); - - -static int canonicalize_path LT_PARAMS((const char *path, - char **pcanonical)); -static int argzize_path LT_PARAMS((const char *path, - char **pargz, - size_t *pargz_len)); -static FILE *find_file LT_PARAMS((const char *search_path, - const char *base_name, - char **pdir)); -static lt_dlhandle *find_handle LT_PARAMS((const char *search_path, - const char *base_name, - lt_dlhandle *handle)); -static int find_module LT_PARAMS((lt_dlhandle *handle, - const char *dir, - const char *libdir, - const char *dlname, - const char *old_name, - int installed)); -static int free_vars LT_PARAMS((char *dlname, char *oldname, - char *libdir, char *deplibs)); -static int load_deplibs LT_PARAMS((lt_dlhandle handle, - char *deplibs)); -static int trim LT_PARAMS((char **dest, - const char *str)); -static int try_dlopen LT_PARAMS((lt_dlhandle *handle, - const char *filename)); -static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle, - const char *filename)); -static int unload_deplibs LT_PARAMS((lt_dlhandle handle)); -static int lt_argz_insert LT_PARAMS((char **pargz, - size_t *pargz_len, - char *before, - const char *entry)); -static int lt_argz_insertinorder LT_PARAMS((char **pargz, - size_t *pargz_len, - const char *entry)); -static int lt_dlpath_insertdir LT_PARAMS((char **ppath, - char *before, - const char *dir)); - -static char *user_search_path= 0; -static lt_dlloader *loaders = 0; -static lt_dlhandle handles = 0; -static int initialized = 0; - -/* Initialize libltdl. */ -int -lt_dlinit () -{ - int errors = 0; - - LT_DLMUTEX_LOCK (); - - /* Initialize only at first call. */ - if (++initialized == 1) - { - handles = 0; - user_search_path = 0; /* empty search path */ - -#if HAVE_LIBDL && !defined(__CYGWIN__) - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen"); -#endif -#if HAVE_SHL_LOAD - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen"); -#endif -#ifdef __WINDOWS__ - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen"); -#endif -#ifdef __BEOS__ - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen"); -#endif -#if HAVE_DLD - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld"); -#endif - errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload"); - - if (presym_init (presym.dlloader_data)) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER)); - ++errors; - } - else if (errors != 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED)); - ++errors; - } - } - - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -int -lt_dlpreload (preloaded) - const lt_dlsymlist *preloaded; -{ - int errors = 0; - - if (preloaded) - { - errors = presym_add_symlist (preloaded); - } - else - { - presym_free_symlists(); - - LT_DLMUTEX_LOCK (); - if (default_preloaded_symbols) - { - errors = lt_dlpreload (default_preloaded_symbols); - } - LT_DLMUTEX_UNLOCK (); - } - - return errors; -} - -int -lt_dlpreload_default (preloaded) - const lt_dlsymlist *preloaded; -{ - LT_DLMUTEX_LOCK (); - default_preloaded_symbols = preloaded; - LT_DLMUTEX_UNLOCK (); - return 0; -} - -int -lt_dlexit () -{ - /* shut down libltdl */ - lt_dlloader *loader; - int errors = 0; - - LT_DLMUTEX_LOCK (); - loader = loaders; - - if (!initialized) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN)); - ++errors; - goto done; - } - - /* shut down only at last call. */ - if (--initialized == 0) - { - int level; - - while (handles && LT_DLIS_RESIDENT (handles)) - { - handles = handles->next; - } - - /* close all modules */ - for (level = 1; handles; ++level) - { - lt_dlhandle cur = handles; - int saw_nonresident = 0; - - while (cur) - { - lt_dlhandle tmp = cur; - cur = cur->next; - if (!LT_DLIS_RESIDENT (tmp)) - saw_nonresident = 1; - if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level) - { - if (lt_dlclose (tmp)) - { - ++errors; - } - } - } - /* done if only resident modules are left */ - if (!saw_nonresident) - break; - } - - /* close all loaders */ - while (loader) - { - lt_dlloader *next = loader->next; - lt_user_data data = loader->dlloader_data; - if (loader->dlloader_exit && loader->dlloader_exit (data)) - { - ++errors; - } - - LT_DLMEM_REASSIGN (loader, next); - } - loaders = 0; - } - - done: - LT_DLMUTEX_UNLOCK (); - return errors; -} - -// returns number of errors, so 0=success -// returns handle in *handle, if one is found. -static int -tryall_dlopen (handle, filename) - lt_dlhandle *handle; - const char *filename; -{ - lt_dlhandle cur; - lt_dlloader *loader; - const char *saved_error; - int errors = 0; - - LT_DLMUTEX_GETERROR (saved_error); - LT_DLMUTEX_LOCK (); - - cur = handles; - loader = loaders; - - /* check whether the module was already opened */ - while (cur) - { - /* try to dlopen the program itself? */ - if (!cur->info.filename && !filename) - { - break; - } - - if (cur->info.filename && filename - && strcmp (cur->info.filename, filename) == 0) - { - break; - } - - cur = cur->next; - } - - if (cur) - { - ++cur->info.ref_count; - *handle = cur; - goto done; - } - - cur = *handle; - if (filename) - { - cur->info.filename = lt_estrdup (filename); - if (!cur->info.filename) - { - ++errors; - goto done; - } - } - else - { - cur->info.filename = 0; - } - - // Call access() to see if it exists first. If not return FILE_NOT_FOUND - // instead of CANNOT_OPEN. - if (access (cur->info.filename, R_OK) != 0) { - LT_DLFREE (cur->info.filename); - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); - ++errors; - goto done; - } - - while (loader) - { - lt_user_data data = loader->dlloader_data; - LTDEBUG_PRINTF(("Trying to open '%s' using loader '%s'\n", filename, loader->loader_name)); - cur->module = loader->module_open (data, filename); - - if (cur->module != 0) - { - LTDEBUG_PRINTF(("Load '%s' succeeded.\n", filename)); - break; - } - loader = loader->next; - } - - if (!loader) - { - LT_DLFREE (cur->info.filename); - ++errors; - goto done; - } - - cur->loader = loader; - LT_DLMUTEX_SETERROR (saved_error); - - done: - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -static int -tryall_dlopen_module (handle, prefix, dirname, dlname) - lt_dlhandle *handle; - const char *prefix; - const char *dirname; - const char *dlname; -{ - int error = 0; - char *filename = 0; - size_t filename_len = 0; -#ifdef __GNUC__ -#warning dirname could be null -#endif - size_t dirname_len = LT_STRLEN (dirname); - - if (dirname == NULL) { - LTDEBUG_PRINTF(("leaving tryall_dlopen_module early because dirname is NULL\n")); - return 1; - } - - assert (handle); - assert (dirname); - assert (dlname); -#ifdef LT_DIRSEP_CHAR - /* Only canonicalized names (i.e. with DIRSEP chars already converted) - should make it into this function: */ - assert (strchr (dirname, LT_DIRSEP_CHAR) == 0); -#endif - - if (dirname[dirname_len -1] == '/') - --dirname_len; - filename_len = dirname_len + 1 + LT_STRLEN (dlname); - - /* Allocate memory, and combine DIRNAME and MODULENAME into it. - The PREFIX (if any) is handled below. */ - filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1); - if (!filename) - return 1; - - sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname); - - /* Now that we have combined DIRNAME and MODULENAME, if there is - also a PREFIX to contend with, simply recurse with the arguments - shuffled. Otherwise, attempt to open FILENAME as a module. */ - if (prefix) - { - error += tryall_dlopen_module (handle, - (const char *) 0, prefix, filename); - } - else if (tryall_dlopen (handle, filename) != 0) - { - ++error; - } - - LT_DLFREE (filename); - return error; -} - -static int -find_module (handle, dir, libdir, dlname, old_name, installed) - lt_dlhandle *handle; - const char *dir; - const char *libdir; - const char *dlname; - const char *old_name; - int installed; -{ - /* Try to open the old library first; if it was dlpreopened, - we want the preopened version of it, even if a dlopenable - module is available. */ - if (old_name && tryall_dlopen (handle, old_name) == 0) - { - return 0; - } - - /* Try to open the dynamic library. */ - if (dlname) - { - /* try to open the installed module */ - if (installed && libdir) - { - if (tryall_dlopen_module (handle, - (const char *) 0, libdir, dlname) == 0) - return 0; - } - - /* try to open the not-installed module */ - if (!installed) - { - if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0) - return 0; - } - - /* maybe it was moved to another directory */ - { - if (tryall_dlopen_module (handle, - (const char *) 0, dir, dlname) == 0) - return 0; - } - } - - return 1; -} - - -static int -canonicalize_path (path, pcanonical) - const char *path; - char **pcanonical; -{ - char *canonical = 0; - - assert (path && *path); - assert (pcanonical); - - canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path)); - if (!canonical) - return 1; - - { - size_t dest = 0; - size_t src; - for (src = 0; path[src] != LT_EOS_CHAR; ++src) - { - /* Path separators are not copied to the beginning or end of - the destination, or if another separator would follow - immediately. */ - if (path[src] == LT_PATHSEP_CHAR) - { - if ((dest == 0) - || (path[1+ src] == LT_PATHSEP_CHAR) - || (path[1+ src] == LT_EOS_CHAR)) - continue; - } - - /* Anything other than a directory separator is copied verbatim. */ - if ((path[src] != '/') -#ifdef LT_DIRSEP_CHAR - && (path[src] != LT_DIRSEP_CHAR) -#endif - ) - { - canonical[dest++] = path[src]; - } - /* Directory separators are converted and copied only if they are - not at the end of a path -- i.e. before a path separator or - NULL terminator. */ - else if ((path[1+ src] != LT_PATHSEP_CHAR) - && (path[1+ src] != LT_EOS_CHAR) -#ifdef LT_DIRSEP_CHAR - && (path[1+ src] != LT_DIRSEP_CHAR) -#endif - && (path[1+ src] != '/')) - { - canonical[dest++] = '/'; - } - } - - /* Add an end-of-string marker at the end. */ - canonical[dest] = LT_EOS_CHAR; - } - - /* Assign new value. */ - *pcanonical = canonical; - - return 0; -} - -static int -argzize_path (path, pargz, pargz_len) - const char *path; - char **pargz; - size_t *pargz_len; -{ - error_t error; - - assert (path); - assert (pargz); - assert (pargz_len); - - if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len))) - { - switch (error) - { - case ENOMEM: - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); - break; - default: - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); - break; - } - - return 1; - } - - return 0; -} - -/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element - of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns - non-zero or all elements are exhausted. If BASE_NAME is non-NULL, - it is appended to each SEARCH_PATH element before FUNC is called. */ -static int -foreach_dirinpath (search_path, base_name, func, data1, data2) - const char *search_path; - const char *base_name; - foreach_callback_func *func; - lt_ptr data1; - lt_ptr data2; -{ - int result = 0; - int filenamesize = 0; - int lenbase = LT_STRLEN (base_name); - size_t argz_len = 0; - char * argz = 0; - char * filename = 0; - char * canonical = 0; - - LT_DLMUTEX_LOCK (); - - if (!search_path || !*search_path) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); - goto cleanup; - } - - if (canonicalize_path (search_path, &canonical) != 0) - goto cleanup; - - if (argzize_path (canonical, &argz, &argz_len) != 0) - goto cleanup; - - { - char *dir_name = 0; - while ((dir_name = argz_next (argz, argz_len, dir_name))) - { - int lendir = LT_STRLEN (dir_name); - - if (lendir +1 +lenbase >= filenamesize) - { - LT_DLFREE (filename); - filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */ - filename = LT_EMALLOC (char, filenamesize); - if (!filename) - goto cleanup; - } - - strncpy (filename, dir_name, lendir); - if (base_name && *base_name) - { - if (filename[lendir -1] != '/') - filename[lendir++] = '/'; - strcpy (filename +lendir, base_name); - } - - if ((result = (*func) (filename, data1, data2))) - { - break; - } - } - } - - cleanup: - LT_DLFREE (argz); - LT_DLFREE (canonical); - LT_DLFREE (filename); - - LT_DLMUTEX_UNLOCK (); - - return result; -} - -/* If FILEPATH can be opened, store the name of the directory component - in DATA1, and the opened FILE* structure address in DATA2. Otherwise - DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */ -static int -find_file_callback (filename, data1, data2) - char *filename; - lt_ptr data1; - lt_ptr data2; -{ - char **pdir = (char **) data1; - FILE **pfile = (FILE **) data2; - int is_done = 0; - - assert (filename && *filename); - assert (pdir); - assert (pfile); - - if ((*pfile = fopen (filename, LT_READTEXT_MODE))) - { - char *dirend = strrchr (filename, '/'); - LTDEBUG_PRINTF(("find_file_callback opening file '%s'...ok\n", filename)); - - if (dirend > filename) - *dirend = LT_EOS_CHAR; - - LT_DLFREE (*pdir); - *pdir = lt_estrdup (filename); - is_done = (*pdir == 0) ? -1 : 1; - } - else - { - LTDEBUG_PRINTF(("find_file_callback opening file '%s'...failed\n", filename)); - } - - return is_done; -} - -static FILE * -find_file (search_path, base_name, pdir) - const char *search_path; - const char *base_name; - char **pdir; -{ - FILE *file = 0; - - foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file); - - return file; -} - -static int -find_handle_callback (filename, data, ignored) - char *filename; - lt_ptr data; - lt_ptr ignored; -{ - lt_dlhandle *handle = (lt_dlhandle *) data; - int found = (0 == access (filename, R_OK)); - LTDEBUG_PRINTF(("find_handle_callback searching for '%s'...%s\n", filename, found?"found":"not found")); - - /* Bail out if file cannot be read... */ - if (!found) - return 0; - - /* Try to dlopen the file, but do not continue searching in any - case. */ - if (tryall_dlopen (handle, filename) != 0) - *handle = 0; - - return 1; -} - -/* If HANDLE was found return it, otherwise return 0. If HANDLE was - found but could not be opened, *HANDLE will be set to 0. */ -static lt_dlhandle * -find_handle (search_path, base_name, handle) - const char *search_path; - const char *base_name; - lt_dlhandle *handle; -{ - if (!search_path) - return 0; - - if (!foreach_dirinpath (search_path, base_name, find_handle_callback, - handle, 0)) - return 0; - - return handle; -} - -static int -load_deplibs (handle, deplibs) - lt_dlhandle handle; - char *deplibs; -{ -#if LTDL_DLOPEN_DEPLIBS - char *p, *save_search_path = 0; - int depcount = 0; - int i; - char **names = 0; -#endif - int errors = 0; - - handle->depcount = 0; - -#if LTDL_DLOPEN_DEPLIBS - if (!deplibs) - { - return errors; - } - ++errors; - - LT_DLMUTEX_LOCK (); - if (user_search_path) - { - save_search_path = lt_estrdup (user_search_path); - if (!save_search_path) - goto cleanup; - } - - /* extract search paths and count deplibs */ - p = deplibs; - while (*p) - { - if (!isspace ((int) *p)) - { - char *end = p+1; - while (*end && !isspace((int) *end)) - { - ++end; - } - - if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0) - { - char save = *end; - *end = 0; /* set a temporary string terminator */ - if (lt_dladdsearchdir(p+2)) - { - goto cleanup; - } - *end = save; - } - else - { - ++depcount; - } - - p = end; - } - else - { - ++p; - } - } - - /* restore the old search path */ - LT_DLFREE (user_search_path); - user_search_path = save_search_path; - - LT_DLMUTEX_UNLOCK (); - - if (!depcount) - { - errors = 0; - goto cleanup; - } - - names = LT_EMALLOC (char *, depcount * sizeof (char*)); - if (!names) - goto cleanup; - - /* now only extract the actual deplibs */ - depcount = 0; - p = deplibs; - while (*p) - { - if (isspace ((int) *p)) - { - ++p; - } - else - { - char *end = p+1; - while (*end && !isspace ((int) *end)) - { - ++end; - } - - if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0) - { - char *name; - char save = *end; - *end = 0; /* set a temporary string terminator */ - if (strncmp(p, "-l", 2) == 0) - { - size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2); - name = LT_EMALLOC (char, 1+ name_len); - if (name) - sprintf (name, "lib%s", p+2); - } - else - name = lt_estrdup(p); - - if (!name) - goto cleanup_names; - - names[depcount++] = name; - *end = save; - } - p = end; - } - } - - /* load the deplibs (in reverse order) - At this stage, don't worry if the deplibs do not load correctly, - they may already be statically linked into the loading application - for instance. There will be a more enlightening error message - later on if the loaded module cannot resolve all of its symbols. */ - if (depcount) - { - int j = 0; - - handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount); - if (!handle->deplibs) - goto cleanup; - - for (i = 0; i < depcount; ++i) - { - handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]); - if (handle->deplibs[j]) - { - ++j; - } - } - - handle->depcount = j; /* Number of successfully loaded deplibs */ - errors = 0; - } - - cleanup_names: - for (i = 0; i < depcount; ++i) - { - LT_DLFREE (names[i]); - } - - cleanup: - LT_DLFREE (names); -#endif - - return errors; -} - -static int -unload_deplibs (handle) - lt_dlhandle handle; -{ - int i; - int errors = 0; - - if (handle->depcount) - { - for (i = 0; i < handle->depcount; ++i) - { - if (!LT_DLIS_RESIDENT (handle->deplibs[i])) - { - errors += lt_dlclose (handle->deplibs[i]); - } - } - } - - return errors; -} - -static int -trim (dest, str) - char **dest; - const char *str; -{ - /* remove the leading and trailing "'" from str - and store the result in dest */ - const char *end = strrchr (str, '\''); - int len = LT_STRLEN (str); - char *tmp; - - LT_DLFREE (*dest); - - if (len > 3 && str[0] == '\'') - { - tmp = LT_EMALLOC (char, end - str); - if (!tmp) - return 1; - - strncpy(tmp, &str[1], (end - str) - 1); - tmp[len-3] = LT_EOS_CHAR; - *dest = tmp; - } - else - { - *dest = 0; - } - - return 0; -} - -static int -free_vars (dlname, oldname, libdir, deplibs) - char *dlname; - char *oldname; - char *libdir; - char *deplibs; -{ - LT_DLFREE (dlname); - LT_DLFREE (oldname); - LT_DLFREE (libdir); - LT_DLFREE (deplibs); - - return 0; -} - -// returns number of errors, so 0=success. -// phandle is a pointer to an lt_dlhandle, which must initially be NULL. -// On success (return value=0), *phandle is changed to point to the new -// lt_dlhandle. -int -try_dlopen (phandle, filename) - lt_dlhandle *phandle; - const char *filename; -{ - const char * ext = 0; - const char * saved_error = 0; - char * canonical = 0; - char * base_name = 0; - char * dir = 0; - char * name = 0; - int errors = 0; - lt_dlhandle newhandle; - - assert (phandle); - assert (*phandle == 0); - - LT_DLMUTEX_GETERROR (saved_error); - - /* dlopen self? */ - if (!filename) - { - *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); - if (*phandle == 0) - return 1; - - memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); - newhandle = *phandle; - - /* lt_dlclose()ing yourself is very bad! Disallow it. */ - LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG); - - if (tryall_dlopen (&newhandle, 0) != 0) - { - LT_DLFREE (*phandle); // this sets *phandle=NULL - return 1; - } - - goto register_handle; - } - - assert (filename && *filename); - - /* Doing this immediately allows internal functions to safely - assume only canonicalized paths are passed. */ - if (canonicalize_path (filename, &canonical) != 0) - { - ++errors; - goto cleanup; - } - - /* If the canonical module name is a path (relative or absolute) - then split it into a directory part and a name part. */ - base_name = strrchr (canonical, '/'); - if (base_name) - { - size_t dirlen = (1+ base_name) - canonical; - - dir = LT_EMALLOC (char, 1+ dirlen); - if (!dir) - { - ++errors; - goto cleanup; - } - - strncpy (dir, canonical, dirlen); - dir[dirlen] = LT_EOS_CHAR; - - ++base_name; - LTDEBUG_PRINTF(("in base_name not NULL section. dir='%s', base_name='%s', canonical='%s'\n", dir, base_name, canonical)); - } - else { - LT_DLMEM_REASSIGN (base_name, canonical); - LTDEBUG_PRINTF(("in base_name=NULL section. dir=NULL, base_name='%s', canonical='%s'\n", base_name, canonical)); - } - - assert (base_name && *base_name); - - /* Check whether we are opening a libtool module (.la extension). */ - ext = strrchr (base_name, '.'); - if (ext && strcmp (ext, archive_ext) == 0) - { - /* this seems to be a libtool module */ - FILE * file = 0; - char * dlname = 0; - char * old_name = 0; - char * libdir = 0; - char * deplibs = 0; - char * line = 0; - size_t line_len; - int i; - - /* if we can't find the installed flag, it is probably an - installed libtool archive, produced with an old version - of libtool */ - int installed = 1; - - /* extract the module name from the file name */ - name = LT_EMALLOC (char, ext - base_name + 1); - if (!name) - { - ++errors; - goto cleanup; - } - - /* canonicalize the module name */ - for (i = 0; i < ext - base_name; ++i) - { - if (isalnum ((int)(base_name[i]))) - { - name[i] = base_name[i]; - } - else - { - name[i] = '_'; - } - } - name[ext - base_name] = LT_EOS_CHAR; - - /* Now try to open the .la file. If there is no directory name - component, try to find it first in user_search_path and then other - prescribed paths. Otherwise (or in any case if the module was not - yet found) try opening just the module name as passed. */ - if (!dir) - { - const char *search_path; - - LT_DLMUTEX_LOCK (); - search_path = user_search_path; - if (search_path) - file = find_file (user_search_path, base_name, &dir); - LT_DLMUTEX_UNLOCK (); - - if (!file) - { - search_path = getenv (LTDL_SEARCHPATH_VAR); - if (search_path) - file = find_file (search_path, base_name, &dir); - } - -#ifdef LTDL_SHLIBPATH_VAR - if (!file) - { - search_path = getenv (LTDL_SHLIBPATH_VAR); - if (search_path) - file = find_file (search_path, base_name, &dir); - } -#endif -#ifdef LTDL_SYSSEARCHPATH - if (!file && sys_search_path) - { - file = find_file (sys_search_path, base_name, &dir); - } -#endif - } - if (!file) - { - LTDEBUG_PRINTF(("try_dlopen opening file '%s'\n", filename)); - file = fopen (filename, LT_READTEXT_MODE); -#ifdef __GNUC__ -#warning dir is still NULL -#endif - } - - /* If we didn't find the file by now, it really isn't there. Set - the status flag, and bail out. */ - if (!file) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); - ++errors; - goto cleanup; - } - - line_len = LT_FILENAME_MAX; - line = LT_EMALLOC (char, line_len); - if (!line) - { - fclose (file); - ++errors; - goto cleanup; - } - - /* read the .la file */ - while (!feof (file)) - { - if (!fgets (line, line_len, file)) - { - break; - } - - /* Handle the case where we occasionally need to read a line - that is longer than the initial buffer size. */ - while (line[LT_STRLEN(line) -1] != '\n') - { - line = LT_DLREALLOC (char, line, line_len *2); - if (!fgets (&line[line_len -1], line_len +1, file)) - { - break; - } - line_len *= 2; - } - - if (line[0] == '\n' || line[0] == '#') - { - continue; - } - -#undef STR_DLNAME -#define STR_DLNAME "dlname=" - if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0) - { - errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]); - } - -#undef STR_OLD_LIBRARY -#define STR_OLD_LIBRARY "old_library=" - else if (strncmp (line, STR_OLD_LIBRARY, - sizeof (STR_OLD_LIBRARY) - 1) == 0) - { - errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]); - } -#undef STR_LIBDIR -#define STR_LIBDIR "libdir=" - else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0) - { - errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]); - } - -#undef STR_DL_DEPLIBS -#define STR_DL_DEPLIBS "dependency_libs=" - else if (strncmp (line, STR_DL_DEPLIBS, - sizeof (STR_DL_DEPLIBS) - 1) == 0) - { - errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]); - } - else if (strcmp (line, "installed=yes\n") == 0) - { - installed = 1; - } - else if (strcmp (line, "installed=no\n") == 0) - { - installed = 0; - } - -#undef STR_LIBRARY_NAMES -#define STR_LIBRARY_NAMES "library_names=" - else if (! dlname && strncmp (line, STR_LIBRARY_NAMES, - sizeof (STR_LIBRARY_NAMES) - 1) == 0) - { - char *last_libname; - errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]); - if (!errors - && dlname - && (last_libname = strrchr (dlname, ' ')) != 0) - { - last_libname = lt_estrdup (last_libname + 1); - if (!last_libname) - { - ++errors; - goto cleanup; - } - LT_DLMEM_REASSIGN (dlname, last_libname); - } - } - - if (errors) - break; - } - - fclose (file); - LT_DLFREE (line); - - /* allocate the handle */ - *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); - if (*phandle == 0) - ++errors; - - if (errors) - { - free_vars (dlname, old_name, libdir, deplibs); - LT_DLFREE (*phandle); - goto cleanup; - } - - assert (*phandle); - - memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); - if (load_deplibs (*phandle, deplibs) == 0) - { - newhandle = *phandle; - /* find_module may replace newhandle */ - if (find_module (&newhandle, dir, libdir, dlname, old_name, installed)) - { - unload_deplibs (*phandle); - ++errors; - } - } - else - { - ++errors; - } - - free_vars (dlname, old_name, libdir, deplibs); - if (errors) - { - LT_DLFREE (*phandle); // sets *phandle=NULL - goto cleanup; - } - - if (*phandle != newhandle) - { - unload_deplibs (*phandle); - } - } - else - { - /* not a libtool module */ - *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); - if (*phandle == 0) - { - ++errors; - goto cleanup; - } - - memset (*phandle, 0, sizeof (struct lt_dlhandle_struct)); - newhandle = *phandle; - - /* If the module has no directory name component, try to find it - first in user_search_path and then other prescribed paths. - Otherwise (or in any case if the module was not yet found) try - opening just the module name as passed. */ - if ((dir || (!find_handle (user_search_path, base_name, &newhandle) - && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name, - &newhandle) -#ifdef LTDL_SHLIBPATH_VAR - && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name, - &newhandle) -#endif -#ifdef LTDL_SYSSEARCHPATH - && !find_handle (sys_search_path, base_name, &newhandle) -#endif - ))) - { - // Directory component was specified, or all find_handle() calls - // failed to find the lib. This is our last try. - errors = tryall_dlopen (&newhandle, filename); - } - - if (!newhandle || errors>0) - { - LT_DLFREE (*phandle); - ++errors; - goto cleanup; - } - } - - register_handle: - LT_DLMEM_REASSIGN (*phandle, newhandle); - - if ((*phandle)->info.ref_count == 0) - { - (*phandle)->info.ref_count = 1; - LT_DLMEM_REASSIGN ((*phandle)->info.name, name); - - LT_DLMUTEX_LOCK (); - (*phandle)->next = handles; - handles = *phandle; - LT_DLMUTEX_UNLOCK (); - } - - LT_DLMUTEX_SETERROR (saved_error); - - cleanup: - LT_DLFREE (dir); - LT_DLFREE (name); - LT_DLFREE (canonical); - - return errors; -} - -lt_dlhandle -lt_dlopen (filename) - const char *filename; -{ - lt_dlhandle handle = 0; - - /* Just incase we missed a code path in try_dlopen() that reports - an error, but forgets to reset handle... */ - if (try_dlopen (&handle, filename) != 0) - return 0; - - // If we're going to return a handle, be sure that has its loader - // field filled in. This is in response to some bugs in which dlopen() - // would return valid-looking handle with NULL loader, causing crashes - // later. - if (handle) assert (handle->loader != NULL); - - return handle; -} - -/* If the last error messge store was `FILE_NOT_FOUND', then return - non-zero. */ -int -file_not_found () -{ - const char *error = 0; - - LT_DLMUTEX_GETERROR (error); - if (error == LT_DLSTRERROR (FILE_NOT_FOUND)) - return 1; - - return 0; -} - -/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to - open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT, - and if a file is still not found try again with SHLIB_EXT appended - instead. */ -lt_dlhandle -lt_dlopenext (filename) - const char *filename; -{ - lt_dlhandle handle = 0; - char * tmp = 0; - char * ext = 0; - int len; - int errors = 0; - int file_found = 1; /* until proven otherwise */ - - if (!filename) - { - return lt_dlopen (filename); - } - - assert (filename); - - len = LT_STRLEN (filename); - ext = strrchr (filename, '.'); - - /* If FILENAME already bears a suitable extension, there is no need - to try appending additional extensions. */ - if (ext && ((strcmp (ext, archive_ext) == 0) -#ifdef LTDL_SHLIB_EXT - || (strcmp (ext, shlib_ext) == 0) -#endif - )) - { - return lt_dlopen (filename); - } - - /* First try appending ARCHIVE_EXT. */ - tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1); - if (!tmp) - return 0; - - strcpy (tmp, filename); - strcat (tmp, archive_ext); - errors = try_dlopen (&handle, tmp); - - /* If we found FILENAME, stop searching -- whether we were able to - load the file as a module or not. If the file exists but loading - failed, it is better to return an error message here than to - report FILE_NOT_FOUND when the alternatives (foo.so etc) are not - in the module search path. */ - if (handle || ((errors > 0) && !file_not_found ())) - { - LT_DLFREE (tmp); - - // If we're going to return a handle, be sure that has its loader - // field filled in. This is in response to some bugs in which dlopen() - // would return valid-looking handle with NULL loader, causing crashes - // later. - if (handle) assert (handle->loader != NULL); - - return handle; - } - -#ifdef LTDL_SHLIB_EXT - /* Try appending SHLIB_EXT. */ - if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext)) - { - LT_DLFREE (tmp); - tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1); - if (!tmp) - return 0; - - strcpy (tmp, filename); - } - else - { - tmp[len] = LT_EOS_CHAR; - } - - strcat(tmp, shlib_ext); - errors = try_dlopen (&handle, tmp); - - /* As before, if the file was found but loading failed, return now - with the current error message. */ - if (handle || ((errors > 0) && !file_not_found ())) - { - LT_DLFREE (tmp); - // If we're going to return a handle, be sure that has its loader - // field filled in. This is in response to some bugs in which dlopen() - // would return valid-looking handle with NULL loader, causing crashes - // later. - if (handle) assert (handle->loader != NULL); - return handle; - } -#endif - - /* Still here? Then we really did fail to locate any of the file - names we tried. */ - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); - LT_DLFREE (tmp); - return 0; -} - - -int -lt_argz_insert (pargz, pargz_len, before, entry) - char **pargz; - size_t *pargz_len; - char *before; - const char *entry; -{ - error_t error; - - if ((error = argz_insert (pargz, pargz_len, before, entry))) - { - switch (error) - { - case ENOMEM: - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); - break; - default: - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); - break; - } - return 1; - } - - return 0; -} - -int -lt_argz_insertinorder (pargz, pargz_len, entry) - char **pargz; - size_t *pargz_len; - const char *entry; -{ - char *before = 0; - - assert (pargz); - assert (pargz_len); - assert (entry && *entry); - - if (*pargz) - while ((before = argz_next (*pargz, *pargz_len, before))) - { - int cmp = strcmp (entry, before); - - if (cmp < 0) break; - if (cmp == 0) return 0; /* No duplicates! */ - } - - return lt_argz_insert (pargz, pargz_len, before, entry); -} - -int -lt_argz_insertdir (pargz, pargz_len, dirnam, dp) - char **pargz; - size_t *pargz_len; - const char *dirnam; - struct dirent *dp; -{ - char *buf = 0; - size_t buf_len = 0; - char *end = 0; - size_t end_offset = 0; - size_t dir_len = 0; - int errors = 0; - - assert (pargz); - assert (pargz_len); - assert (dp); - - dir_len = LT_STRLEN (dirnam); - end = dp->d_name + LT_D_NAMLEN(dp); - - /* Ignore version numbers. */ - { - char *p; - for (p = end; p -1 > dp->d_name; --p) - if (strchr (".0123456789", p[-1]) == 0) - break; - - if (*p == '.') - end = p; - } - - /* Ignore filename extension. */ - { - char *p; - for (p = end -1; p > dp->d_name; --p) - if (*p == '.') - { - end = p; - break; - } - } - - /* Prepend the directory name. */ - end_offset = end - dp->d_name; - buf_len = dir_len + 1+ end_offset; - buf = LT_EMALLOC (char, 1+ buf_len); - if (!buf) - return ++errors; - - assert (buf); - - strcpy (buf, dirnam); - strcat (buf, "/"); - strncat (buf, dp->d_name, end_offset); - buf[buf_len] = LT_EOS_CHAR; - - /* Try to insert (in order) into ARGZ/ARGZ_LEN. */ - if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0) - ++errors; - - LT_DLFREE (buf); - - return errors; -} - -int -list_files_by_dir (dirnam, pargz, pargz_len) - const char *dirnam; - char **pargz; - size_t *pargz_len; -{ - DIR *dirp = 0; - int errors = 0; - - assert (dirnam && *dirnam); - assert (pargz); - assert (pargz_len); - assert (dirnam[LT_STRLEN(dirnam) -1] != '/'); - - dirp = opendir (dirnam); - if (dirp) - { - struct dirent *dp = 0; - - while ((dp = readdir (dirp))) - if (dp->d_name[0] != '.') - if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp)) - { - ++errors; - break; - } - - closedir (dirp); - } - else - ++errors; - - return errors; -} - - -/* If there are any files in DIRNAME, call the function passed in - DATA1 (with the name of each file and DATA2 as arguments). */ -static int -foreachfile_callback (dirname, data1, data2) - char *dirname; - lt_ptr data1; - lt_ptr data2; -{ - int (*func) LT_PARAMS((const char *filename, lt_ptr data)) - = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1; - - int is_done = 0; - char *argz = 0; - size_t argz_len = 0; - - if (list_files_by_dir (dirname, &argz, &argz_len) != 0) - goto cleanup; - if (!argz) - goto cleanup; - - { - char *filename = 0; - while ((filename = argz_next (argz, argz_len, filename))) - if ((is_done = (*func) (filename, data2))) - break; - } - - cleanup: - LT_DLFREE (argz); - - return is_done; -} - - -/* Call FUNC for each unique extensionless file in SEARCH_PATH, along - with DATA. The filenames passed to FUNC would be suitable for - passing to lt_dlopenext. The extensions are stripped so that - individual modules do not generate several entries (e.g. libfoo.la, - libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL, - then the same directories that lt_dlopen would search are examined. */ -int -lt_dlforeachfile (search_path, func, data) - const char *search_path; - int (*func) LT_PARAMS ((const char *filename, lt_ptr data)); - lt_ptr data; -{ - int is_done = 0; - - if (search_path) - { - /* If a specific path was passed, search only the directories - listed in it. */ - is_done = foreach_dirinpath (search_path, 0, - foreachfile_callback, func, data); - } - else - { - /* Otherwise search the default paths. */ - is_done = foreach_dirinpath (user_search_path, 0, - foreachfile_callback, func, data); - if (!is_done) - { - is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0, - foreachfile_callback, func, data); - } - -#ifdef LTDL_SHLIBPATH_VAR - if (!is_done) - { - is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0, - foreachfile_callback, func, data); - } -#endif -#ifdef LTDL_SYSSEARCHPATH - if (!is_done) - { - is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0, - foreachfile_callback, func, data); - } -#endif - } - - return is_done; -} - -int -lt_dlclose (handle) - lt_dlhandle handle; -{ - lt_dlhandle cur, last; - int errors = 0; - - LT_DLMUTEX_LOCK (); - - /* check whether the handle is valid */ - last = cur = handles; - while (cur && handle != cur) - { - last = cur; - cur = cur->next; - } - - if (!cur) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - ++errors; - goto done; - } - - handle->info.ref_count--; - - /* Note that even with resident modules, we must track the ref_count - correctly incase the user decides to reset the residency flag - later (even though the API makes no provision for that at the - moment). */ - if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle)) - { - lt_user_data data = handle->loader->dlloader_data; - - if (handle != handles) - { - last->next = handle->next; - } - else - { - handles = handle->next; - } - - errors += handle->loader->module_close (data, handle->module); - errors += unload_deplibs(handle); - - LT_DLFREE (handle->info.filename); - LT_DLFREE (handle->info.name); - LT_DLFREE (handle); - - goto done; - } - - if (LT_DLIS_RESIDENT (handle)) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE)); - ++errors; - } - - done: - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -lt_ptr -lt_dlsym (handle, symbol) - lt_dlhandle handle; - const char *symbol; -{ - int lensym; - char lsym[LT_SYMBOL_LENGTH]; - char *sym; - lt_ptr address; - lt_user_data data; - - if (!handle) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - return 0; - } - - if (!symbol) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - return 0; - } - - // Due to bugs in lt_dlopen*, some handles were being returned that have a - // NULL loader field. Check for this. - assert (handle->loader); - - lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix) - + LT_STRLEN (handle->info.name); - - if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH) - { - sym = lsym; - } - else - { - sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1); - if (!sym) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW)); - return 0; - } - } - - data = handle->loader->dlloader_data; - if (handle->info.name) - { - const char *saved_error; - - LT_DLMUTEX_GETERROR (saved_error); - - /* this is a libtool module */ - if (handle->loader->sym_prefix) - { - strcpy(sym, handle->loader->sym_prefix); - strcat(sym, handle->info.name); - } - else - { - strcpy(sym, handle->info.name); - } - - strcat(sym, "_LTX_"); - strcat(sym, symbol); - - /* try "modulename_LTX_symbol" */ - LTDEBUG_PRINTF(("dlsym looking for '%s'\n", sym)); - address = handle->loader->find_sym (data, handle->module, sym); - if (address) - { - if (sym != lsym) - { - LT_DLFREE (sym); - } - return address; - } - LT_DLMUTEX_SETERROR (saved_error); - } - - /* otherwise try "symbol" */ - if (handle->loader->sym_prefix) - { - strcpy(sym, handle->loader->sym_prefix); - strcat(sym, symbol); - } - else - { - strcpy(sym, symbol); - } - - LTDEBUG_PRINTF(("dlsym looking for '%s'\n", sym)); - address = handle->loader->find_sym (data, handle->module, sym); - if (sym != lsym) - { - LT_DLFREE (sym); - } - - return address; -} - -const char * -lt_dlerror () -{ - const char *error; - - LT_DLMUTEX_GETERROR (error); - LT_DLMUTEX_SETERROR (0); - - return error ? error : LT_DLSTRERROR (UNKNOWN); -} - -int -lt_dlpath_insertdir (ppath, before, dir) - char **ppath; - char *before; - const char *dir; -{ - int errors = 0; - char *canonical = 0; - char *argz = 0; - size_t argz_len = 0; - - assert (ppath); - assert (dir && *dir); - - if (canonicalize_path (dir, &canonical) != 0) - { - ++errors; - goto cleanup; - } - - assert (canonical && *canonical); - - /* If *PPATH is empty, set it to DIR. */ - if (*ppath == 0) - { - assert (!before); /* BEFORE cannot be set without PPATH. */ - assert (dir); /* Without DIR, don't call this function! */ - - *ppath = lt_estrdup (dir); - if (*ppath == 0) - ++errors; - - return errors; - } - - assert (ppath && *ppath); - - if (argzize_path (*ppath, &argz, &argz_len) != 0) - { - ++errors; - goto cleanup; - } - - /* Convert BEFORE into an equivalent offset into ARGZ. This only works - if *PPATH is already canonicalized, and hence does not change length - with respect to ARGZ. We canonicalize each entry as it is added to - the search path, and don't call this function with (uncanonicalized) - user paths, so this is a fair assumption. */ - if (before) - { - assert (*ppath <= before); - assert (before - *ppath <= strlen (*ppath)); - - before = before - *ppath + argz; - } - - if (lt_argz_insert (&argz, &argz_len, before, dir) != 0) - { - ++errors; - goto cleanup; - } - - argz_stringify (argz, argz_len, LT_PATHSEP_CHAR); - LT_DLMEM_REASSIGN (*ppath, argz); - - cleanup: - LT_DLFREE (canonical); - LT_DLFREE (argz); - - return errors; -} - -int -lt_dladdsearchdir (search_dir) - const char *search_dir; -{ - int errors = 0; - - if (search_dir && *search_dir) - { - LT_DLMUTEX_LOCK (); - if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0) - ++errors; - LT_DLMUTEX_UNLOCK (); - } - - return errors; -} - -int -lt_dlinsertsearchdir (before, search_dir) - const char *before; - const char *search_dir; -{ - int errors = 0; - - if (before) - { - LT_DLMUTEX_LOCK (); - if ((before < user_search_path) - || (before >= user_search_path + LT_STRLEN (user_search_path))) - { - LT_DLMUTEX_UNLOCK (); - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION)); - return 1; - } - LT_DLMUTEX_UNLOCK (); - } - - if (search_dir && *search_dir) - { - LT_DLMUTEX_LOCK (); - if (lt_dlpath_insertdir (&user_search_path, - (char *) before, search_dir) != 0) - { - ++errors; - } - LT_DLMUTEX_UNLOCK (); - } - - return errors; -} - -int -lt_dlsetsearchpath (search_path) - const char *search_path; -{ - int errors = 0; - - LT_DLMUTEX_LOCK (); - LT_DLFREE (user_search_path); - LT_DLMUTEX_UNLOCK (); - - if (!search_path || !LT_STRLEN (search_path)) - { - return errors; - } - - LT_DLMUTEX_LOCK (); - if (canonicalize_path (search_path, &user_search_path) != 0) - ++errors; - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -const char * -lt_dlgetsearchpath () -{ - const char *saved_path; - - LT_DLMUTEX_LOCK (); - saved_path = user_search_path; - LT_DLMUTEX_UNLOCK (); - - return saved_path; -} - -int -lt_dlmakeresident (handle) - lt_dlhandle handle; -{ - int errors = 0; - - if (!handle) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - ++errors; - } - else - { - LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG); - } - - return errors; -} - -int -lt_dlisresident (handle) - lt_dlhandle handle; -{ - if (!handle) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - return -1; - } - - return LT_DLIS_RESIDENT (handle); -} - - - - -/* --- MODULE INFORMATION --- */ - -const lt_dlinfo * -lt_dlgetinfo (handle) - lt_dlhandle handle; -{ - if (!handle) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - return 0; - } - - return &(handle->info); -} - -lt_dlhandle -lt_dlhandle_next (place) - lt_dlhandle place; -{ - return place ? place->next : handles; -} - -int -lt_dlforeach (func, data) - int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data)); - lt_ptr data; -{ - int errors = 0; - lt_dlhandle cur; - - LT_DLMUTEX_LOCK (); - - cur = handles; - while (cur) - { - lt_dlhandle tmp = cur; - - cur = cur->next; - if ((*func) (tmp, data)) - { - ++errors; - break; - } - } - - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -lt_dlcaller_id -lt_dlcaller_register () -{ - static lt_dlcaller_id last_caller_id = 0; - int result; - - LT_DLMUTEX_LOCK (); - result = ++last_caller_id; - LT_DLMUTEX_UNLOCK (); - - return result; -} - -lt_ptr -lt_dlcaller_set_data (key, handle, data) - lt_dlcaller_id key; - lt_dlhandle handle; - lt_ptr data; -{ - int n_elements = 0; - lt_ptr stale = (lt_ptr) 0; - int i; - - /* This needs to be locked so that the caller data can be updated - simultaneously by different threads. */ - LT_DLMUTEX_LOCK (); - - if (handle->caller_data) - while (handle->caller_data[n_elements].key) - ++n_elements; - - for (i = 0; i < n_elements; ++i) - { - if (handle->caller_data[i].key == key) - { - stale = handle->caller_data[i].data; - break; - } - } - - /* Ensure that there is enough room in this handle's caller_data - array to accept a new element (and an empty end marker). */ - if (i == n_elements) - { - lt_caller_data *temp - = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements); - - if (!temp) - { - stale = 0; - goto done; - } - - handle->caller_data = temp; - - /* We only need this if we needed to allocate a new caller_data. */ - handle->caller_data[i].key = key; - handle->caller_data[1+ i].key = 0; - } - - handle->caller_data[i].data = data; - - done: - LT_DLMUTEX_UNLOCK (); - - return stale; -} - -lt_ptr -lt_dlcaller_get_data (key, handle) - lt_dlcaller_id key; - lt_dlhandle handle; -{ - lt_ptr result = (lt_ptr) 0; - - /* This needs to be locked so that the caller data isn't updated by - another thread part way through this function. */ - LT_DLMUTEX_LOCK (); - - /* Locate the index of the element with a matching KEY. */ - { - int i; - for (i = 0; handle->caller_data[i].key; ++i) - { - if (handle->caller_data[i].key == key) - { - result = handle->caller_data[i].data; - break; - } - } - } - - LT_DLMUTEX_UNLOCK (); - - return result; -} - - - -/* --- USER MODULE LOADER API --- */ - - -int -lt_dlloader_add (place, dlloader, loader_name) - lt_dlloader *place; - const struct lt_user_dlloader *dlloader; - const char *loader_name; -{ - int errors = 0; - lt_dlloader *node = 0, *ptr = 0; - - if ((dlloader == 0) /* diagnose null parameters */ - || (dlloader->module_open == 0) - || (dlloader->module_close == 0) - || (dlloader->find_sym == 0)) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); - return 1; - } - - /* Create a new dlloader node with copies of the user callbacks. */ - node = LT_EMALLOC (lt_dlloader, 1); - if (!node) - return 1; - - node->next = 0; - node->loader_name = loader_name; - node->sym_prefix = dlloader->sym_prefix; - node->dlloader_exit = dlloader->dlloader_exit; - node->module_open = dlloader->module_open; - node->module_close = dlloader->module_close; - node->find_sym = dlloader->find_sym; - node->dlloader_data = dlloader->dlloader_data; - - LT_DLMUTEX_LOCK (); - if (!loaders) - { - /* If there are no loaders, NODE becomes the list! */ - loaders = node; - } - else if (!place) - { - /* If PLACE is not set, add NODE to the end of the - LOADERS list. */ - for (ptr = loaders; ptr->next; ptr = ptr->next) - { - /*NOWORK*/; - } - - ptr->next = node; - } - else if (loaders == place) - { - /* If PLACE is the first loader, NODE goes first. */ - node->next = place; - loaders = node; - } - else - { - /* Find the node immediately preceding PLACE. */ - for (ptr = loaders; ptr->next != place; ptr = ptr->next) - { - /*NOWORK*/; - } - - if (ptr->next != place) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); - ++errors; - } - else - { - /* Insert NODE between PTR and PLACE. */ - node->next = place; - ptr->next = node; - } - } - - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -int -lt_dlloader_remove (loader_name) - const char *loader_name; -{ - lt_dlloader *place = lt_dlloader_find (loader_name); - lt_dlhandle handle; - int errors = 0; - - if (!place) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); - return 1; - } - - LT_DLMUTEX_LOCK (); - - /* Fail if there are any open modules which use this loader. */ - for (handle = handles; handle; handle = handle->next) - { - if (handle->loader == place) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER)); - ++errors; - goto done; - } - } - - if (place == loaders) - { - /* PLACE is the first loader in the list. */ - loaders = loaders->next; - } - else - { - /* Find the loader before the one being removed. */ - lt_dlloader *prev; - for (prev = loaders; prev->next; prev = prev->next) - { - if (!strcmp (prev->next->loader_name, loader_name)) - { - break; - } - } - - place = prev->next; - prev->next = prev->next->next; - } - - if (place->dlloader_exit) - { - errors = place->dlloader_exit (place->dlloader_data); - } - - LT_DLFREE (place); - - done: - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -lt_dlloader * -lt_dlloader_next (place) - lt_dlloader *place; -{ - lt_dlloader *next; - - LT_DLMUTEX_LOCK (); - next = place ? place->next : loaders; - LT_DLMUTEX_UNLOCK (); - - return next; -} - -const char * -lt_dlloader_name (place) - lt_dlloader *place; -{ - const char *name = 0; - - if (place) - { - LT_DLMUTEX_LOCK (); - name = place ? place->loader_name : 0; - LT_DLMUTEX_UNLOCK (); - } - else - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); - } - - return name; -} - -lt_user_data * -lt_dlloader_data (place) - lt_dlloader *place; -{ - lt_user_data *data = 0; - - if (place) - { - LT_DLMUTEX_LOCK (); - data = place ? &(place->dlloader_data) : 0; - LT_DLMUTEX_UNLOCK (); - } - else - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); - } - - return data; -} - -lt_dlloader * -lt_dlloader_find (loader_name) - const char *loader_name; -{ - lt_dlloader *place = 0; - - LT_DLMUTEX_LOCK (); - for (place = loaders; place; place = place->next) - { - if (strcmp (place->loader_name, loader_name) == 0) - { - break; - } - } - LT_DLMUTEX_UNLOCK (); - - return place; -} diff --git a/bochs/ltdlconf.h.in b/bochs/ltdlconf.h.in deleted file mode 100644 index c592adc430..0000000000 --- a/bochs/ltdlconf.h.in +++ /dev/null @@ -1,160 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: ltdlconf.h.in,v 1.2 2002-10-24 21:04:38 bdenney Exp $ -// -// The configure script reads this file and produces ltdlconf.h, which -// tells ltdl.c how to compile. It was copied out of the libtool package -// but appears to have been generated by autoheader. -///////////////////////////////////////////////////////////////////////// - -/* config-h.in. Generated automatically from configure.in by autoheader. */ - -/* Define to empty if the keyword does not work. */ -#undef const - -/* Define as __inline if that's what the C compiler calls it. */ -#undef inline - -/* Define if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define if you have the argz_append function. */ -#undef HAVE_ARGZ_APPEND - -/* Define if you have the argz_create_sep function. */ -#undef HAVE_ARGZ_CREATE_SEP - -/* Define if you have the argz_insert function. */ -#undef HAVE_ARGZ_INSERT - -/* Define if you have the argz_next function. */ -#undef HAVE_ARGZ_NEXT - -/* Define if you have the argz_stringify function. */ -#undef HAVE_ARGZ_STRINGIFY - -/* Define if you have the bcopy function. */ -#undef HAVE_BCOPY - -/* Define if you have the dlerror function. */ -#undef HAVE_DLERROR - -/* Define if you have the index function. */ -#undef HAVE_INDEX - -/* Define if you have the memcpy function. */ -#undef HAVE_MEMCPY - -/* Define if you have the memmove function. */ -#undef HAVE_MEMMOVE - -/* Define if you have the rindex function. */ -#undef HAVE_RINDEX - -/* Define if you have the strchr function. */ -#undef HAVE_STRCHR - -/* Define if you have the strcmp function. */ -#undef HAVE_STRCMP - -/* Define if you have the strrchr function. */ -#undef HAVE_STRRCHR - -/* Define if you have the header file. */ -#undef HAVE_ARGZ_H - -/* Define if you have the header file. */ -#undef HAVE_ASSERT_H - -/* Define if you have the header file. */ -#undef HAVE_CTYPE_H - -/* Define if you have the header file. */ -#undef HAVE_DIRENT_H - -/* Define if you have the header file. */ -#undef HAVE_DL_H - -/* Define if you have the header file. */ -#undef HAVE_DLD_H - -/* Define if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define if you have the header file. */ -#undef HAVE_ERRNO_H - -/* Define if you have the header file. */ -#undef HAVE_MALLOC_H - -/* Define if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define if you have the header file. */ -#undef HAVE_NDIR_H - -/* Define if you have the header file. */ -#undef HAVE_STDIO_H - -/* Define if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define if you have the header file. */ -#undef HAVE_STRING_H - -/* Define if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define if you have the header file. */ -#undef HAVE_SYS_DIR_H - -/* Define if you have the header file. */ -#undef HAVE_SYS_DL_H - -/* Define if you have the header file. */ -#undef HAVE_SYS_NDIR_H - -/* Define if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to the extension used for shared libraries, say, .so. */ -#undef LTDL_SHLIB_EXT - -/* Define to the name of the environment variable that determines the dynamic library search path. */ -#undef LTDL_SHLIBPATH_VAR - -/* Define to the system default library search path. */ -#undef LTDL_SYSSEARCHPATH - -/* Define to the sub-directory in which libtool stores uninstalled libraries. */ -#undef LTDL_OBJDIR - -/* Define if libtool can extract symbol lists from object files. */ -#undef HAVE_PRELOADED_SYMBOLS - -/* Define if you have the libdl library or equivalent. */ -#undef HAVE_LIBDL - -/* Define if you have the libdl library or equivalent. */ -#undef HAVE_LIBDL - -/* Define if you have the libdl library or equivalent. */ -#undef HAVE_LIBDL - -/* Define if you have the shl_load function. */ -#undef HAVE_SHL_LOAD - -/* Define if you have the shl_load function. */ -#undef HAVE_SHL_LOAD - -/* Define if you have the GNU dld library. */ -#undef HAVE_DLD - -/* Define if dlsym() requires a leading underscode in symbol names. */ -#undef NEED_USCORE - -/* Define if the OS needs help to load dependent libraries for dlopen(). */ -#undef LTDL_DLOPEN_DEPLIBS - -/* Define to a type to use for `error_t' if it is not otherwise available. */ -#undef error_t - diff --git a/bochs/main.cc b/bochs/main.cc index 342b5f3e7c..997ec7bea1 100644 --- a/bochs/main.cc +++ b/bochs/main.cc @@ -1331,7 +1331,7 @@ void bx_init_hardware() if (memSize < hostMemSize) hostMemSize = memSize; bx_param_num_c *bxp_memblock_size = SIM->get_param_num(BXPN_MEM_BLOCK_SIZE); - Bit32u memBlockSize = bxp_memblock_size->get64() * 1024; + Bit32u memBlockSize = (Bit32u)(bxp_memblock_size->get64() * 1024); BX_MEM(0)->init_memory(memSize, hostMemSize, memBlockSize); diff --git a/bochs/memory/Makefile.in b/bochs/memory/Makefile.in index f755e9f7c5..19c6fb244c 100644 --- a/bochs/memory/Makefile.in +++ b/bochs/memory/Makefile.in @@ -72,29 +72,32 @@ memory.o: memory.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h ../cpu/cpu.h ../bx_debug/debug.h ../config.h ../osdep.h \ ../cpu/decoder/decoder.h ../cpu/decoder/features.h \ ../cpu/decoder/decoder.h ../instrument/stubs/instrument.h ../cpu/i387.h \ - ../cpu/fpu/softfloat.h ../cpu/fpu/tag_w.h ../cpu/fpu/status_w.h \ - ../cpu/fpu/control_w.h ../cpu/crregs.h ../cpu/descriptor.h \ - ../cpu/decoder/instr.h ../cpu/lazy_flags.h ../cpu/tlb.h ../cpu/icache.h \ - ../cpu/xmm.h ../cpu/vmx.h ../cpu/access.h ../iodev/iodev.h ../plugin.h \ + ../cpu/softfloat3e/include/softfloat_types.h ../cpu/fpu/tag_w.h \ + ../cpu/fpu/status_w.h ../cpu/fpu/control_w.h ../cpu/crregs.h \ + ../cpu/descriptor.h ../cpu/decoder/instr.h ../cpu/lazy_flags.h \ + ../cpu/tlb.h ../cpu/icache.h ../cpu/xmm.h ../cpu/vmx.h \ + ../cpu/vmx_ctrls.h ../cpu/access.h ../iodev/iodev.h ../plugin.h \ ../extplugin.h ../param_names.h ../pc_system.h ../memory/memory-bochs.h \ ../gui/siminterface.h ../gui/paramtree.h ../gui/gui.h memory_stub.o: memory_stub.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../logio.h ../misc/bswap.h ../pc_system.h ../param_names.h ../cpu/cpu.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../cpu/decoder/decoder.h \ ../cpu/decoder/features.h ../cpu/decoder/decoder.h \ - ../instrument/stubs/instrument.h ../cpu/i387.h ../cpu/fpu/softfloat.h \ - ../cpu/fpu/tag_w.h ../cpu/fpu/status_w.h ../cpu/fpu/control_w.h \ - ../cpu/crregs.h ../cpu/descriptor.h ../cpu/decoder/instr.h \ - ../cpu/lazy_flags.h ../cpu/tlb.h ../cpu/icache.h ../cpu/xmm.h \ - ../cpu/vmx.h ../cpu/access.h ../memory/memory-bochs.h + ../instrument/stubs/instrument.h ../cpu/i387.h \ + ../cpu/softfloat3e/include/softfloat_types.h ../cpu/fpu/tag_w.h \ + ../cpu/fpu/status_w.h ../cpu/fpu/control_w.h ../cpu/crregs.h \ + ../cpu/descriptor.h ../cpu/decoder/instr.h ../cpu/lazy_flags.h \ + ../cpu/tlb.h ../cpu/icache.h ../cpu/xmm.h ../cpu/vmx.h \ + ../cpu/vmx_ctrls.h ../cpu/access.h ../memory/memory-bochs.h misc_mem.o: misc_mem.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h ../param_names.h ../cpu/cpu.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../cpu/decoder/decoder.h \ ../cpu/decoder/features.h ../cpu/decoder/decoder.h \ - ../instrument/stubs/instrument.h ../cpu/i387.h ../cpu/fpu/softfloat.h \ - ../cpu/fpu/tag_w.h ../cpu/fpu/status_w.h ../cpu/fpu/control_w.h \ - ../cpu/crregs.h ../cpu/descriptor.h ../cpu/decoder/instr.h \ - ../cpu/lazy_flags.h ../cpu/tlb.h ../cpu/icache.h ../cpu/xmm.h \ - ../cpu/vmx.h ../cpu/access.h ../iodev/iodev.h ../plugin.h ../extplugin.h \ - ../pc_system.h ../memory/memory-bochs.h ../gui/siminterface.h \ - ../gui/paramtree.h ../gui/gui.h + ../instrument/stubs/instrument.h ../cpu/i387.h \ + ../cpu/softfloat3e/include/softfloat_types.h ../cpu/fpu/tag_w.h \ + ../cpu/fpu/status_w.h ../cpu/fpu/control_w.h ../cpu/crregs.h \ + ../cpu/descriptor.h ../cpu/decoder/instr.h ../cpu/lazy_flags.h \ + ../cpu/tlb.h ../cpu/icache.h ../cpu/xmm.h ../cpu/vmx.h \ + ../cpu/vmx_ctrls.h ../cpu/access.h ../iodev/iodev.h ../plugin.h \ + ../extplugin.h ../pc_system.h ../memory/memory-bochs.h \ + ../gui/siminterface.h ../gui/paramtree.h ../gui/gui.h diff --git a/bochs/misc/bswap.h b/bochs/misc/bswap.h index 4b63887607..68581f2b05 100644 --- a/bochs/misc/bswap.h +++ b/bochs/misc/bswap.h @@ -71,7 +71,7 @@ BX_CPP_INLINE void WriteHostDWordToLittleEndian(Bit32u *hostPtr, Bit32u nativeVa BX_CPP_INLINE void WriteHostQWordToLittleEndian(Bit64u *hostPtr, Bit64u nativeVar64) { -#ifdef ANDROID +#ifdef __ANDROID__ // Resolve problems with unaligned access ((Bit8u *)(hostPtr))[0] = (Bit8u) (nativeVar64); ((Bit8u *)(hostPtr))[1] = (Bit8u) ((nativeVar64)>>8); @@ -98,7 +98,7 @@ BX_CPP_INLINE Bit32u ReadHostDWordFromLittleEndian(Bit32u *hostPtr) BX_CPP_INLINE Bit64u ReadHostQWordFromLittleEndian(Bit64u *hostPtr) { -#ifdef ANDROID +#ifdef __ANDROID__ // Resolve problems with unaligned access Bit64u nativeVar64 = ((Bit64u) ((Bit8u *)(hostPtr))[0]) | (((Bit64u) ((Bit8u *)(hostPtr))[1])<<8) | diff --git a/bochs/misc/bximage.cc b/bochs/misc/bximage.cc index aa2078a356..43d7d39b30 100644 --- a/bochs/misc/bximage.cc +++ b/bochs/misc/bximage.cc @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2023 The Bochs Project +// Copyright (C) 2001-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -55,6 +55,8 @@ #define BX_MAX_CYL_BITS 24 // 8 TB +#define SECTOR_SIZE 512 + const int bx_max_hd_megs = (int)(((1 << BX_MAX_CYL_BITS) - 1) * 16.0 * 63.0 / 2048.0); int bximage_func; @@ -773,6 +775,60 @@ int get_image_mode_and_hdsize(const char *filename, const char **image_mode) return hdsize_megs; } +void print_partitiontable(device_image_t *hdimage) +{ + size_t ret = 0; + unsigned int n = 0; + Bit8u data[SECTOR_SIZE]; + + ret = hdimage->lseek(0, SEEK_SET); + if (ret < 0) { + fatal("lseek() to MBR failed"); + } + ret = hdimage->read(data, SECTOR_SIZE); + if (ret != SECTOR_SIZE) { + fatal("failed to read MBR"); + } + + // check bootsector ID, not present = no partition table present + if ((data[0x1FE] != 0x55) && (data[0x1FE] != 0xAA)) { + printf("No partition-table detected.\n\n"); + return; + } + + printf("Partition table\n"); + printf(" boot\t sector start\tsize\ttype\n"); + for (n = 0; n < 4; n++) { + // calculate position of partition record (n) in table + Bit8u *p = &data[0x1BE + (16 * n)]; + Bit8u bootable = p[0x00]; // 0x80 = bootable, 0x00 = not bootable + Bit8u type = p[0x04]; + Bit32u start = *((Bit32u *)&p[0x08]); + Bit32u size = *((Bit32u *)&p[0x0C]); + + if (type > 0) { + // print partition number + printf("%d. ", (n + 1)); + + // print '*' if partition is bootable + if (bootable) printf("*\t "); else printf("\t "); + + // print start of partition in sectors + printf("%12u", start); + + // print size of partition in sectors + size = (size >> 1) / 1024; + if (size > (4 * 1024)) + printf("%6uG\t", (size / 1024)); + else + printf("%6uM\t", size); + + printf("%02X\n", type); + } + } + printf("\n"); +} + int CDECL main(int argc, char *argv[]) { char bochsrc_line[1024], prompt[80], tmpfname[528]; @@ -1005,6 +1061,7 @@ int CDECL main(int argc, char *argv[]) printf("geometry = %d/%d/%d (" FMT_LL "d MB)\n\n", hdimage->cylinders, hdimage->heads, hdimage->spt, hdimage->hd_size >> 20); } + print_partitiontable(hdimage); hdimage->close(); } break; diff --git a/bochs/misc/slirp.conf b/bochs/misc/slirp.conf index 606ef61bcb..3531f37724 100644 --- a/bochs/misc/slirp.conf +++ b/bochs/misc/slirp.conf @@ -3,19 +3,21 @@ # Supported options: # -# RESTRICTED if set to 1, only built-in services are available -# NET base IP address of the virtual network -# MASK netmask of the virtual network -# HOST IP address of the DHCP and TFTP server -# HOSTNAME DHCP client hostname -# DHCPSTART start address of DHCP pool -# DNS IP address of the virtual DNS server -# BOOTFILE boot filename returned by DHCP -# DNSSEARCH comma-separated list of DNS suffixes to search (DHCP extension) -# SMB_EXPORT absolute path to the shared folder (non-Windows SMB support) -# SMB_SRV alternative IP address of the SMB server (default is 10.0.2.4) -# HOSTFWD map guest port to host port for host-to-guest access -# (format: protocol:hostaddr:hostport-guestaddr:guestport) +# RESTRICTED if set to 1, only built-in services are available +# NET base IP address of the virtual network +# MASK netmask of the virtual network +# HOST IP address of the DHCP and TFTP server +# HOSTNAME DHCP client hostname +# DHCPSTART start address of DHCP pool +# DNS IP address of the virtual DNS server +# BOOTFILE boot filename returned by DHCP +# TFTP_SRVNAME optional TFTP server name reported by DHCP +# DNSSEARCH comma-separated list of DNS suffixes to search (DHCP extension) +# SMB_EXPORT absolute path to the shared folder (non-Windows SMB support) +# SMB_SRV alternative IP address of the SMB server (default is 10.0.2.4) +# HOSTFWD map guest port to host port for host-to-guest access +# (format: protocol:hostaddr:hostport-guestaddr:guestport) +# PKTLOG enable packet logging in text format (similar to vnet) # This is the default (classic slirp) setup # restricted = 0 @@ -37,5 +39,18 @@ # Host forwarding example (access guest SSH server from host port 12345) # hostfwd = tcp::12345-:22 -# Enable packet logging in text format (similar to vnet) +# Packet logging example # pktlog = slirp-pktlog.txt + +# IPv6 support (enabled by default using Qemu settings) +# ipv6_enabled = 1 +# ipv6_prefix = fec0:: + +# Enable slirp debugging support if > 0 +# The value can be a combination of these debug levels +# 1 - "call" (function calls and arguments) +# 2 - "misc" (misc debug messages) +# 4 - "error" (normal errors) +# 8 - "tftp" (TFTP messages) +# 16 - "verbose_call" (more function calls) +# debug_switches = 1 diff --git a/bochs/msrs.def b/bochs/msrs.def index 61acf32bcb..33d180730c 100644 --- a/bochs/msrs.def +++ b/bochs/msrs.def @@ -41,5 +41,7 @@ # ADDRESS TYPE RESET_HI RESET_LO RSRVD_HI RSRVD_LO IGNRD_HI IGNRD_LO # --------------------------------------------------------------------------------- + 0x017 0 00000000 00000000 00000000 00000000 00000000 00000000 # IA32_PLATFORM_ID 0x02c 0 00000000 00000000 00000000 00000000 00000000 00000000 - \ No newline at end of file + 0x1b1 0 00000000 00000000 00000000 00000000 00000000 00000000 # IA32_PACKAGE_THERM_STATUS + 0xdb2 0 00000000 00000000 00000000 00000000 00000000 00000000 # IA32_THREAD_STALL diff --git a/bochs/param_names.h b/bochs/param_names.h index 1a96748f32..a00ae05295 100644 --- a/bochs/param_names.h +++ b/bochs/param_names.h @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2009-2023 The Bochs Project +// Copyright (C) 2009-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -164,13 +164,14 @@ #define BXPN_XHCI_ENABLED "ports.usb.xhci.enabled" #define BXPN_XHCI_MODEL "ports.usb.xhci.model" #define BXPN_XHCI_N_PORTS "ports.usb.xhci.n_ports" -#define BXPN_USB_DEBUG_TYPE "usb_debug.type" -#define BXPN_USB_DEBUG_RESET "usb_debug.reset" -#define BXPN_USB_DEBUG_ENABLE "usb_debug.enable" -#define BXPN_USB_DEBUG_START_FRAME "usb_debug.start_frame" -#define BXPN_USB_DEBUG_DOORBELL "usb_debug.doorbell" -#define BXPN_USB_DEBUG_EVENT "usb_debug.event" -#define BXPN_USB_DEBUG_NON_EXIST "usb_debug.non_exist" +#define BXPN_USB_DEBUG "ports.usb_debug" +#define BXPN_USB_DEBUG_TYPE "ports.usb_debug.type" +#define BXPN_USB_DEBUG_RESET "ports.usb_debug.reset" +#define BXPN_USB_DEBUG_ENABLE "ports.usb_debug.enable" +#define BXPN_USB_DEBUG_START_FRAME "ports.usb_debug.start_frame" +#define BXPN_USB_DEBUG_DOORBELL "ports.usb_debug.doorbell" +#define BXPN_USB_DEBUG_EVENT "ports.usb_debug.event" +#define BXPN_USB_DEBUG_NON_EXIST "ports.usb_debug.non_exist" #define BXPN_NE2K "network.ne2k" #define BXPN_PNIC "network.pcipnic" #define BXPN_E1000 "network.e1000" diff --git a/bochs/plugin.cc b/bochs/plugin.cc index 63084a2b95..5666b1bece 100644 --- a/bochs/plugin.cc +++ b/bochs/plugin.cc @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2023 The Bochs Project +// Copyright (C) 2002-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -1090,6 +1090,9 @@ plugin_t bx_builtin_plugins[] = { #if BX_HAVE_SOUND_OSX BUILTIN_SND_PLUGIN_ENTRY(osx), #endif +#if BX_HAVE_SOUND_PULSE + BUILTIN_SND_PLUGIN_ENTRY(pulse), +#endif #if BX_HAVE_SOUND_SDL BUILTIN_SND_PLUGIN_ENTRY(sdl), #endif diff --git a/bochs/plugin.h b/bochs/plugin.h index 268e8e48d8..5c59a6bc25 100644 --- a/bochs/plugin.h +++ b/bochs/plugin.h @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2023 The Bochs Project +// Copyright (C) 2002-2024 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -463,6 +463,7 @@ PLUGIN_ENTRY_FOR_SND_MODULE(dummy); PLUGIN_ENTRY_FOR_SND_MODULE(file); PLUGIN_ENTRY_FOR_SND_MODULE(oss); PLUGIN_ENTRY_FOR_SND_MODULE(osx); +PLUGIN_ENTRY_FOR_SND_MODULE(pulse); PLUGIN_ENTRY_FOR_SND_MODULE(sdl); PLUGIN_ENTRY_FOR_SND_MODULE(win); // network driver plugins diff --git a/bochs/win32res.rc b/bochs/win32res.rc index fd911d847a..f60e099666 100644 --- a/bochs/win32res.rc +++ b/bochs/win32res.rc @@ -100,7 +100,9 @@ BEGIN PUSHBUTTON "Cancel", IDCANCEL, 105, 40, 50, 14 END +#if BX_USB_DEBUGGER #include "win32usbres.rc" +#endif #include "bxversion.rc" #if BX_DEBUGGER_GUI #include "win32_enh_dbg.rc" diff --git a/bochs/win32usbres.rc b/bochs/win32usbres.rc index e6844d485f..3e8945d9f6 100644 --- a/bochs/win32usbres.rc +++ b/bochs/win32usbres.rc @@ -55,7 +55,7 @@ BEGIN ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP, WS_EX_STATICEDGE PUSHBUTTON "&Apply",ID_APPLY,106,212,50,14,WS_DISABLED - EDITTEXT IDC_FRAME_ADDRESS,231,163,58,12,ES_AUTOHSCROLL | + EDITTEXT IDC_FRAME_ADDRESS,241,163,58,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP, WS_EX_STATICEDGE CONTROL "Reset",IDC_DEBUG_RESET,"Button",BS_AUTOCHECKBOX | @@ -84,15 +84,15 @@ BEGIN RTEXT "Port 1",IDC_STATIC,15,173,50,8,WS_TABSTOP RTEXT "Emulation Type",IDC_STATIC,15,159,50,8,WS_TABSTOP RTEXT "Emulation Type",IDC_STATIC,16,187,50,8,WS_TABSTOP - RTEXT "UHCI at Port IO Address",IDC_STATIC,17,15,80,8, + RTEXT "UHCI at Base IO Address",IDC_STATIC,17,15,80,8, WS_TABSTOP EDITTEXT IDC_PORT_ADDR,102,13,58,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_STATICEDGE - RTEXT "Frame at Address",IDC_RING_TYPE,168,166,57,8,WS_TABSTOP + RTEXT "Frame at Address",IDC_RING_TYPE,168,164,67,8,WS_TABSTOP RTEXT "Frame Address",IDC_STATIC,15,101,50,8,WS_TABSTOP EDITTEXT IDC_TREE_COMMENT,168,486,411,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP - PUSHBUTTON "View Item",IDC_VIEW_TD,295,162,50,14,WS_DISABLED + PUSHBUTTON "View Item",IDC_VIEW_TD,305,162,50,14,WS_DISABLED GROUPBOX "Debug Flags",IDC_STATIC,477,30,116,126 END @@ -334,9 +334,9 @@ BEGIN RTEXT "Emulation Type",IDC_X_REG_PORT7_ETYPE,16,383,50,8 RTEXT "Emulation Type",IDC_X_REG_PORT8_ETYPE,16,411,50,8 RTEXT "Emulation Type",IDC_X_REG_PORT9_ETYPE,16,439,50,8 - RTEXT "xHCI at Mem-mapped Address",IDC_STATIC,17,15,80,8, + RTEXT "xHCI at Base MMIO Address",IDC_STATIC,12,15,90,8, WS_TABSTOP - EDITTEXT IDC_PORT_ADDR,102,13,58,12,ES_RIGHT | ES_AUTOHSCROLL | + EDITTEXT IDC_PORT_ADDR,105,13,55,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP, WS_EX_STATICEDGE EDITTEXT IDC_TREE_COMMENT,168,486,411,12,ES_RIGHT | diff --git a/bochs/wxbochs.rc b/bochs/wxbochs.rc index 2974ffabb5..059539d94d 100644 --- a/bochs/wxbochs.rc +++ b/bochs/wxbochs.rc @@ -4,6 +4,9 @@ icon_bochs ICON build/win32/nsis/bochs.ico #if BX_WITH_WIN32 #include "win32res.rc" #else +#if BX_USB_DEBUGGER +#include "win32usbres.rc" +#endif #if BX_DEBUGGER_GUI #include "win32_enh_dbg.rc" #endif