From 17bb5d7efa6ae20a166870921d3d8e87236e4f0a Mon Sep 17 00:00:00 2001 From: geos_one Date: Thu, 14 Aug 2025 09:28:49 +0200 Subject: [PATCH] New upstream version 2.0-0.9 --- .github/FUNDING.yml | 3 - .github/ISSUE_TEMPLATE/bug_report.md | 13 +- .github/workflows/ci-build.yml | 42 +- .github/workflows/ci-manual-asan.yml | 12 - .github/workflows/ci-manual-full.yml | 12 - .github/workflows/ci-manual-normal.yml | 12 - .github/workflows/ci-master.yml | 73 - .gitignore | 39 - .tito/packages/.readme | 3 - .tito/packages/dosemu2 | 1 - .tito/tito.props | 6 - .travis.yml | 2 +- COPYING.DOSEMU | 42 +- INSTALL | 7 +- Makefile | 4 +- Makefile.conf.in | 23 +- README.md | 38 +- THANKS | 11 +- autogen.sh | 10 +- ci_build.sh | 36 +- ci_prereq.sh | 55 +- ci_test.sh | 71 +- ci_test_prereq.sh | 27 - compiletime-settings.devel | 4 +- configure.ac | 348 +- debian/control | 20 +- debian/docs | 1 + debian/rules | 7 +- default-configure | 28 +- doc/README.html | 13 +- doc/tweaks.html | 246 +- dosemu2.spec | 119 - dosemu2.spec.rpkg | 25 +- etc/dosemu.conf | 197 +- etc/global.conf | 114 +- etc/locales.conf | 2 - git-rev.sh | 6 +- install-sh | 323 + m4/m4_ax_prog_cc_for_build.m4 | 155 - man/Makefile | 6 +- man/dosemu.1.in | 47 +- man/dosemu.bin.1.in | 74 +- man/ru/dosemu.1.in | 41 +- man/ru/dosemu.bin.1.in | 109 +- plugin_list | 1 - scripts/aconf.sh | 2 - scripts/buildwithfdpp.sh | 4 +- scripts/config.guess | 1480 ---- scripts/config.sub | 1801 ----- scripts/install-sh | 541 -- scripts/mkpluginhooks | 2 +- scripts/plugctl.sh | 2 +- src/Makefile | 2 +- src/Makefile.common.inc | 1 - src/Makefile.common.post | 69 +- src/arch/linux/Makefile.main | 57 +- src/arch/linux/async/Makefile | 4 +- src/arch/linux/async/backtrace-symbols.c | 2 +- src/arch/linux/async/debug.c | 49 +- src/arch/linux/async/debug.h | 1 - src/arch/linux/async/signal.c | 839 ++- src/arch/linux/async/sigsegv.c | 553 ++ src/{base/lib => arch/linux}/mapping/Makefile | 2 +- src/arch/linux/mapping/mapfile.c | 329 + .../lib => arch/linux}/mapping/mapping.c | 742 +- src/arch/linux/mapping/mapshm.c | 184 + src/base/bios/int10.c | 133 +- src/base/bios/int16.c | 12 +- src/base/bios/pci_bios.c | 15 +- src/base/bios/setup.c | 80 +- src/base/bios/vgabios.c | 52 +- src/base/bios/x86/Makefile | 52 +- src/base/bios/x86/{bios.S => bios.s} | 121 +- src/base/bios/x86/bios_offsets.h | 88 - src/base/core/Makefile | 12 +- src/base/core/coopth.c | 139 +- src/base/core/dump.c | 6 +- src/base/core/emu.c | 65 +- src/base/core/int.c | 312 +- src/base/core/lowmem.c | 27 +- src/base/core/ports.c | 447 +- src/base/core/priv.c | 78 +- src/base/core/vint.c | 181 - src/base/dev/dma/dma.c | 27 +- src/base/dev/dma/dmaregs.h | 14 +- src/base/dev/misc/8042.c | 13 +- src/base/dev/misc/Makefile | 6 +- src/base/dev/misc/chipset.c | 41 +- src/base/dev/misc/cmos.c | 14 +- src/base/dev/misc/joystick.c | 23 +- src/base/dev/misc/kbd.c | 6 +- src/base/dev/misc/lpt.c | 12 +- src/base/dev/misc/pci.c | 33 +- src/base/dev/misc/rtc.c | 49 +- src/base/dev/misc/timers.c | 375 +- src/base/dev/misc/virq.c | 196 - src/base/dev/misc/vtmr.c | 496 -- src/base/dev/ne2k/ne2000.c | 91 +- src/base/dev/pic/Makefile | 10 +- src/base/dev/pic/i8259.c | 359 - src/base/dev/pic/i8259.h | 23 - src/base/dev/pic/i8259_common.c | 76 - src/base/dev/pic/i8259_internal.h | 64 - src/base/dev/pic/irq.c | 32 - src/base/dev/pic/irq.h | 34 - src/base/dev/pic/pic.c | 1152 ++- src/base/dev/sb16/Makefile | 6 +- src/base/dev/sb16/adlib.c | 25 +- src/base/dev/sb16/dbadlib.c | 66 +- src/base/dev/sb16/dspio.c | 161 +- src/base/dev/sb16/dspio.h | 36 +- src/base/dev/sb16/mpu401.c | 205 - src/base/dev/sb16/mpu401.h | 42 - src/base/dev/sb16/mt32.c | 128 - src/base/dev/sb16/opl.c | 6 +- src/base/dev/sb16/sb16.c | 291 +- src/base/dev/sb16/sb16.h | 41 + src/base/dev/sb16/softmpu/Makefile | 13 - src/base/dev/sb16/softmpu/export.h | 58 - src/base/dev/sb16/softmpu/mpu401.c | 638 -- src/base/dev/sb16/softmpu/pic.c | 161 - src/base/dev/vga/attremu.c | 6 +- src/base/dev/vga/crtcemu.c | 9 +- src/base/dev/vga/dacemu.c | 8 +- src/base/dev/vga/gfxemu.c | 6 +- src/base/dev/vga/hercemu.c | 4 +- src/base/dev/vga/miscemu.c | 10 +- src/base/dev/vga/seqemu.c | 6 +- src/base/dev/vga/vesa.c | 25 +- src/base/dev/vga/vesabios.S | 4 +- src/base/dev/vga/vesabios_offsets.h | 4 - src/base/dev/vga/vesabios_pm.S | 2 - src/base/dev/vga/vesabios_pm_offsets.h | 2 - src/base/dev/vga/vgaemu.c | 297 +- src/base/dev/vga/vgaemu_modelist.h | 4 - src/base/dev/vga/vgafonts.c | 2 +- src/base/emu-i386/Makefile | 9 +- src/base/emu-i386/coopth_vm86.c | 74 +- src/base/emu-i386/cpu.c | 175 +- src/base/emu-i386/cputime.c | 143 +- src/base/emu-i386/do_vm86.c | 127 +- src/base/emu-i386/kvm.c | 604 +- src/base/emu-i386/kvmmon.S | 18 - src/base/emu-i386/kvmmon_offsets.h | 3 - src/base/emu-i386/simx86/Makefile | 10 +- src/base/emu-i386/simx86/codegen-arch.h | 1 - src/base/emu-i386/simx86/codegen-sim.c | 168 +- src/base/emu-i386/simx86/codegen-sim.h | 6 + src/base/emu-i386/simx86/codegen-x86.c | 437 +- src/base/emu-i386/simx86/codegen-x86.h | 21 +- src/base/emu-i386/simx86/codegen.h | 20 +- src/base/emu-i386/simx86/cpatch.c | 108 +- src/base/emu-i386/simx86/cpatch.h | 24 +- src/base/emu-i386/simx86/cpu-emu.c | 205 +- src/base/emu-i386/simx86/econfig.h | 10 +- src/base/emu-i386/simx86/emu86.h | 30 +- src/base/emu-i386/simx86/fp87-sim.c | 486 +- src/base/emu-i386/simx86/fp87-x86.c | 12 +- src/base/emu-i386/simx86/host.h | 4 +- src/base/emu-i386/simx86/interp.c | 1302 ++-- src/base/emu-i386/simx86/memory.c | 57 +- src/base/emu-i386/simx86/modrm-gen.c | 2 +- src/base/emu-i386/simx86/modrm-sim.c | 6 +- src/base/emu-i386/simx86/protmode.c | 20 +- src/base/emu-i386/simx86/protmode.h | 6 +- src/base/emu-i386/simx86/sigsegv.c | 112 +- src/base/emu-i386/simx86/softfloat/Makefile | 13 - .../simx86/softfloat/softfloat-macros.h | 606 -- .../simx86/softfloat/softfloat-specialize.h | 993 --- .../emu-i386/simx86/softfloat/softfloat.c | 6384 ----------------- .../emu-i386/simx86/softfloat/softfloat.h | 611 -- src/base/emu-i386/simx86/syncpu.h | 29 +- src/base/emu-i386/simx86/tables.c | 2 +- src/base/emu-i386/simx86/trees.c | 181 +- src/base/init/Makefile | 4 + src/base/init/config.c | 405 +- src/base/init/dev_list.c | 20 +- src/base/init/init.c | 238 +- src/base/init/lexer.l | 26 +- src/base/init/memcheck.c | 52 +- src/base/init/parser.y | 228 +- src/base/kbd_unicode/getfd.c | 2 +- src/base/kbd_unicode/keyb_clients.c | 13 +- src/base/kbd_unicode/keyb_none.c | 51 +- src/base/kbd_unicode/keyb_raw.c | 24 +- src/base/kbd_unicode/keymaps.c | 2 +- src/base/kbd_unicode/prestroke.c | 15 +- src/base/kbd_unicode/serv_backend.c | 2 +- src/base/kbd_unicode/serv_xlat.c | 27 +- src/base/lib/libpcl/pcl.h | 13 +- src/base/lib/libpcl/pcl_ctx.c | 8 - src/base/lib/libpcl/pcl_private.h | 2 +- src/base/lib/mapping/mapashm.c | 141 - src/base/lib/mapping/mapfile.c | 345 - src/base/lib/mcontext/Makefile | 4 +- src/base/lib/mcontext/aarch64-ucontext.h | 37 - src/base/lib/mcontext/arm-ucontext.h | 4 - src/base/lib/mcontext/asm.S | 110 + src/base/lib/mcontext/asm.SS | 464 -- src/base/lib/mcontext/context.c | 14 - src/base/lib/mcontext/mcontext.h | 9 +- src/base/lib/mcontext/mips-ucontext.h | 77 - src/base/lib/mcontext/power-ucontext.h | 37 - src/base/lib/misc/Makefile | 3 +- src/base/lib/misc/dlmalloc.c | 34 +- src/base/lib/misc/pgalloc.c | 154 - src/base/lib/misc/sequencr.c | 168 - src/base/lib/misc/shlock.c | 250 - src/base/lib/misc/smalloc.c | 253 +- src/base/lib/misc/spscq.c | 111 - src/base/lib/timer/Makefile | 10 - src/base/lib/timer/evtimer.c | 186 - src/base/lib/timer/evtimer_fd.c | 286 - src/base/lib/translate/Makefile | 4 +- src/base/lib/translate/dosemu_charset.c | 4 +- src/base/lib/translate/translate.c | 1 - src/base/lib/translate/translate_config.c | 2 +- src/base/lib/translate/unicode_utils.c | 6 +- src/base/misc/Makefile | 3 +- src/base/misc/clipboard.c | 175 - src/base/misc/disks.c | 785 +- src/base/misc/dos2linux.c | 594 +- src/base/misc/fatfs.c | 19 +- src/base/misc/fatfs.h | 1 - src/base/misc/hma.c | 62 +- src/base/misc/ioctl.c | 252 +- src/base/misc/utilities.c | 383 +- src/base/mouse/mouse.c | 167 +- src/base/mouse/mousedrv.c | 216 +- src/base/mouse/mouseint.c | 4 +- src/base/serial/Makefile | 2 +- src/base/serial/commouse.c | 32 +- src/base/serial/comredir.c | 253 - src/base/serial/comredir.h | 8 - src/base/serial/fossil.c | 80 +- src/base/serial/int14.c | 32 +- src/base/serial/nullmm.c | 137 - src/base/serial/nullmm.h | 6 - src/base/serial/ser_defs.h | 53 +- src/base/serial/ser_init.c | 47 +- src/base/serial/ser_irq.c | 65 +- src/base/serial/ser_ports.c | 28 +- src/base/serial/sermouse.c | 84 +- src/base/serial/tty_io.c | 450 +- src/base/sound/midi.c | 58 +- src/base/sound/sndpcm.c | 19 +- src/base/speaker/console_speaker.c | 2 +- src/base/speaker/speaker.c | 17 +- src/base/video/instremu.c | 1965 ++++- src/base/video/render.c | 32 +- src/base/video/text.c | 205 +- src/base/video/video.c | 47 +- src/bindist/bat/dosrc.d/3uhook.bat | 2 - src/bindist/bat/dosrc.d/7mouse.bat | 2 + src/bindist/bat/exechlp.bat | 7 +- src/bindist/fdautoem.bat | 2 - src/bindist/fdppauto.bat | 5 +- src/bindist/fdppconf.sys | 11 +- src/doc/HOWTO/tweaks.sgml | 80 - src/doc/README/Makefile | 6 +- src/doc/README/Windows | 13 +- src/doc/tools/doSgmlTools.pl | 2 +- src/dosemu | 91 +- src/dosemu.systemwide | 2 +- src/dosext/builtins/Makefile | 4 +- src/dosext/builtins/blaster.c | 16 +- src/dosext/builtins/builtins.c | 6 +- src/dosext/builtins/commands.c | 62 +- src/dosext/builtins/{emuconf.c => dosdbg.c} | 41 +- src/dosext/builtins/{emuconf.h => dosdbg.h} | 0 src/dosext/builtins/emumouse.c | 137 +- src/dosext/builtins/fossil.c | 54 - src/dosext/builtins/fossil.h | 8 - src/dosext/builtins/lredir.c | 6 +- src/dosext/builtins/msetenv.c | 6 +- src/dosext/builtins/system.c | 62 +- src/dosext/builtins/system.h | 2 +- src/dosext/builtins/unix.c | 22 +- src/dosext/builtins/xmode.c | 34 +- src/dosext/dpmi/Makefile | 5 +- src/dosext/dpmi/coopth_pm.c | 24 +- src/dosext/dpmi/coopth_pm.h | 6 +- src/dosext/dpmi/djdpmi.h | 127 - src/dosext/dpmi/dmemory.h | 32 +- src/dosext/dpmi/dnative.c | 245 + src/dosext/dpmi/dnative.h | 11 + src/dosext/dpmi/dnative/Makefile | 11 - src/dosext/dpmi/dnative/dnative.c | 315 - src/dosext/dpmi/dnative/dnative.h | 53 - src/dosext/dpmi/dnative/sigsegv.c | 1179 --- src/dosext/dpmi/doslib/Makefile | 6 - src/dosext/dpmi/doslib/dos.c | 172 - src/dosext/dpmi/doslib/dos.h | 12 - src/dosext/dpmi/doslib/dpmi.h | 149 - src/dosext/dpmi/dpmi.c | 2544 +++---- src/dosext/dpmi/dpmi_api.c | 568 +- src/dosext/dpmi/dpmi_api.h | 167 +- src/dosext/dpmi/dpmisel.S | 127 +- src/dosext/dpmi/dpmisel.h | 78 +- src/dosext/dpmi/dpmisel_offsets.h | 74 - src/dosext/dpmi/emu-ldt.c | 12 +- src/dosext/dpmi/emudpmi.h | 108 +- src/dosext/dpmi/memory.c | 602 +- src/dosext/dpmi/msdos/Makefile | 5 +- src/dosext/dpmi/msdos/callbacks.c | 24 +- src/dosext/dpmi/msdos/callbacks.h | 8 +- src/dosext/dpmi/msdos/emm.c | 12 +- src/dosext/dpmi/msdos/emm_msdos.h | 14 +- src/dosext/dpmi/msdos/hlpmisc.c | 11 - src/dosext/dpmi/msdos/hlpmisc.h | 15 +- src/dosext/dpmi/msdos/instr_dec.c | 460 +- src/dosext/dpmi/msdos/instr_dec.h | 9 +- src/dosext/dpmi/msdos/lio.c | 36 +- src/dosext/dpmi/msdos/lio.h | 8 +- src/dosext/dpmi/msdos/msdos.c | 356 +- src/dosext/dpmi/msdos/msdos.h | 6 +- src/dosext/dpmi/msdos/msdos_ldt.c | 43 +- src/dosext/dpmi/msdos/msdos_ldt.h | 10 +- src/dosext/dpmi/msdos/msdos_priv.h | 6 +- src/dosext/dpmi/msdos/segreg.c | 24 +- src/dosext/dpmi/msdos/segreg_priv.h | 4 +- src/dosext/dpmi/msdos/xms.c | 133 +- src/dosext/dpmi/msdoshlp.c | 160 +- src/dosext/dpmi/msdoshlp.h | 36 +- src/dosext/dpmi/stub/dpmi.h | 360 + src/dosext/dpmi/vxd.c | 8 +- src/dosext/dpmi/vxd.h | 4 +- src/dosext/dpmi/windefs.h | 2 +- src/dosext/drivers/aspi.c | 4 +- src/dosext/drivers/cdrom.c | 8 +- src/dosext/mfs/Makefile | 10 +- src/dosext/mfs/lfn.c | 78 +- src/dosext/mfs/lfn.h | 1 - src/dosext/mfs/mangle.c | 30 +- src/dosext/mfs/mangle.h | 1 + src/dosext/mfs/mfs.c | 1046 ++- src/dosext/mfs/mfs.h | 81 +- src/dosext/mfs/mscdex.c | 26 +- src/dosext/mfs/rlocks.c | 216 - src/dosext/mfs/rlocks.h | 76 - src/dosext/mfs/share.c | 514 -- src/dosext/mfs/share.h | 30 - src/dosext/mfs/util.c | 27 +- src/dosext/mfs/xattr.c | 137 - src/dosext/mfs/xattr.h | 56 - src/dosext/misc/emm.c | 2 +- src/dosext/misc/xms.c | 359 +- src/dosext/net/Makefile | 2 +- src/dosext/net/ipx.c | 177 +- src/dosext/net/ipx_wrp.h | 2 - src/dosext/net/ipxglt.c | 8 +- src/dosext/net/libpacket.c | 216 +- src/dosext/net/pktnew.c | 78 +- src/include/Asm/ldt.h | 4 + src/include/Asm/processor-flags.h | 168 - src/include/Linux/const.h | 36 - src/include/Linux/kd.h | 190 - src/include/Linux/magic.h | 107 - src/include/Sys/kd.h | 34 - src/include/bios.h | 5 +- src/include/bitops.h | 139 +- src/include/chipset.h | 6 - src/include/clipboard.h | 34 - src/include/cmos.h | 6 +- src/include/coopth.h | 28 +- src/include/coopth_be.h | 3 +- src/include/coopth_pm.h | 16 - src/include/cpu-emu.h | 50 +- src/include/cpu.h | 461 +- src/include/disks.h | 69 +- src/include/dlmalloc.h | 8 +- src/include/dnative.h | 16 - src/include/dos.h | 16 - src/include/dos2linux.h | 158 +- src/include/dosemu_config.h | 38 +- src/include/dosemu_debug.h | 2 - src/include/doshelpers.h | 6 +- src/include/dpmi.h | 16 - src/include/emm.h | 14 +- src/include/emu-ldt.h | 9 + src/include/emu.h | 91 +- src/include/emudpmi.h | 14 +- src/include/evtimer.h | 20 - src/include/fls.h | 43 - src/include/generic-non-atomic.h | 171 - src/include/hma.h | 2 + src/include/instremu.h | 11 +- src/include/int.h | 4 +- src/include/iodev.h | 21 +- src/include/ioselect.h | 21 - src/include/ipx.h | 2 + src/include/joystick.h | 13 - src/include/keyboard/keyb_clients.h | 1 - src/include/keyboard/keyb_server.h | 5 +- src/include/keyboard/keyboard.h | 1 - src/include/kvm.h | 30 +- src/include/lowmem.h | 14 +- src/include/mapping.h | 53 +- src/include/memory.h | 38 +- src/include/mhpdbg.h | 15 +- src/include/mouse.h | 31 +- src/include/msdoshlp.h | 16 - src/include/ne2000.h | 1 + src/include/pci.h | 1 - src/include/pgalloc.h | 17 - src/include/pic.h | 102 +- src/include/pktdrvr.h | 18 +- src/include/port.h | 98 +- src/include/priv.h | 1 + src/include/ringbuf.h | 3 - src/include/sequencr.h | 16 - src/include/serial.h | 9 +- src/include/shlock.h | 7 - src/include/sig.h | 189 +- src/include/smalloc.h | 22 +- src/include/sound/midi.h | 2 +- src/include/sound/oplplug.h | 3 +- src/include/sound/sound.h | 5 +- src/include/spscq.h | 10 - src/include/timers.h | 32 +- src/include/translate/translate.h | 2 + src/include/utilities.h | 73 +- src/include/vgaemu.h | 30 +- src/include/vgatext.h | 3 +- src/include/video.h | 8 +- src/include/vint.h | 13 - src/include/virq.h | 16 - src/include/vm86_compat.h | 39 +- src/include/vtmr.h | 27 - src/include/xms.h | 25 +- src/plugin/X/Makefile | 8 +- src/plugin/X/X.c | 102 +- src/plugin/X/X.h | 2 + src/plugin/X/X_speaker.c | 4 +- src/plugin/X/configure.ac | 8 +- src/plugin/X/keyb_X.c | 5 +- src/plugin/Xkmaps/Makefile | 8 +- src/plugin/Xkmaps/X_keymaps.c | 1 - src/plugin/Xkmaps/X_keysyms.c | 5 +- src/plugin/Xkmaps/configure.ac | 4 +- src/plugin/alsa/Makefile | 6 +- src/plugin/alsa/configure.ac | 4 +- src/plugin/alsa/m4/alsa.m4 | 143 + src/plugin/alsa/mid_o_alsa.c | 29 +- src/plugin/alsa/snd_i_alsa.c | 5 +- src/plugin/charsets/GB2312.c | 1 - src/plugin/charsets/JIS0201.c | 1 - src/plugin/charsets/JIS0208.c | 1 - src/plugin/charsets/KSX1001.c | 1 - src/plugin/charsets/ascii.c | 1 - src/plugin/charsets/cp437.c | 1 - src/plugin/charsets/cp850.c | 1 - src/plugin/charsets/cp852.c | 1 - src/plugin/charsets/ibm_ascii.c | 1 - src/plugin/charsets/iso2022.c | 1 - src/plugin/charsets/iso8859-1.c | 1 - src/plugin/charsets/iso8859-2.c | 1 - src/plugin/charsets/iso8859-3.c | 1 - src/plugin/charsets/iso8859-4.c | 1 - src/plugin/charsets/iso8859-5.c | 1 - src/plugin/charsets/iso8859-6.c | 1 - src/plugin/charsets/iso8859-7.c | 1 - src/plugin/charsets/iso8859-8.c | 1 - src/plugin/charsets/iso8859-9.c | 1 - src/plugin/charsets/multibyte.c | 1 - src/plugin/charsets/utf8.c | 1 - src/plugin/charsets/vt100.c | 1 - src/plugin/console/Makefile | 6 +- src/plugin/console/console.c | 6 +- src/plugin/console/detach.c | 2 +- src/plugin/console/vbe.c | 4 + src/plugin/console/vc.c | 12 +- src/plugin/console/vga.c | 12 +- src/plugin/debugger/Makefile | 10 +- src/plugin/debugger/configure.ac | 11 - .../lib/misc => plugin/debugger}/dis8086.c | 7 +- src/plugin/debugger/dosdebug.c | 37 +- src/plugin/debugger/mhpdbg.c | 37 +- src/plugin/debugger/mhpdbgc.c | 290 +- src/plugin/dj64/Makefile | 22 - src/plugin/dj64/Makefile.conf.in | 10 - src/plugin/dj64/coff.c | 172 - src/plugin/dj64/coff.h | 8 - src/plugin/dj64/config/plugin_config.h | 15 - src/plugin/dj64/configure.ac | 6 - src/plugin/dj64/djdev64.c | 319 - src/plugin/dj64/elf.c | 158 - src/plugin/dj64/elf.h | 750 -- src/plugin/dj64/elfp.h | 8 - src/plugin/dj64/stub.c | 270 - src/plugin/dj64/stub.h | 13 - src/plugin/dj64/stub_ex.h | 7 - src/plugin/dj64/stubinfo.h | 63 - src/plugin/dj64/util.c | 45 - src/plugin/dj64/util.h | 14 - src/plugin/doscmd/Makefile | 8 +- src/plugin/dosdrv/Makefile | 8 +- src/plugin/dosdrv/ems.s | 2 +- src/plugin/dosdrv/fossil.s | 102 + src/plugin/dosdrv/xms.inc | 26 +- src/plugin/extra_charsets/bg-mik.c | 1 - src/plugin/extra_charsets/cp1125.c | 1 - src/plugin/extra_charsets/cp1251.c | 1 - src/plugin/extra_charsets/cp737.c | 1 - src/plugin/extra_charsets/cp773.c | 1 - src/plugin/extra_charsets/cp775.c | 1 - src/plugin/extra_charsets/cp855.c | 1 - src/plugin/extra_charsets/cp857.c | 1 - src/plugin/extra_charsets/cp858.c | 1 - src/plugin/extra_charsets/cp860.c | 1 - src/plugin/extra_charsets/cp861.c | 1 - src/plugin/extra_charsets/cp862.c | 1 - src/plugin/extra_charsets/cp863.c | 1 - src/plugin/extra_charsets/cp864.c | 1 - src/plugin/extra_charsets/cp865.c | 1 - src/plugin/extra_charsets/cp866.c | 1 - src/plugin/extra_charsets/cp869.c | 1 - src/plugin/extra_charsets/cp874.c | 1 - src/plugin/extra_charsets/cp895.c | 1 - src/plugin/extra_charsets/iso8859-10.c | 1 - src/plugin/extra_charsets/iso8859-13.c | 1 - src/plugin/extra_charsets/iso8859-14.c | 1 - src/plugin/extra_charsets/iso8859-15.c | 1 - src/plugin/extra_charsets/koi8-r.c | 1 - src/plugin/extra_charsets/koi8-ru.c | 1 - src/plugin/extra_charsets/koi8-u.c | 1 - src/plugin/extra_charsets/mazovia.c | 1 - src/plugin/fdpp/Makefile | 8 +- src/plugin/fdpp/Makefile.conf.in | 17 +- src/plugin/fdpp/boot.c | 62 +- src/plugin/fdpp/boot.h | 7 +- src/plugin/fdpp/configure.ac | 66 +- src/plugin/fdpp/fdpp.c | 31 +- src/plugin/fdpp/hooks.c | 125 +- src/plugin/fdpp/hooks.h | 2 - src/plugin/fluidsynth/Makefile | 8 +- src/plugin/fluidsynth/configure.ac | 7 + src/plugin/fluidsynth/mid_o_flus.c | 64 +- src/plugin/gpm/Makefile | 6 +- src/plugin/gpm/configure.ac | 1 + src/plugin/gpm/mouse_gpm.c | 9 +- src/plugin/ieee1284/Makefile | 6 +- src/plugin/ieee1284/configure.ac | 1 + src/plugin/ieee1284/opl2lpt.c | 3 +- src/plugin/json/Makefile | 6 +- src/plugin/json/configure.ac | 2 + src/plugin/json/locale.c | 3 +- src/plugin/ladspa/Makefile | 6 +- src/plugin/libao/Makefile | 6 +- src/plugin/libao/configure.ac | 4 +- src/plugin/libao/m4/ao.m4 | 108 + src/plugin/libao/snd_o_ao.c | 4 - src/plugin/midimisc/Makefile | 16 +- src/plugin/midimisc/fluid_midi.c | 4 +- src/plugin/midimisc/mid_i_pipe.c | 12 +- src/plugin/midimisc/mid_o_pipe.c | 6 +- src/plugin/midimisc/mid_o_tmdty.c | 6 +- src/plugin/modemu/atcmd.c | 8 +- src/plugin/modemu/modemu.c | 7 +- src/plugin/modemu/sock.c | 2 +- src/plugin/modemu/sock.h | 2 +- src/plugin/modemu/telopt.c | 2 +- src/plugin/munt/Makefile | 6 +- src/plugin/munt/configure.ac | 1 + src/plugin/munt/munt.c | 11 +- src/plugin/periph/Makefile | 25 +- src/plugin/periph/{bootnorm.S => bootnorm.s} | 124 +- src/plugin/periph/bootnorm_offsets.h | 1 - src/plugin/periph/{bootsect.S => bootsect.s} | 4 +- src/plugin/periph/bootsect_offsets.h | 1 - src/plugin/periph/dexeconfig.c | 5 +- src/plugin/periph/mkfatimage16.c | 13 +- src/plugin/plugins.mak | 4 +- src/plugin/sdl/Makefile | 8 +- src/plugin/sdl/acinclude.m4 | 181 + src/plugin/sdl/clip_SDL.c | 176 - src/plugin/sdl/clip_SDL.h | 4 - src/plugin/sdl/configure.ac | 21 +- src/plugin/sdl/keyb_SDL.c | 18 +- src/plugin/sdl/keyb_SDL.h | 14 +- src/plugin/sdl/m4/sdl2.m4 | 202 + src/plugin/sdl/sdl.c | 268 +- src/plugin/sdl/sdl.h | 14 +- src/plugin/sdl1/Makefile | 6 +- src/plugin/sdl1/configure.ac | 4 +- src/plugin/sdl1/m4/sdl.m4 | 185 + src/plugin/sdl1/sdl.c | 4 +- src/plugin/slirp/Makefile | 6 +- src/plugin/slirp/configure.ac | 1 + src/plugin/slirp/slirp.c | 3 +- src/plugin/svgalib/Makefile | 6 +- src/plugin/svgalib/configure.ac | 1 + src/plugin/term/Makefile | 8 +- src/plugin/term/Makefile.conf.in | 2 +- src/plugin/term/clip_term.c | 95 - src/plugin/term/configure.ac | 6 +- src/plugin/term/keyb_slang.c | 59 +- src/plugin/term/mouse_xterm.c | 2 +- src/plugin/term/terminal.c | 11 +- src/plugin/vde/Makefile | 6 +- src/plugin/vde/configure.ac | 1 + src/plugin/vde/vde.c | 14 +- test/common_framework.py | 214 +- test/cpu/Makefile | 24 +- test/cpu/reffile.log | 4493 ------------ test/cpu/test-i386-code16.S | 4 - test/cpu/test-i386-shift.h | 13 +- test/cpu/test-i386-vm86.S | 4 - test/cpu/test-i386.c | 8 +- test/dosemu_tap_interface.sh | 27 - test/ecm/dpmitest/Makefile | 2 +- test/func_cpu_trap_flag.py | 91 +- test/func_ds2_file_seek_read.py | 189 +- test/func_ds2_file_seek_tell.py | 165 +- test/func_ds3_file_access.py | 2 +- test/func_ds3_lock_two_handles.py | 175 +- test/func_ds3_share_open_access.py | 104 +- test/func_ds3_share_open_twice.py | 269 +- test/func_label_create.py | 676 -- test/func_lfn_voln_info.py | 75 - test/func_lfs_disk_info.py | 144 - test/func_lfs_file_info.py | 14 +- test/func_libi86_testsuite.py | 75 - test/func_memory_dpmi_dpmi10_ldt.py | 159 - test/func_memory_dpmi_japheth.py | 158 - test/func_memory_dpmi_leak_check.py | 89 - test/func_memory_dpmi_leak_check_dos.py | 88 - test/func_memory_hma.py | 601 -- test/func_memory_uma.py | 164 - test/func_memory_xms.py | 216 - test/func_mfs_truename.py | 176 +- test/func_network.py | 88 - test/func_pit_mode_2.py | 138 - test/test_dos.py | 3021 ++++---- 634 files changed, 19105 insertions(+), 52303 deletions(-) delete mode 100644 .github/FUNDING.yml delete mode 100644 .github/workflows/ci-manual-asan.yml delete mode 100644 .github/workflows/ci-manual-full.yml delete mode 100644 .github/workflows/ci-manual-normal.yml delete mode 100644 .github/workflows/ci-master.yml delete mode 100644 .gitignore delete mode 100644 .tito/packages/.readme delete mode 100644 .tito/packages/dosemu2 delete mode 100644 .tito/tito.props delete mode 100755 ci_test_prereq.sh delete mode 100644 dosemu2.spec create mode 100755 install-sh delete mode 100644 m4/m4_ax_prog_cc_for_build.m4 delete mode 100755 scripts/config.guess delete mode 100755 scripts/config.sub delete mode 100755 scripts/install-sh create mode 100644 src/arch/linux/async/sigsegv.c rename src/{base/lib => arch/linux}/mapping/Makefile (94%) create mode 100644 src/arch/linux/mapping/mapfile.c rename src/{base/lib => arch/linux}/mapping/mapping.c (59%) create mode 100644 src/arch/linux/mapping/mapshm.c rename src/base/bios/x86/{bios.S => bios.s} (94%) delete mode 100644 src/base/bios/x86/bios_offsets.h delete mode 100644 src/base/core/vint.c delete mode 100644 src/base/dev/misc/virq.c delete mode 100644 src/base/dev/misc/vtmr.c delete mode 100644 src/base/dev/pic/i8259.c delete mode 100644 src/base/dev/pic/i8259.h delete mode 100644 src/base/dev/pic/i8259_common.c delete mode 100644 src/base/dev/pic/i8259_internal.h delete mode 100644 src/base/dev/pic/irq.c delete mode 100644 src/base/dev/pic/irq.h delete mode 100644 src/base/dev/sb16/mpu401.c delete mode 100644 src/base/dev/sb16/mpu401.h delete mode 100644 src/base/dev/sb16/mt32.c delete mode 100644 src/base/dev/sb16/softmpu/Makefile delete mode 100644 src/base/dev/sb16/softmpu/export.h delete mode 100644 src/base/dev/sb16/softmpu/mpu401.c delete mode 100644 src/base/dev/sb16/softmpu/pic.c delete mode 100644 src/base/dev/vga/vesabios_offsets.h delete mode 100644 src/base/dev/vga/vesabios_pm_offsets.h delete mode 100644 src/base/emu-i386/kvmmon_offsets.h delete mode 100644 src/base/emu-i386/simx86/softfloat/Makefile delete mode 100644 src/base/emu-i386/simx86/softfloat/softfloat-macros.h delete mode 100644 src/base/emu-i386/simx86/softfloat/softfloat-specialize.h delete mode 100644 src/base/emu-i386/simx86/softfloat/softfloat.c delete mode 100644 src/base/emu-i386/simx86/softfloat/softfloat.h delete mode 100644 src/base/lib/mapping/mapashm.c delete mode 100644 src/base/lib/mapping/mapfile.c delete mode 100644 src/base/lib/mcontext/aarch64-ucontext.h delete mode 100644 src/base/lib/mcontext/arm-ucontext.h create mode 100644 src/base/lib/mcontext/asm.S delete mode 100644 src/base/lib/mcontext/asm.SS delete mode 100644 src/base/lib/mcontext/mips-ucontext.h delete mode 100644 src/base/lib/mcontext/power-ucontext.h delete mode 100644 src/base/lib/misc/pgalloc.c delete mode 100644 src/base/lib/misc/sequencr.c delete mode 100644 src/base/lib/misc/shlock.c delete mode 100644 src/base/lib/misc/spscq.c delete mode 100644 src/base/lib/timer/Makefile delete mode 100644 src/base/lib/timer/evtimer.c delete mode 100644 src/base/lib/timer/evtimer_fd.c delete mode 100644 src/base/misc/clipboard.c delete mode 100644 src/base/serial/comredir.c delete mode 100644 src/base/serial/comredir.h delete mode 100644 src/base/serial/nullmm.c delete mode 100644 src/base/serial/nullmm.h delete mode 100644 src/bindist/bat/dosrc.d/3uhook.bat create mode 100644 src/bindist/bat/dosrc.d/7mouse.bat rename src/dosext/builtins/{emuconf.c => dosdbg.c} (72%) rename src/dosext/builtins/{emuconf.h => dosdbg.h} (100%) delete mode 100644 src/dosext/builtins/fossil.c delete mode 100644 src/dosext/builtins/fossil.h delete mode 100644 src/dosext/dpmi/djdpmi.h create mode 100644 src/dosext/dpmi/dnative.c create mode 100644 src/dosext/dpmi/dnative.h delete mode 100644 src/dosext/dpmi/dnative/Makefile delete mode 100644 src/dosext/dpmi/dnative/dnative.c delete mode 100644 src/dosext/dpmi/dnative/dnative.h delete mode 100644 src/dosext/dpmi/dnative/sigsegv.c delete mode 100644 src/dosext/dpmi/doslib/Makefile delete mode 100644 src/dosext/dpmi/doslib/dos.c delete mode 100644 src/dosext/dpmi/doslib/dos.h delete mode 100644 src/dosext/dpmi/doslib/dpmi.h delete mode 100644 src/dosext/dpmi/dpmisel_offsets.h delete mode 100644 src/dosext/dpmi/msdos/hlpmisc.c create mode 100644 src/dosext/dpmi/stub/dpmi.h delete mode 100644 src/dosext/mfs/rlocks.c delete mode 100644 src/dosext/mfs/rlocks.h delete mode 100644 src/dosext/mfs/share.c delete mode 100644 src/dosext/mfs/share.h delete mode 100644 src/dosext/mfs/xattr.c delete mode 100644 src/dosext/mfs/xattr.h delete mode 100644 src/include/Asm/processor-flags.h delete mode 100644 src/include/Linux/const.h delete mode 100644 src/include/Linux/kd.h delete mode 100644 src/include/Linux/magic.h delete mode 100644 src/include/Sys/kd.h delete mode 100644 src/include/clipboard.h delete mode 100644 src/include/coopth_pm.h delete mode 100644 src/include/dnative.h delete mode 100644 src/include/dos.h delete mode 100644 src/include/dpmi.h delete mode 100644 src/include/evtimer.h delete mode 100644 src/include/fls.h delete mode 100644 src/include/generic-non-atomic.h delete mode 100644 src/include/ioselect.h delete mode 100644 src/include/msdoshlp.h delete mode 100644 src/include/pgalloc.h delete mode 100644 src/include/sequencr.h delete mode 100644 src/include/shlock.h delete mode 100644 src/include/spscq.h delete mode 100644 src/include/vint.h delete mode 100644 src/include/virq.h delete mode 100644 src/include/vtmr.h create mode 100644 src/plugin/alsa/m4/alsa.m4 rename src/{base/lib/misc => plugin/debugger}/dis8086.c (99%) delete mode 100644 src/plugin/dj64/Makefile delete mode 100644 src/plugin/dj64/Makefile.conf.in delete mode 100644 src/plugin/dj64/coff.c delete mode 100644 src/plugin/dj64/coff.h delete mode 100644 src/plugin/dj64/config/plugin_config.h delete mode 100644 src/plugin/dj64/configure.ac delete mode 100644 src/plugin/dj64/djdev64.c delete mode 100644 src/plugin/dj64/elf.c delete mode 100644 src/plugin/dj64/elf.h delete mode 100644 src/plugin/dj64/elfp.h delete mode 100644 src/plugin/dj64/stub.c delete mode 100644 src/plugin/dj64/stub.h delete mode 100644 src/plugin/dj64/stub_ex.h delete mode 100644 src/plugin/dj64/stubinfo.h delete mode 100644 src/plugin/dj64/util.c delete mode 100644 src/plugin/dj64/util.h create mode 100644 src/plugin/dosdrv/fossil.s create mode 100644 src/plugin/libao/m4/ao.m4 rename src/plugin/periph/{bootnorm.S => bootnorm.s} (56%) delete mode 100644 src/plugin/periph/bootnorm_offsets.h rename src/plugin/periph/{bootsect.S => bootsect.s} (98%) delete mode 100644 src/plugin/periph/bootsect_offsets.h create mode 100644 src/plugin/sdl/acinclude.m4 delete mode 100644 src/plugin/sdl/clip_SDL.c delete mode 100644 src/plugin/sdl/clip_SDL.h create mode 100644 src/plugin/sdl/m4/sdl2.m4 create mode 100644 src/plugin/sdl1/m4/sdl.m4 delete mode 100644 src/plugin/term/clip_term.c delete mode 100644 test/cpu/reffile.log delete mode 100755 test/dosemu_tap_interface.sh delete mode 100644 test/func_label_create.py delete mode 100644 test/func_lfn_voln_info.py delete mode 100644 test/func_lfs_disk_info.py delete mode 100644 test/func_libi86_testsuite.py delete mode 100644 test/func_memory_dpmi_dpmi10_ldt.py delete mode 100644 test/func_memory_dpmi_japheth.py delete mode 100644 test/func_memory_dpmi_leak_check.py delete mode 100644 test/func_memory_dpmi_leak_check_dos.py delete mode 100644 test/func_memory_hma.py delete mode 100644 test/func_memory_uma.py delete mode 100644 test/func_memory_xms.py delete mode 100644 test/func_network.py delete mode 100644 test/func_pit_mode_2.py diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index c701875..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -# These are supported funding model platforms - -patreon: stsp diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 5f52617..f242f15 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -19,9 +19,7 @@ or provide the download URL. **Attach the log** It is located in ~/.dosemu/boot.log -Unless you get the plain crash of dosemu2, -you may need to enable some logging flags -to make your report more useful. +To make the log more useful, you may need to enable some logging flags. See description of -D option in `man dosemu.bin`. **A regression?** @@ -29,15 +27,6 @@ If you happened to know this problem didn't exist on dosemu1 or some earlier versions of dosemu2, please write. -**dosemu2 origins** -Please describe where do you get dosemu2 -from (PPA, COPR, git sources). In case of a -source build, please describe any configure-time -customizations. In case of binary packages, -please specify your distribution and make sure -to install the debuginfo packages before creating -the log file. - **Additional info** Please write here if you did any dosemu2 setup customizations, like installing any custom DOS diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index c9887c4..ce6d0d2 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -1,37 +1,31 @@ name: Build on: - workflow_call: - inputs: - jobtype: - required: true - type: string - subtype: - required: true - type: string - runtype: - required: true - type: string + pull_request: + types: + - opened + - edited + - ready_for_review + - reopened + - synchronize + push: jobs: build: + if: contains(github.event.head_commit.message, '[skip ci]') == false - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v2 - name: package install run: ./ci_prereq.sh - name: build - env: - JOBTYPE: ${{ inputs.jobtype }} - SUBTYPE: ${{ inputs.subtype }} - RUNTYPE: ${{ inputs.runtype }} run: ./ci_build.sh - name: cache binaries - uses: actions/cache@v4 + uses: actions/cache@v2 env: cache-name: test-binaries with: @@ -40,23 +34,13 @@ jobs: restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- - - name: Enable KVM group perms - run: | - echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules - sudo udevadm control --reload-rules - sudo udevadm trigger --name-match=kvm - - name: test id: test - env: - JOBTYPE: ${{ inputs.jobtype }} - SUBTYPE: ${{ inputs.subtype }} - RUNTYPE: ${{ inputs.runtype }} run: ./ci_test.sh - name: upload failure logs if: ${{ always() && (steps.test.outcome == 'failure') }} - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v2 with: name: failure-logs path: test_* diff --git a/.github/workflows/ci-manual-asan.yml b/.github/workflows/ci-manual-asan.yml deleted file mode 100644 index f254d89..0000000 --- a/.github/workflows/ci-manual-asan.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Manual ASAN -on: - workflow_dispatch: - -jobs: - manual_asan: - name: Manual (ASAN) - uses: ./.github/workflows/ci-build.yml - with: - jobtype: 'manual' - subtype: 'asan' - runtype: 'simple' diff --git a/.github/workflows/ci-manual-full.yml b/.github/workflows/ci-manual-full.yml deleted file mode 100644 index b83c128..0000000 --- a/.github/workflows/ci-manual-full.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Manual FULL -on: - workflow_dispatch: - -jobs: - manual_full: - name: Manual (FULL) - uses: ./.github/workflows/ci-build.yml - with: - jobtype: 'manual' - subtype: '' - runtype: 'full' diff --git a/.github/workflows/ci-manual-normal.yml b/.github/workflows/ci-manual-normal.yml deleted file mode 100644 index 53f62ab..0000000 --- a/.github/workflows/ci-manual-normal.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Manual Normal -on: - workflow_dispatch: - -jobs: - manual_normal: - name: Manual (Normal) - uses: ./.github/workflows/ci-build.yml - with: - jobtype: 'manual' - subtype: '' - runtype: 'normal' diff --git a/.github/workflows/ci-master.yml b/.github/workflows/ci-master.yml deleted file mode 100644 index 74c81bc..0000000 --- a/.github/workflows/ci-master.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: Master - -on: - schedule: - - cron: '23 23 * * 0' # 23:23 Every Sunday - pull_request: - types: - - opened - - reopened - - synchronize - push: - -jobs: -# scheduled_asan: -# name: Scheduled (ASAN) -# if: (github.event_name == 'schedule' && -# github.repository_owner == 'dosemu2') - -# uses: ./.github/workflows/ci-build.yml -# with: -# jobtype: 'schedule' -# subtype: 'asan' -# runtype: 'simple' - - scheduled_full: - name: Scheduled (FULL) - if: (github.event_name == 'schedule' && - github.repository_owner == 'dosemu2') - - uses: ./.github/workflows/ci-build.yml - with: - jobtype: 'schedule' - subtype: '' - runtype: 'full' - - triggered: - name: Triggered - if: (github.event_name != 'schedule' && - contains(github.event.head_commit.message, '[skip ci]') == false && - contains(github.event.head_commit.message, '[full ci]') == false && - contains(github.event.head_commit.message, '[asan ci]') == false) - - uses: ./.github/workflows/ci-build.yml - with: - jobtype: 'triggered' - subtype: '' - runtype: 'normal' - - triggered_asan: - name: Triggered (ASAN) - if: (github.event_name != 'schedule' && - contains(github.event.head_commit.message, '[skip ci]') == false && - contains(github.event.head_commit.message, '[full ci]') == false && - contains(github.event.head_commit.message, '[asan ci]') == true) - - uses: ./.github/workflows/ci-build.yml - with: - jobtype: 'triggered' - subtype: 'asan' - runtype: 'simple' - - triggered_full: - name: Triggered (FULL) - if: (github.event_name != 'schedule' && - contains(github.event.head_commit.message, '[skip ci]') == false && - contains(github.event.head_commit.message, '[full ci]') == true && - contains(github.event.head_commit.message, '[asan ci]') == false) - - uses: ./.github/workflows/ci-build.yml - with: - jobtype: 'triggered' - subtype: '' - runtype: 'full' diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 86f9af1..0000000 --- a/.gitignore +++ /dev/null @@ -1,39 +0,0 @@ -/install-sh -/config.status -/config.sub -*.d -!dosrc.d -*.o -configure -config.log -aclocal.m4 -autom4te.cache -Makefile.conf -plugin_enable -*.map -*.xxd -_*.h.in -_*.h -*.hh -config.hh.in -*.yy.c -*.zz.c -parser.c -parser.h -parser.output -*.1 -dosemu_c.c -global_c.c -etc/Xfonts -/etc/ttf/.uuid -.tstamp -/2.* -/bin -/commands -/lib -dosemu.desktop -dosdebug -hdinfo -bios_symbols.c -keysym_attributes.c -make_attributes diff --git a/.tito/packages/.readme b/.tito/packages/.readme deleted file mode 100644 index b9411e2..0000000 --- a/.tito/packages/.readme +++ /dev/null @@ -1,3 +0,0 @@ -the .tito/packages directory contains metadata files -named after their packages. Each file has the latest tagged -version and the project's relative directory. diff --git a/.tito/packages/dosemu2 b/.tito/packages/dosemu2 deleted file mode 100644 index 5a4bd26..0000000 --- a/.tito/packages/dosemu2 +++ /dev/null @@ -1 +0,0 @@ -2.0pre9-2 ./ diff --git a/.tito/tito.props b/.tito/tito.props deleted file mode 100644 index 9f6fd2b..0000000 --- a/.tito/tito.props +++ /dev/null @@ -1,6 +0,0 @@ -[buildconfig] -builder = tito.builder.Builder -tagger = tito.tagger.VersionTagger -changelog_do_not_remove_cherrypick = 0 -changelog_format = %s (%ae) - diff --git a/.travis.yml b/.travis.yml index 11dd5fc..a91c13b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: c -os: linux +sudo: true dist: focal if: type = cron diff --git a/COPYING.DOSEMU b/COPYING.DOSEMU index 7b16464..b5f661e 100644 --- a/COPYING.DOSEMU +++ b/COPYING.DOSEMU @@ -17,10 +17,8 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -2. All dosemu2 C sources (*.c) that have no explicit copyright statement, - are copyrighted under GPLv2. Headers (*.h) without explicit - copyrights are copyrighted similar to their respective .c - counterparts, or, if no .c file with that name - under GPLv2+. +2. All dosemu2 sources that have no explicit copyright statement, + are copyrighted under GPLv2. 3. Parts of the code not covered by the GPL are marked explicitly within the code, and/or their copyrights are at the end of this @@ -46,35 +44,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ---- The QEMU emulator, before July 2013 - (src/base/dev/pic/*, src/base/dev/ne2k/ne2000.c) - -The following points clarify the QEMU license: - -1) QEMU as a whole is released under the GNU General Public License - -2) Parts of QEMU have specific licenses which are compatible with the -GNU General Public License. Hence each source file contains its own -licensing information. - -Many hardware device emulation sources are released under the BSD license. - -3) The Tiny Code Generator (TCG) is released under the BSD license - (see license headers in files). - -4) QEMU is a trademark of Fabrice Bellard. - -Fabrice Bellard. - -dosemu2 note: in July 2013 QEMU license was updated to state GPLv2-only: --1) QEMU as a whole is released under the GNU General Public License -+1) QEMU as a whole is released under the GNU General Public License, -+version 2. - -Therefore we take care to remove all changes done since that date, -while porting QEMU sources to dosemu2. - ---- The Mach DOS Emulator (mfs.c, emm.c, emufs.s) +--- The Mach DOS Emulator Copyright (c) 1991 Carnegie Mellon University All Rights Reserved. @@ -99,7 +69,7 @@ Carnegie Mellon requests users of this software to return to any improvements or extensions that they make and grant Carnegie Mellon the rights to redistribute these changes. ---- XFree86 (src/base/mouse/mouseint.c) +--- XFree86 (mouse code) Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. Copyright 1993 by David Dawes @@ -123,14 +93,14 @@ RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ---- Doug Lea's malloc in src/base/lib/misc/dlmalloc.c +--- Doug Lea's malloc in src/base/misc/dlmalloc.c This is a version (aka dlmalloc) of malloc/free/realloc written by Doug Lea and released to the public domain, as explained at http://creativecommons.org/licenses/publicdomain. Send questions, comments, complaints, performance data, etc to dl@cs.oswego.edu ---- The VGA fonts in src/base/dev/vga/vgafonts.c (copyleft_vgafonts.txt) +--- The VGA fonts in src/env/video/vgafonts.c (copyleft_vgafonts.txt) This *compilation* is (c) Copyright 1991,1992 Joseph (Yossi) Gil. Permission is granted to use and redistribute the files comprising diff --git a/INSTALL b/INSTALL index 232e052..4e62fce 100644 --- a/INSTALL +++ b/INSTALL @@ -6,7 +6,7 @@ building and installing dosemu2 from sources https://code.launchpad.net/~dosemu2/+archive/ubuntu/ppa of from COPR: https://copr.fedorainfracloud.org/coprs/stsp/dosemu2/ - - gcc >= 8.1 or clang >= 3.7.0 + - gcc >= 3.3 or clang >= 3.7.0 - glibc >= 2.20 - linux >= 3.16 for x86-64, >= 4.7 recommended. With older version than 3.16 there may be some problems @@ -14,8 +14,11 @@ building and installing dosemu2 from sources linux >= 4.3 for i386. linux >= 4.11 if you want to run 32bit dosemu under x86_64 kernel with multilib environment (you likely don't want to do this). + - x86 (i386/x86-64) target CPU - bison and flex - - SDL >= 2.0.6, >= 2.26.0 is required for copy/paste support. + - SDL >= 2.0.6, >= 2.0.15 is recommended (older versions may not have + scaling filters and KMS rendering working). + - udev >= 240 recommended for KVM (execution acceleration) - libslirp >= 4.1.0 recommended for networking - json-c >= 0.13 recommended - development libraries: Xext, slang, gpm, alsa, fluidsynth, diff --git a/Makefile b/Makefile index e9ffc30..e26dfb7 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ endif REALTOPDIR ?= $(abspath $(srcdir)) $(REALTOPDIR)/configure: $(REALTOPDIR)/configure.ac - cd $(@D) && autoreconf --install -v -I m4 + cd $(@D) && autoreconf -v -I m4 Makefile.conf config.status src/include/config.hh etc/dosemu.desktop: \ $(REALTOPDIR)/configure @@ -62,7 +62,7 @@ rpm: dosemu2.spec.rpkg rpkg local deb: - debuild -e CC=clang -i -us -uc -b + debuild -i -us -uc -b changelog: if [ -d $(top_srcdir)/.git -o -f $(top_srcdir)/.git ]; then \ diff --git a/Makefile.conf.in b/Makefile.conf.in index e33cffa..62d358e 100644 --- a/Makefile.conf.in +++ b/Makefile.conf.in @@ -24,7 +24,7 @@ abs_top_srcdir:=@abs_top_srcdir@ abs_top_builddir:=@abs_top_builddir@ INCDIR=-I${top_builddir}/src/include -I${top_builddir}/src/plugin/include \ - -I${top_srcdir}/src/base/bios/x86 -I${top_srcdir}/src/include \ + -I${top_builddir}/src/base/bios/x86 -I${top_srcdir}/src/include \ -I${top_srcdir}/src/base/lib top_srcdir:=$(abs_top_srcdir) srcdir = $(patsubst %/,%,$(abs_top_srcdir)/src/$(SUBDIR)) @@ -46,16 +46,12 @@ LD:=@CC@ AS:=@AS@ XAS:=@XAS@ AS_LD:=@AS_LD@ -XOBJCOPY:=@XOBJCOPY@ -CC_FOR_BUILD:=@CC_FOR_BUILD@ -CFLAGS_FOR_BUILD:=@CFLAGS_FOR_BUILD@ +OBJCOPY:=@OBJCOPY@ YACC:=@YACC@ # NOTE: we really need bison, yacc won't work any more #YACC=bison -y LEX:=@LEX@ -LN_S := @LN_S@ -LN_SFT := @LN_SFT@ # This gets defined even if we chose via ./include/config.h NOT to # use the debugger @@ -72,17 +68,8 @@ RANLIB:=@RANLIB@ PACKAGE_NAME:=@PACKAGE_TARNAME@ -USE_DL_PLUGINS := @USE_DL_PLUGINS@ -X86_EMULATOR := @X86_EMULATOR@ -X86_JIT := @X86_JIT@ -DNATIVE := @DNATIVE@ -KVM := @KVM@ -MCONTEXT := @MCONTEXT@ -USE_OFD_LOCKS := @USE_OFD_LOCKS@ -USE_XATTRS := @USE_XATTRS@ -USE_EVTIMER_FD := @USE_EVTIMER_FD@ -USE_OSS := @USE_OSS@ -USE_SOFTFLOAT := @USE_SOFTFLOAT@ +@USE_DL_PLUGINS@ +@X86_EMULATOR@ INSTALL:=@INSTALL@ REALTOPDIR:=$(top_srcdir) @@ -107,7 +94,7 @@ BINPATH:=$(top_builddir)/$(THISVERSION) RELEASE_DATE="@RELEASE_DATE@" REVISION:=$(shell cd $(top_srcdir) && ./getversion -r) -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS DL_CFLAGS:=-fPIC else -include $(top_builddir)/src/plugin/*/Makefile.conf diff --git a/README.md b/README.md index 536c8e7..7bfde3d 100644 --- a/README.md +++ b/README.md @@ -17,40 +17,10 @@ https://github.com/dosemu2/dosemu2/issues ## Running -Just type -``` -dosemu -``` -to run an emulator. - -Use -``` -dosemu -E -``` -to run `` and exit (add `-T` to not exit). - -Use -``` -dosemu -K -E -``` -or -``` -dosemu -- -``` -to run DOS programs from unix directory. - -If you want to run the DOS program from a DOS directory, use this syntax: -``` -dosemu -K :C:\\games\\carma -E carma.exe -``` -This will run `carma.exe` from `c:\games\carma`. Note the leading colon -after `-K`: it means that the DOS path, rather than unix path, is specified. -You can actually specify both paths: -``` -dosemu -K ~/dosgames:carma -E carma.exe -``` -This creates the DOS drive for `~/dosgames`, then chdirs to `carma` and -runs `carma.exe`. +Just type `dosemu` to run an emulator. +Use `dosemu -E ` to run `` and exit (add `-T` to not exit). +Use `dosemu -K -E ` or `dosemu -K ` +to run DOS programs from unix directories. ## Configuring diff --git a/THANKS b/THANKS index 7659f38..247159c 100644 --- a/THANKS +++ b/THANKS @@ -4,22 +4,15 @@ Main contributors (with their github names): Stas Sergeev @stsp Bart Oldeman @bartoldeman Andrew Bird @andrewbird -C. Masloch @ecm-pushbx Ryan C. Underwood @runderwo Stuart Axon @stuaxo -Special thanks for making dosemu2 feasible -by sponsoring the initial development: +Special thanks for making dosemu2 feasible: Caylan Van Larson Hans-Christian Koch -Many thanks to our Patreon patrons: -Jeffrey H. Ingber (@jharrison022) -C. Masloch (@ecm-pushbx) -doctorwhoguy@gmail.com (@PaddyMac) - Thanks for the good testing and bugreporting: -Julius Schwartzenberg (@jschwartzenberg) +Julius Schwartzenberg @jschwartzenberg A big thanks goes to Linus Torvalds and Andy Lutomirski, who helped in solving many dosemu2-specific problems in diff --git a/autogen.sh b/autogen.sh index b46a452..64826b2 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,18 +2,10 @@ DIR=$(dirname $0 | xargs realpath) echo "Generating toplevel configure script in $DIR..." - -check_scr() { - [ -f $DIR/$1 ] || cp $DIR/scripts/$1 $DIR/$1 -} - rm -f aclocal.m4 -if ! autoreconf -v -I m4 --install --force $DIR; then +if ! autoreconf -I m4 --install --force $DIR; then echo "Failure!" exit 1 fi -check_scr config.sub -check_scr config.guess -check_scr install-sh echo echo "Done, now run $DIR/default-configure" diff --git a/ci_build.sh b/ci_build.sh index 3b3e8a1..4e024f0 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -8,13 +8,6 @@ FDPPBRANCH="" test -d ${LOCALFDPP} && exit 1 -if [ "${TRAVIS}" = "true" ] ; then - echo "Travis seems to have some old version of clang in its local directory" - PATH=$(echo ${PATH} | sed 's,:/usr/local/clang-7.0.0/bin,,g') - export PATH - echo PATH is ${PATH} -fi - git clone --depth 1 --no-single-branch https://github.com/dosemu2/fdpp.git ${LOCALFDPP} ( cd ${LOCALFDPP} || exit 2 @@ -27,37 +20,14 @@ git clone --depth 1 --no-single-branch https://github.com/dosemu2/fdpp.git ${LOC echo "EXTRA_DEBUG = 1" >> local.mak echo "USE_UBSAN = 1" >> local.mak - # Install the build dependancies based FDPP's debian/control file - sudo add-apt-repository ppa:stsp-0/nasm-segelf - sudo add-apt-repository ppa:stsp-0/thunk-gen - sudo apt update -q - mk-build-deps --install --root-cmd sudo - - # Seems to miss this, perhaps the optional dependency confuses things - if [ "${TRAVIS}" = "true" ] ; then - sudo apt install binutils - fi - - make - sudo make install + make clean all install PREFIX=${LOCALFDPPINST} ) -# Install the build dependancies based Dosemu's debian/control file -sudo add-apt-repository -y ppa:dosemu2/ppa -mk-build-deps --install --root-cmd sudo - -if [ "${SUBTYPE}" = "asan" ] ; then - sed -i 's/asan off/asan on/g' compiletime-settings.devel -fi -CC=clang ./default-configure -d +export PKG_CONFIG_PATH=${LOCALFDPPINST}/lib/pkgconfig +./default-configure -d make # Install the FAT mount helper sudo cp test/dosemu_fat_mount.sh /bin/. sudo chown root.root /bin/dosemu_fat_mount.sh sudo chmod 755 /bin/dosemu_fat_mount.sh - -# Install the TAP helper -sudo cp test/dosemu_tap_interface.sh /bin/. -sudo chown root.root /bin/dosemu_tap_interface.sh -sudo chmod 755 /bin/dosemu_tap_interface.sh diff --git a/ci_prereq.sh b/ci_prereq.sh index 888bf1a..a4e482c 100755 --- a/ci_prereq.sh +++ b/ci_prereq.sh @@ -1,8 +1,55 @@ #!/bin/sh -sudo apt-get update +sudo add-apt-repository -y ppa:dosemu2/ppa +sudo add-apt-repository -y ppa:jwt27/djgpp-toolchain +sudo add-apt-repository -y ppa:tkchia/build-ia16 + +sudo apt update -q + sudo apt install -y \ - devscripts \ - equivs \ + acl \ + comcom32 \ git \ - bash + bash \ + autoconf \ + autotools-dev \ + automake \ + coreutils \ + linuxdoc-tools \ + bison \ + flex \ + gawk \ + sed \ + libbsd-dev \ + libx11-dev \ + libxext-dev \ + libslang2-dev \ + xfonts-utils \ + libgpm-dev \ + libasound2-dev \ + libsdl2-dev \ + libsdl2-ttf-dev \ + libfontconfig1-dev \ + libsdl1.2-dev \ + ladspa-sdk \ + libfluidsynth-dev \ + libao-dev \ + libieee1284-3-dev \ + libreadline-dev \ + libjson-c-dev \ + libslirp-dev \ + binutils-dev \ + libelf-dev \ + pkg-config \ + clang \ + nasm \ + python3-cpuinfo \ + python3-pexpect \ + gcc-djgpp \ + qemu-system-common \ + gdb \ + valgrind \ + gcc-ia16-elf \ + libi86-ia16-elf \ + gcc-multilib \ + dos2unix diff --git a/ci_test.sh b/ci_test.sh index cddb7ed..122e152 100755 --- a/ci_test.sh +++ b/ci_test.sh @@ -1,36 +1,42 @@ -#!/bin/bash +#!/bin/sh -. ./ci_test_prereq.sh +set -e + +# Get any test binaries we need +TBINS="test-binaries" +THOST="http://www.spheresystems.co.uk/test-binaries" if [ "${TRAVIS}" = "true" ] ; then export CI="true" - export CI_BRANCH="${TRAVIS_BRANCH}" if [ "${TRAVIS_EVENT_TYPE}" = "cron" ] ; then - export RUNTYPE="full" - else - export RUNTYPE="simple" + export CI_EVENT="cron" fi + export CI_BRANCH="${TRAVIS_BRANCH}" elif [ "${GITHUB_ACTIONS}" = "true" ] ; then # CI is already set - export CI_BRANCH="$(echo ${GITHUB_REF} | cut -d/ -f3)" - if [ "${GITHUB_EVENT_NAME}" = "push" ] && [ "${GITHUB_REPOSITORY_OWNER}" = "dosemu2" ] && [ "${CI_BRANCH}" = "devel" ] ; then - export RUNTYPE="simple" + if [ "${GITHUB_EVENT_NAME}" = "scheduled" ] ; then + export CI_EVENT="cron" fi + export CI_BRANCH="$(echo ${GITHUB_REF} | cut -d/ -f3)" fi -TBINS="test-binaries" if [ "${CI}" = "true" ] ; then [ -d "${HOME}"/cache ] || mkdir "${HOME}"/cache [ -h "${TBINS}" ] || ln -s "${HOME}"/cache "${TBINS}" else [ -d "${TBINS}"] || mkdir "${TBINS}" fi -python3 test/test_dos.py --get-test-binaries -if [ -f /dev/kvm ] ; then - sudo setfacl -m u:${USER}:rw /dev/kvm -fi +( + cd "${TBINS}" || exit 1 + [ -f DR-DOS-7.01.tar ] || wget ${THOST}/DR-DOS-7.01.tar + [ -f FR-DOS-1.20.tar ] || wget ${THOST}/FR-DOS-1.20.tar + [ -f MS-DOS-6.22.tar ] || wget ${THOST}/MS-DOS-6.22.tar + + [ -f VARIOUS.tar ] || wget ${THOST}/VARIOUS.tar + [ -f TEST_EMM286.tar ] || wget ${THOST}/TEST_EMM286.tar +) echo echo "=====================================================" @@ -43,35 +49,20 @@ echo "=====================================================" # single test example # python3 test/test_dos.py FRDOS120TestCase.test_mfs_fcb_rename_wild_1 -if [ "${TRAVIS}" = "true" ] ; then - ARGS="--require-attr=cputest" +if [ "${CI_EVENT}" = "cron" ] ; then + if [ "${TRAVIS}" = "true" ] ; then + python3 test/test_dos.py --require-attr=cputest PPDOSGITTestCase MSDOS622TestCase FRDOS120TestCase + else + python3 test/test_dos.py + fi else - ARGS="" + if [ "${CI_BRANCH}" = "devel" ] ; then + python3 test/test_dos.py PPDOSGITTestCase MSDOS622TestCase + else + python3 test/test_dos.py PPDOSGITTestCase + fi fi -case "${RUNTYPE}" in - "full") - ARGS="${ARGS} PPDOSGITTestCase MSDOS622TestCase FRDOS130TestCase DRDOS701TestCase" - ;; - "normal") - ARGS="${ARGS} PPDOSGITTestCase MSDOS622TestCase" - export SKIP_UNCERTAIN=1 - ;; - "simple") - ARGS="${ARGS} PPDOSGITTestCase" - export SKIP_EXPENSIVE=1 - export SKIP_UNCERTAIN=1 - ;; -esac - -# CC is set on Travis and can confuse compilation during tests -unset CC - -# Make cpu tests here so that we see any failures -make -C test/cpu clean all - -python3 test/test_dos.py ${ARGS} - for i in test_*.*.*.log ; do test -f $i || exit 0 done diff --git a/ci_test_prereq.sh b/ci_test_prereq.sh deleted file mode 100755 index 74e7225..0000000 --- a/ci_test_prereq.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -sudo add-apt-repository -y ppa:jwt27/djgpp-toolchain -sudo add-apt-repository -y ppa:tkchia/build-ia16 - -sudo apt update -q - -sudo apt install -y \ - acl \ - comcom64 \ - nasm \ - python3-cpuinfo \ - python3-pexpect \ - mtools \ - gcc-djgpp \ - djgpp-dev \ - qemu-system-common \ - gdb \ - valgrind \ - gcc-ia16-elf \ - libi86-ia16-elf \ - libi86-testsuite-ia16-elf \ - gcc-multilib \ - dos2unix \ - bridge-utils \ - libvirt-daemon \ - libvirt-daemon-system diff --git a/compiletime-settings.devel b/compiletime-settings.devel index d0f188d..fdee0ef 100644 --- a/compiletime-settings.devel +++ b/compiletime-settings.devel @@ -1,9 +1,7 @@ config { experimental on debug on - asan off - lsan off - tsan off + asan on ubsan on optimize off system-wa off diff --git a/configure.ac b/configure.ac index 3ecd739..f8adba2 100644 --- a/configure.ac +++ b/configure.ac @@ -16,11 +16,10 @@ AC_PROG_CC #AC_PROG_CC_C11([AC_DEFINE(HAVE_STD_C11)]) AC_DEFINE(HAVE_STD_C11) AC_PROG_CPP -AX_PROG_CC_FOR_BUILD AC_USE_SYSTEM_EXTENSIONS AC_MSG_CHECKING([for $CC actually being clang]) -if $CC -v 2>&1|grep 'clang' >/dev/null; then +if "$CC" -v 2>&1|grep 'clang' >/dev/null; then AC_MSG_RESULT([yes]) AC_MSG_CHECKING([for clang >= 3.7]) clang_ver=`$CC -v 2>&1 | grep version | sed 's/.*version //' | cut -d " " -f 1` @@ -36,93 +35,46 @@ if $CC -v 2>&1|grep 'clang' >/dev/null; then -Wno-address-of-packed-member" LDFLAGS="$LDFLAGS -Wno-unused-command-line-argument" use_clang="yes" - - AS="$CC" - clang_as_as=1 - ASFLAGS="-xassembler -c -" else + CCAS="$CC" AC_MSG_RESULT([no]) use_clang="no" AC_MSG_CHECKING([for $CC actually being c++]) - if $CC -v 2>&1 | grep "g++" | grep "COLLECT_GCC" >/dev/null; then + if "$CC" -v 2>&1 | grep "g++" | grep "COLLECT_GCC" >/dev/null; then AC_MSG_RESULT([yes, using -fpermissive]) - DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fpermissive -Wno-narrowing" + DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fpermissive" else AC_MSG_RESULT([no]) DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fplan9-extensions" fi fi -CONFIG_HOST=`uname -s` -AC_SUBST(CONFIG_HOST) -machine=`$CC -dumpmachine | cut -d- -f1 | sed 's/i.86/i386/'` - +AC_PATH_PROG([AS], [as]) if test -z "$AS"; then - AC_PATH_PROG([AS], [as]) - if test -z "$AS"; then - AC_PATH_PROG([AS], [clang]) - if test -z "$AS"; then - AC_MSG_ERROR(as not found) - fi - AC_MSG_NOTICE(Using clang as as...) - clang_as_as=1 - ASFLAGS="-xassembler -c -" - fi + AC_MSG_ERROR(as not found) fi -AC_PATH_PROGS([XAS], [i686-linux-gnu-as i386-elf-as]) +AC_PATH_PROG([XAS], [i386-elf-as]) if test -z "$XAS"; then - if test "$CONFIG_HOST" = "Darwin"; then - AC_MSG_ERROR([Please install i386-elf-binutils from https://github.com/nativeos/homebrew-i386-elf-toolchain]) - fi - AC_PATH_PROG([XAS], [x86_64-linux-gnu-as]) - if test -z "$XAS"; then - if test "$machine" = "i386" -o "$machine" = "x86_64"; then - XAS="$AS" - if test "$clang_as_as" = "1"; then - XASFLAGS="$ASFLAGS -m32" - else - XASFLAGS="$ASFLAGS --32" - fi - else - AC_MSG_ERROR([cross-assembler not found, please install binutils-i686-linux-gnu]) - fi - else - XASFLAGS="$ASFLAGS --32" - fi + XAS="$AS" + XASFLAGS=--32 fi - -AC_PATH_PROGS([LD], [ld ld.lld]) +AC_PATH_PROG([LD], [ld]) if test -z "$LD"; then AC_MSG_ERROR(ld not found) fi -AC_PATH_PROGS([AS_LD], [i686-linux-gnu-ld i386-elf-ld x86_64-linux-gnu-ld ld.lld ld]) +AC_PATH_PROG([AS_LD], [i386-elf-ld]) if test -z "$AS_LD"; then AS_LD="$LD" fi - -AC_PATH_PROG([OBJCOPY], [objcopy]) -O_VER=`$OBJCOPY -V | head -n 1 | grep "GNU objcopy"` -if test -z "$O_VER"; then - AC_MSG_WARN([rejecting BSD objcopy]) - OBJCOPY="" -fi +AC_PATH_PROGS([OBJCOPY], [i386-elf-objcopy objcopy]) if test -z "$OBJCOPY"; then - AC_PATH_PROG([LOBJCOPY], [llvm-objcopy], [], [$PATH${PATH_SEPARATOR}/usr/local/opt/llvm/bin]) - if test -z "$LOBJCOPY"; then - AC_MSG_ERROR(objcopy not found) - fi - OBJCOPY="$LOBJCOPY" -fi - -AC_PATH_PROGS([XOBJCOPY], [i686-linux-gnu-objcopy x86_64-linux-gnu-objcopy objcopy]) -if test -z "$XOBJCOPY"; then - XOBJCOPY="$OBJCOPY" + AC_MSG_ERROR(objcopy not found) fi AC_SUBST(AS) AC_SUBST(XAS) AC_SUBST(AS_LD) -AC_SUBST(XOBJCOPY) +AC_SUBST(OBJCOPY) AC_ARG_WITH(target-bits-32, [AS_HELP_STRING([--with-target-bits-32], [build for 32bit target (multilib in case of x86_64 host)])], @@ -133,30 +85,20 @@ AC_ARG_WITH(target-bits-32, [AS_HELP_STRING([--with-target-bits-32], ) AC_PROG_INSTALL AC_PROG_LEX([noyywrap]) -if test -z "$LEX"; then +if test -z "`echo $LEX | grep flex`" ; then + AC_CHECK_PROG(lex_ok, $LEX, "yes", "no") +fi +if test "$lex_ok" = "no"; then AC_MSG_WARN(Your system doesn't seem to have lex or flex available.) AC_MSG_ERROR(Install lex or flex and retry.) fi - AC_PROG_LN_S -AC_MSG_CHECKING([if $LN_S is a GNU ln]) -if $LN_S --help >/dev/null 2>&1; then - AC_MSG_RESULT([yes, using -T]) - LN_SFT="$LN_S -f -T" -else - AC_MSG_RESULT([no, using -F]) - LN_SFT="$LN_S -f -F" -fi -AC_SUBST(LN_SFT) - -AC_CHECK_PROGS([MAKE], [gmake make]) -if test -z "$MAKE"; then +AC_CHECK_PROG([MAKE], [make], ["yes"]) +if test "$MAKE" != "yes"; then AC_MSG_ERROR(You don't have make installed) fi -# export MAKE to run from scripts -export MAKE="$MAKE" -AC_CHECK_PROGS([REALPATH], [realpath]) -if test -z "$REALPATH"; then +AC_CHECK_PROG([REALPATH], [realpath], ["yes"]) +if test "$REALPATH" != "yes"; then AC_MSG_ERROR(You don't have realpath installed) fi AC_PROG_RANLIB @@ -174,7 +116,7 @@ AC_PROG_AWK if test "$ac_cv_prog_AWK" != "gawk" ; then AC_MSG_ERROR(Install gawk and retry.) fi -AC_CHECK_PROGS([PKG_CONFIG], [pkg-config]) +AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes) if test -z "$PKG_CONFIG"; then AC_MSG_ERROR(Install pkg-config and retry.) fi @@ -207,6 +149,7 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([ ])], [ AC_MSG_RESULT([yes]) + AC_MSG_NOTICE(Compiling with x86 emulator) AC_DEFINE(HAVE_ASSIGNABLE_STDERR) ], [ @@ -214,70 +157,32 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([ ] ) -AC_MSG_CHECKING([for optreset]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([ - #include - int main(void) - { - optreset = 1; - return 0; - } - ])], - [ - AC_MSG_RESULT([yes]) - AC_DEFINE(HAVE_OPTRESET) - ], - [ - AC_MSG_RESULT([no]) - ] -) - AC_CHECK_LIB(rt, shm_open) dnl below defines HAVE_xxx so needed even if AC_CHECK_LIB() succeeded -AC_CHECK_FUNCS([shm_open memfd_create fopencookie sigtimedwait closefrom]) -AC_CHECK_FUNCS([setxattr], [ - USE_XATTRS=1 - AC_SUBST(USE_XATTRS) -]) -AC_CHECK_FUNCS([timerfd_create], [ - USE_EVTIMER_FD=1 - AC_SUBST(USE_EVTIMER_FD) -], [AC_CHECK_FUNCS([kqueue], [ - USE_EVTIMER_FD=1 - AC_SUBST(USE_EVTIMER_FD) -])]) -AC_CHECK_FUNCS([mremap]) -AC_CHECK_FUNCS([fls]) +AC_CHECK_FUNCS([shm_open memfd_create renameat2]) -AC_CHECK_DECLS([F_OFD_SETLK], [ - USE_OFD_LOCKS=1 - AC_SUBST(USE_OFD_LOCKS) - ],, [[#include ]] -) -AC_CHECK_DECLS([MREMAP_MAYMOVE],,, [[#include ]]) -AC_CHECK_DECLS([MADV_POPULATE_WRITE, MADV_COLD],,, - [[#include ]]) - -AC_CHECK_TYPES([__float80],, [ - if test "$machine" != "i386" -a "$machine" != "x86_64"; then - USE_SOFTFLOAT=1 - AC_SUBST(USE_SOFTFLOAT) - fi - ] +AC_CHECK_DECLS([F_OFD_SETLK],, [ + AC_MSG_ERROR([F_OFD_SETLK not available, your glibc is too old]) + ], [[#include ]] ) -AC_CHECK_FUNC(strlcpy,, [ - PKG_CHECK_MODULES([LIBBSD], [libbsd], [ +PKG_CHECK_MODULES([LIBBSD], [libbsd], [ dnl re-check for proper arch (multilib) AC_CHECK_LIB(bsd, strlcpy,, [AC_MSG_ERROR(libbsd not found)]) + ], [ + dnl extra check because on bsd these functions are available w/o lib + AC_CHECK_FUNC(strlcpy,, [AC_MSG_ERROR(libbsd not found)]) ] -)]) +) dnl Here is where we do our stuff AC_ARG_WITH(confdir, [AS_HELP_STRING([--with-confdir=dir], [directory suffix under sysconfdir. default: dosemu])], confdir="$withval", confdir="dosemu") +AC_ARG_WITH(plugindir, [AS_HELP_STRING([--with-plugindir=dir], + [directory for dosemu plugins. default: ${libdir}/dosemu])], + plugindir="$withval", plugindir="${libdir}/dosemu") AC_ARG_WITH(x11fontdir, [AS_HELP_STRING([--with-x11fontdir=dir], [directory to install the VGA X11 font. default: ${datadir}/dosemu/Xfonts])], x11fontdir="$withval", x11fontdir="${datadir}/dosemu/Xfonts") @@ -288,10 +193,6 @@ AC_ARG_WITH(fdtarball, [AS_HELP_STRING([--with-fdtarball=file], [path to FreeDOS tarball])], fdtarball="$withval") -# Hard-code this. It is evaluated at run-time as ../lib/dosemu, -# so we do not use libdir here (which can be lib64 or something unrelated) -plugindir="\${prefix}/lib/dosemu" - AC_SUBST(confdir) AC_SUBST(plugindir) AC_SUBST(x11fontdir) @@ -301,14 +202,20 @@ AC_SUBST(fdtarball) AC_DEFINE_DIR([SYSCONFDIR], [sysconfdir], [ System config dir ]) AC_DEFINE_DIR([CONFSUBDIR], [confdir], [ dosemu-specific config subdir ]) -AC_DEFINE_DIR([PREFIX], [prefix], [ prefix ]) +AC_DEFINE_DIR([DOSEMUPLUGINDIR], [plugindir], [ Directory for dosemu plugins ]) +AC_DEFINE_DIR([DATADIR], [datadir], [ Where data are placed to ]) AC_DEFINE_DIR([LIBEXECDIR], [libexecdir], [ Where extra executables are placed to ]) AC_DEFINE_DIR([SYSTEM_XFONTS_PATH], [x11fontdir], [ Directory for x11 fonts ]) +CONFIG_HOST='linux' +AC_SUBST(CONFIG_HOST) + +machine=`"$CC" -dumpmachine | cut -d- -f1` + DOSEMU_CPPFLAGS="$DOSEMU_CPPFLAGS -imacros config.hh" DOSEMU_CFLAGS="$DOSEMU_CFLAGS -Wall -Wstrict-prototypes -Wmissing-declarations \ -Wnested-externs -fms-extensions -pthread \ --Wno-unused-result -Wcast-qual -Wwrite-strings -Wstrict-aliasing=2 -Wundef" +-Wno-unused-result -Wcast-qual -Wwrite-strings" AX_CHECK_COMPILE_FLAG([-Waddress-of-packed-member], [DOSEMU_CFLAGS="$DOSEMU_CFLAGS -Wno-address-of-packed-member"],, [-Werror]) AX_CHECK_COMPILE_FLAG([-Wstring-plus-int], @@ -322,7 +229,7 @@ AC_ARG_ENABLE(dlplugins, if test "$enable_dlplugins" != "no"; then AC_MSG_NOTICE(Using dynamically loaded plugins...) AC_DEFINE(USE_DL_PLUGINS) - USE_DL_PLUGINS=1 + USE_DL_PLUGINS="USE_DL_PLUGINS=1" AC_SUBST(USE_DL_PLUGINS) DOSBIN_LDFLAGS="-rdynamic" AC_SUBST(DOSBIN_LDFLAGS) @@ -355,45 +262,14 @@ AX_RESTORE_FLAGS([attr_check]) AC_DEFINE_UNQUOTED(SIG_PROTO_PFX, $SIG_PROTO_PFX) dnl Check whether we have pthreads and whether to use it -AC_CHECK_LIB(pthread, pthread_create,, [ - dnl see if the func is provided nevertheless (not needing -lpthread) - AC_CHECK_FUNC(pthread_create,, [ +AC_CHECK_LIB(pthread, pthread_create,,[ AC_MSG_ERROR([No libpthread found, please install glibc-devel package]) ] -)]) -AC_CHECK_FUNC(pthread_cancel,, [ - AC_CHECK_HEADERS([bthread.h],, [ - AC_MSG_ERROR([pthread_cancel() missing, install libbthread]) - ]) -]) -AC_CHECK_LIB(bthread, pthread_cancel) - +) AC_CHECK_FUNCS([pthread_getname_np pthread_setname_np]) -AC_CHECK_FUNCS([pthread_attr_setsigmask_np pthread_setattr_default_np]) -AC_CHECK_HEADER([wordexp.h],, [ - AC_MSG_ERROR([wordexp.h missing, install libwordexp]) -]) -AC_CHECK_LIB(wordexp, wordexp) - -AC_CHECK_HEADERS([scsi/sg.h linux/cdrom.h sys/io.h]) +AC_CHECK_HEADERS([sys/kd.h scsi/sg.h linux/cdrom.h]) AC_CHECK_HEADERS([netipx/ipx.h linux/ipx.h netpacket/packet.h]) -AC_CHECK_HEADERS([asm/ucontext.h],,, [ - #include - #include -]) -AC_CHECK_HEADERS([ucontext.h],, [ - AS_UNSET([ac_cv_header_ucontext_h]) - AC_CHECK_HEADER([ucontext.h], - AC_DEFINE([_XOPEN_SOURCE], [500], [Use X/Open 5 with POSIX 1995]), - AC_MSG_ERROR([Can't use ucontext.h]), [ - #define _XOPEN_SOURCE 500 -])]) -AC_CHECK_HEADERS([linux/signal.h],,, [#include ]) -AC_CHECK_HEADERS([sys/soundcard.h], [ - USE_OSS=1 - AC_SUBST(USE_OSS) -]) DATE_FMT="%F %T %z" test -n "$SOURCE_DATE_EPOCH" || SOURCE_DATE_EPOCH=`date +%s` CONFIG_TIME=`date -u -d "@$SOURCE_DATE_EPOCH" "+$DATE_FMT" 2>/dev/null || date -u -r "$SOURCE_DATE_EPOCH" "+$DATE_FMT" 2>/dev/null || date -u "+$DATE_FMT"` @@ -477,9 +353,9 @@ AC_ARG_ENABLE(system_wa, AS_HELP_STRING([--disable-system-wa], [compile without system-specific work-arounds (mostly for linux kernel) that are not needed on this system])) AS_IF([test "x$enable_system_wa" = "xno"], [ - AC_MSG_NOTICE(Disabling system-specific work-arounds) + AC_MSG_NOTICE(Disasbling system-specific work-arounds) AC_DEFINE(DISABLE_SYSTEM_WA) - AS_IF([test -z "$WARN_OUTDATED_WA" -a -n "$WARN_UNDISABLED_WA"], [ + AS_IF([test -z "$WARN_OUTDATED_WA" -a -z "$NOWARN_UNDISABLED_WA"], [ AC_DEFINE(WARN_UNDISABLED_WA)]) ]) AS_IF([test -n "$WARN_OUTDATED_WA"], [ @@ -491,7 +367,7 @@ dnl Do compilation for GDB HAVE_LIBBFD=0 AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [compile with debug info])) -if test "$enable_debug" != "no"; then +if test "$enable_debug" = "yes"; then AC_MSG_NOTICE(Compiling with debug info...) DOSEMU_CFLAGS="$DOSEMU_CFLAGS -ggdb3" if test "$use_clang" = "yes" ; then @@ -508,6 +384,7 @@ if test "$enable_debug" != "no"; then if test "$ac_cv_lib_bfd_bfd_init" = "yes"; then HAVE_LIBBFD=1 AC_DEFINE(HAVE_LIBBFD) + AC_DEFINE(HAVE_BACKTRACE) fi ]) if test "$HAVE_LIBBFD" = "1"; then @@ -521,7 +398,7 @@ if test "$enable_debug" != "no"; then if test "$HAVE_LIBBFD" != "1"; then DOSEMU_LDFLAGS="$DOSEMU_LDFLAGS -rdynamic" fi - AC_CHECK_FUNCS([backtrace backtrace_symbols]) + AC_DEFINE(HAVE_BACKTRACE) ]) else AC_MSG_NOTICE(Compiling without debug info...) @@ -531,8 +408,6 @@ AC_ARG_ENABLE(profile, AS_HELP_STRING([--enable-profile], [compile with profile info])) AC_ARG_ENABLE(asan, [AS_HELP_STRING(--enable-asan, [enable address sanitizer])]) -AC_ARG_ENABLE(lsan, [AS_HELP_STRING(--enable-lsan, [enable leak sanitizer])]) -AC_ARG_ENABLE(tsan, [AS_HELP_STRING(--enable-tsan, [enable thread sanitizer])]) AC_ARG_ENABLE(ubsan, [AS_HELP_STRING(--enable-ubsan, [enable UB sanitizer])]) AC_SUBST(OPTIONALSUBDIRS) @@ -546,21 +421,29 @@ dnl CPU emulator AC_ARG_ENABLE(cpuemu, [AS_HELP_STRING([--disable-cpuemu], [do NOT compile with optional x86 emulation code])]) if test "$enable_cpuemu" != "no"; then - AC_MSG_NOTICE(Compiling with x86 emulator) - AC_DEFINE(X86_EMULATOR) - X86_EMULATOR=1 - AC_SUBST(X86_EMULATOR) - - if test "$machine" = "i386" -o "$machine" = "x86_64"; then - AC_ARG_ENABLE(cpuemu_jit, [AS_HELP_STRING([--disable-cpuemu-jit], - [do NOT compile with optional x86 JIT])]) - if test "$enable_cpuemu_jit" != "no"; then - AC_MSG_NOTICE(Compiling with x86 JIT) - AC_DEFINE(X86_JIT) - X86_JIT=1 - AC_SUBST(X86_JIT) - fi - fi + AC_MSG_CHECKING([for __attribute__((force_align_arg_pointer))]) + AX_SAVE_FLAGS([attr_check2]) + CFLAGS="-Wall -Werror" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ + void foo(void); + __attribute__((force_align_arg_pointer)) + void foo(void) + { + } + ])], + [ + AC_MSG_RESULT([supported]) + AC_MSG_NOTICE(Compiling with x86 emulator) + AC_DEFINE_UNQUOTED(X86_EMULATOR) + X86_EMULATOR="X86_EMULATOR=1" + AC_SUBST(X86_EMULATOR) + ], + [ + AC_MSG_RESULT([unsupported]) + AC_MSG_WARN(Compiling without x86 emulator) + ] + ) + AX_RESTORE_FLAGS([attr_check2]) fi AC_ARG_WITH(target_cpu, [AS_HELP_STRING([--with-target-cpu=CPU], @@ -573,72 +456,25 @@ else target_cpu=$with_target_cpu fi -if test "$machine" = "i386" -o "$with_target_bits" = "32" -o \ - "$enable_profile" = "yes"; then +if test "$machine" = "x86_64" -a "$with_target_bits" != "32" -a \ + "$enable_profile" != "yes"; then + AC_MSG_NOTICE(Compiling as PIE for $machine...) + DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fpie" + DOSEMU_LDFLAGS="$DOSEMU_LDFLAGS -pie" +else AC_MSG_NOTICE(Compiling as non-PIE...) DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fno-pie" AX_CHECK_COMPILE_FLAG([-no-pie], [DOSEMU_LDFLAGS="$DOSEMU_LDFLAGS -no-pie"]) -else - AC_MSG_NOTICE(Compiling as PIE for $machine...) - DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fpie" - DOSEMU_LDFLAGS="$DOSEMU_LDFLAGS -pie" -fi - -if test "$CONFIG_HOST" = "Linux"; then - if test "$machine" = "i386" -o "$machine" = "x86_64"; then - AC_ARG_ENABLE(dnative, [AS_HELP_STRING([--disable-dnative], - [do NOT compile with native DPMI support])]) - if test "$enable_dnative" != "no"; then - AC_MSG_NOTICE([Enabling native DPMI support...]) - AC_DEFINE(DNATIVE) - DNATIVE=1 - AC_SUBST(DNATIVE) - fi - - AC_DEFINE(USE_KVM) - KVM=1 - AC_SUBST(KVM) - fi -fi - -if test "$CONFIG_HOST" = "Darwin"; then - DOSEMU_LDFLAGS="$DOSEMU_LDFLAGS -Wl,-undefined,dynamic_lookup" -fi - -AC_ARG_ENABLE(mcontext, - AS_HELP_STRING([--disable-mcontext], [disable fast context switch])) -if test "$enable_mcontext" != "no"; then - AC_MSG_NOTICE([Enabling fast context switching...]) - AC_DEFINE(MCONTEXT) - MCONTEXT=1 - AC_SUBST(MCONTEXT) fi if test "$enable_asan" = "yes"; then AX_CHECK_LINK_FLAG([-fsanitize=address], [ DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fsanitize=address" - # working around this bug: - # https://github.com/google/sanitizers/issues/934 - # Linking to libstdc++ seems to be the cure. - LDFLAGS="$LDFLAGS -fsanitize=address -lstdc++" + LDFLAGS="$LDFLAGS -fsanitize=address" AC_MSG_NOTICE(enabling address sanitizer) ]) fi -if test "$enable_lsan" = "yes"; then - AX_CHECK_LINK_FLAG([-fsanitize=leak], [ - DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fsanitize=leak" - LDFLAGS="$LDFLAGS -fsanitize=leak" - AC_MSG_NOTICE(enabling leak sanitizer) - ]) -fi -if test "$enable_tsan" = "yes"; then - AX_CHECK_LINK_FLAG([-fsanitize=thread], [ - DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fsanitize=thread" - LDFLAGS="$LDFLAGS -fsanitize=thread" - AC_MSG_NOTICE(enabling thread sanitizer) - ]) -fi if test "$enable_ubsan" = "yes"; then AX_CHECK_LINK_FLAG([-fsanitize=undefined], [ DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fsanitize=undefined -fno-sanitize=alignment" @@ -728,9 +564,6 @@ fi AH_TEMPLATE([HAVE_ASSIGNABLE_STDERR], [ Define if stderr is not const ]) -AH_TEMPLATE([HAVE_OPTRESET], -[ Define if optreset is available ]) - AH_TEMPLATE([CONFIG_HOST], [ Define the host for which Dosemu is configured ]) @@ -758,21 +591,12 @@ AH_TEMPLATE(HAVE_EXECINFO, AH_TEMPLATE([USE_DL_PLUGINS], [ DEFINE this, if you want dynamically loaded plugins ]) +AH_TEMPLATE([HAVE_BACKTRACE], +[ Define this for backtrace() functionality ]) + AH_TEMPLATE([X86_EMULATOR], [ Define this to use the X86 CPU emulator ]) -AH_TEMPLATE([X86_JIT], -[ Define this to use the X86 JIT ]) - -AH_TEMPLATE([DNATIVE], -[ Define this to enable native DPMI back-end ]) - -AH_TEMPLATE([USE_KVM], -[ Define this to enable kvm support ]) - -AH_TEMPLATE([MCONTEXT], -[ Define this to enable libmcontext use ]) - AH_TEMPLATE([DISABLE_SYSTEM_WA], [ Define this to disable system-specific work-arounds that are unneeded on your system ]) diff --git a/debian/control b/debian/control index d850d7e..f35af4b 100644 --- a/debian/control +++ b/debian/control @@ -5,15 +5,19 @@ Maintainer: Stas Sergeev Standards-Version: 4.1.5 Build-Depends: git (>= 2.0), + bash, autoconf, autotools-dev, automake, make, + coreutils, linuxdoc-tools, bison, debhelper (>= 9~), flex, gawk, + sed, + findutils, libx11-dev, libxext-dev, libslang2-dev, @@ -22,6 +26,7 @@ Build-Depends: libasound2-dev, libsdl2-dev, libsdl2-ttf-dev, + libsdl2-image-dev, libfontconfig1-dev, ladspa-sdk, libfluidsynth-dev, @@ -31,25 +36,22 @@ Build-Depends: libbsd-dev, libreadline-dev, libjson-c-dev, - libb64-dev, binutils-dev, pkg-config, - fdpp-dev, - dj64-dev, - clang, - binutils-i686-linux-gnu + fdpp-dev Homepage: https://github.com/dosemu2/dosemu2 Package: dosemu2 Replaces: dosemu Conflicts: dosemu -Architecture: any +Architecture: i386 amd64 Depends: ${misc:Depends}, ${shlibs:Depends}, - fdpp, - dj64, - comcom64 + udev (>= 240), + bash, + coreutils, + comcom32 (>= 0.1~alpha2) Recommends:${shlibs-:Recommends}, ladspa-sdk, gdb, kbd, fluid-soundfont-gm, install-freedos Suggests: vde2, valgrind, install-otherdos diff --git a/debian/docs b/debian/docs index d7b4711..149589d 100644 --- a/debian/docs +++ b/debian/docs @@ -2,6 +2,7 @@ BUGS CONTRIBUTING.md COPYING COPYING.DOSEMU +INSTALL NEWS.md README.md THANKS diff --git a/debian/rules b/debian/rules index 34785c0..5f12b5f 100755 --- a/debian/rules +++ b/debian/rules @@ -1,20 +1,19 @@ #!/usr/bin/make -f export DH_ALWAYS_EXCLUDE=fonts.dir:fonts.alias -export CC=clang %: dh $@ --parallel --builddirectory=build override_dh_autoreconf: - ./autogen.sh + dh_autoreconf autoreconf -- -f -i -I m4 override_dh_auto_configure: dh_auto_configure -O--parallel -- \ + --enable-debug --disable-xbacktrace \ + --with-plugindir=/usr/lib/dosemu \ --with-x11fontdir=/usr/share/fonts/X11/misc override_dh_shlibdeps: dh_shlibdeps -X.so dh_shlibdeps -- -dRecommends -pshlibs- - -override_dh_dwz: diff --git a/default-configure b/default-configure index b376f3d..4abe12a 100755 --- a/default-configure +++ b/default-configure @@ -23,7 +23,7 @@ if [ ! -f $CONF_FILE ]; then fi CONF=`cat $CONF_FILE` -CONF=`printf "$CONF"| sed '/^config {/d' | sed '/^}/d' | tr '\n' ' ' ` +CONF=`echo -n "$CONF"| sed '/^config {/d' | sed '/^}/d' | tr '\n' ' ' ` SUFFIX="" while [ "$#" != "0" ]; do @@ -60,12 +60,6 @@ while [ "$1" != "" ]; do asan) if [ "$2" = "on" ]; then STRING="$STRING --enable-asan"; fi ;; - lsan) - if [ "$2" = "on" ]; then STRING="$STRING --enable-lsan"; fi - ;; - tsan) - if [ "$2" = "on" ]; then STRING="$STRING --enable-tsan"; fi - ;; ubsan) if [ "$2" = "on" ]; then STRING="$STRING --enable-ubsan"; fi ;; @@ -135,29 +129,13 @@ while [ "$1" != "" ]; do shift; shift; done -[ -f "$srcdir"/install-sh ] || "$srcdir"/autogen.sh || exit $? -if [ -z "$MAKE" ]; then - if [ `uname -s` = "FreeBSD" ]; then - MAKE=gmake - else - MAKE=make - fi -fi -if [ `uname -s` = "FreeBSD" ]; then - export CPPFLAGS="${CPPFLAGS} -I/usr/local/include" - export LDFLAGS="${LDFLAGS} -L/usr/local/lib" -fi -${MAKE} "$srcdir"/configure +[ -f "$srcdir"/configure ] || "$srcdir"/autogen.sh || exit $? +make "$srcdir"/configure STRING="$STRING --enable-plugins=$PLUGIN,$EXTRA_PLUGINS" if [ -n "$FDPP_STR" ]; then FDPP_STR=`echo $FDPP_STR | sed 's/^ *//'` STRING="$STRING --with-plugin-options=fdpp,\"$FDPP_STR\"" fi - -if [ -z "$CC" ] && which ccache; then - echo "Enabling ccache use" - export CC="ccache cc" -fi echo exec "$srcdir"/configure $STRING $SUFFIX eval exec "$srcdir"/configure $STRING $SUFFIX diff --git a/doc/README.html b/doc/README.html index 1512168..f9889ce 100644 --- a/doc/README.html +++ b/doc/README.html @@ -4343,14 +4343,15 @@ NAME="AEN650" >

In Windows, the mouse cursor is not always in sync with the native X mouse cursor. This problem can be easily avoided by enabling mouse grab. -There also exist an +There also exist an alternative mouse driver specially written to +work in ungrabbed mode: alternative mouse driver -specially written to work in ungrabbed mode under many emulators or -on a real machine.

https://github.com/stsp/win31-mouse-driver/tree/master/out. +This driver is not limited to use with dosemu2: it can be used with +any other emulator and under bare-metal machine.

in your dosemu.conf or .dosemurc.


4.2. Sound is crackling.

Solution: set -
    $_dos_up = (off)
-in your dosemu.conf or .dosemurc. -The only "explanation" we can provide, is a conspiracy theory that -prehistoric is trying to slander third-party DOSes that put LoL/SDA -to UMB.


5. Carmageddon

5.1. Timer is too fast during race


6. Simon 2

6.1. Game freezes at start.


7. Prince of Persia 2

7.1. Game slows down unbearably after some playing.


8. Cosmo game by Apogee Software

8.1. Cosmo's Cosmic Adventure doesn't start


9. Pinball Fantasies

9.1. Long start-up delay (like half a minute)


9.2. Black screen and hang after choosing the table.


9.3. Game doesn't see the Fx keys that should start the game.


10. WordPerfect 6.2

= 2.0 -BuildRequires: bdftopcf -BuildRequires: mkfontscale -BuildRequires: linuxdoc-tools -BuildRequires: readline-devel -BuildRequires: json-c-devel -BuildRequires: libb64-devel -BuildRequires: binutils -BuildRequires: binutils-x86_64-linux-gnu -BuildRequires: pkgconf-pkg-config -BuildRequires: fdpp-devel -BuildRequires: dj64-devel - -# our startup script is bash-specific -Requires: bash -Requires: comcom64 -Recommends: fluid-soundfont-gm -Suggests: timidity++ >= 2.14.0 -Recommends: ladspa -# ncurses-base is for terminfo -Recommends: ncurses-base -Recommends: gdb -Recommends: kbd -Suggests: valgrind -Recommends: install-freedos -Suggests: install-otherdos - -# cannot coexist with dosemu1 -Conflicts: dosemu - -%description -dosemu2 is an emulator for running DOS programs under linux. -It can also serve as a VM to boot various DOSes. - -%prep -%setup -T -b 0 -q -n dosemu2 - -%build -./autogen.sh -%configure -make %{?_smp_mflags} - -%check - -%install -mkdir -p %{buildroot}%{_sysconfdir}/X11/fontpath.d -make DESTDIR=%{buildroot} install - -%files -%defattr(-,root,root) -%{_bindir}/* -%{_mandir}/man1/* -%lang(ru) %dir %{_mandir}/ru -%lang(ru) %dir %{_mandir}/ru/man1 -%lang(ru) %{_mandir}/ru/man1/* -# Not using libdir here as we only install plugins, and their path hard-coded -%{_prefix}/lib/dosemu -%{_datadir}/dosemu -%{_datadir}/applications/dosemu.desktop -%{_datadir}/fonts/oldschool -%{_sysconfdir}/X11/fontpath.d/dosemu2* -%doc %{_docdir}/dosemu2 -%dir %{_sysconfdir}/dosemu -%config(noreplace) %{_sysconfdir}/dosemu/dosemu.conf - -%changelog -* Tue Apr 09 2024 Stas Sergeev 2.0pre9-2 -- - -* Tue Apr 09 2024 Stas Sergeev -- - -* Tue Apr 09 2024 Stas Sergeev 2.0pre9-1 -- new package built with tito - -* Sat Aug 20 2016 Stas Sergeev 2.0pre6-dev -(none) diff --git a/dosemu2.spec.rpkg b/dosemu2.spec.rpkg index 7030980..1371054 100644 --- a/dosemu2.spec.rpkg +++ b/dosemu2.spec.rpkg @@ -18,6 +18,7 @@ Source0: {{{ git_dir_archive }}} BuildRequires: SDL2-devel BuildRequires: SDL2_ttf-devel +BuildRequires: SDL2_image-devel BuildRequires: fontconfig-devel BuildRequires: libXext-devel BuildRequires: alsa-lib-devel @@ -28,7 +29,6 @@ BuildRequires: ladspa-devel BuildRequires: slang-devel BuildRequires: libslirp-devel BuildRequires: libieee1284-devel -BuildRequires: mt32emu-devel BuildRequires: libbsd-devel BuildRequires: gcc BuildRequires: bison @@ -44,18 +44,19 @@ BuildRequires: git >= 2.0 BuildRequires: bdftopcf BuildRequires: mkfontscale BuildRequires: linuxdoc-tools +BuildRequires: coreutils BuildRequires: readline-devel BuildRequires: json-c-devel -BuildRequires: libb64-devel -BuildRequires: binutils -BuildRequires: binutils-x86_64-linux-gnu +BuildRequires: binutils-devel BuildRequires: pkgconf-pkg-config BuildRequires: fdpp-devel -BuildRequires: dj64-devel +# require udev with kvm support +Requires: systemd-udev >= 234 # our startup script is bash-specific Requires: bash -Requires: comcom64 +Requires: coreutils +Requires: comcom32 Recommends: fluid-soundfont-gm Suggests: timidity++ >= 2.14.0 Recommends: ladspa @@ -79,7 +80,14 @@ It can also serve as a VM to boot various DOSes. %build ./autogen.sh -%configure +./configure --prefix=%{_prefix} --libdir=%{_libdir} \ + --sysconfdir=%{_sysconfdir} --docdir=%{_docdir}/%{name} \ + --enable-debug --disable-xbacktrace +# can't use %%configure because of this: +# https://bugzilla.redhat.com/show_bug.cgi?id=1343892 +# additionally have to use double-percent for comments: +# https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/Packagers_Guide/chap-Packagers_Guide-Spec_File_Reference-Comments.html +#%%configure make %{?_smp_mflags} %check @@ -95,8 +103,7 @@ make DESTDIR=%{buildroot} install %lang(ru) %dir %{_mandir}/ru %lang(ru) %dir %{_mandir}/ru/man1 %lang(ru) %{_mandir}/ru/man1/* -# Not using libdir here as we only install plugins, and their path hard-coded -%{_prefix}/lib/dosemu +%{_libdir}/dosemu %{_datadir}/dosemu %{_datadir}/applications/dosemu.desktop %{_datadir}/fonts/oldschool diff --git a/etc/dosemu.conf b/etc/dosemu.conf index 3c90f41..7556256 100644 --- a/etc/dosemu.conf +++ b/etc/dosemu.conf @@ -14,6 +14,8 @@ # ############################################################################## + + # Notes for editing this file: # # In $_xxx = (n) n is a numerical or boolean value @@ -23,17 +25,6 @@ # Please note that all options are commented out by default! # Remove the # in front of the $ to change an option. -# Path to the local directory. -# Note: this option is only valid in global config file. -# Default: "~/.dosemu" - -# $_local_dir = "~/.dosemu" - -# Name of the local config file under local directory. -# Note: this option is only valid in global config file. -# Default: "dosemurc" - -# $_dosemurc = "dosemurc" ############################################################################## ## CPU settings: define the CPU features to DOSEMU. @@ -68,6 +59,10 @@ # $_cpuemu = (0) +# if possible use Pentium cycle counter for timing. Default: off + +# $_rdtsc = (off) + # CPU speed, used in conjunction with the TSC # Default 0 = calibrated by dosemu, else given (e.g.166.666) @@ -244,42 +239,27 @@ # $_dosmem = (640) # Extended Memory size. This memory is accessible via int15h and can be -# used by himem.sys. -# Default: 8192 (8Mb) +# used by himem.sys and the internal XMS driver. +# Default: 8192 -# $_ext_mem = (8192) +# $_xms = (8192) -# XMS (internal driver) is only needed if you do not load -# himem.sys or another external XMS driver. Size in Kbytes. -# Default: 16384 (16Mb) - -# $_xms = (16384) - -# Enable 64K UMB at 0xa0000. +# Enable 64K UMB at 0a0000. # This is where the VGA graphics memory resides, so enabling this UMB # will leave you with text mode only. # Default: auto (enabled only if dosemu runs in text mode) # $_umb_a0 = (auto) -# Enable 32K UMB at 0xb0000. +# Enable 32K UMB at 0b0000. # This is where the MDA text memory used to reside, so some programs # write to that area without hesitation. Therefore it is rather risky # to enable that UMB: beware even of ansi.sys! -# Default: auto (means: enable only for dumb video mode) - -# $_umb_b0 = (auto) - -# Enable 32K UMB at 0xb8000. -# This is the text-mode video memory. -# It can be used as UMB only in dumb video mode. -# Use "auto" to get it enabled in that mode. -# And even in that case only few well-behaved programs will work. # Default: off -# $_umb_b8 = (off) +# $_umb_b0 = (off) -# Enable 16K UMB at 0xf0000. +# Enable 48K UMB at 0f0000. # This is where normally a read-only BIOS resides but the DOSEMU BIOS does # not need it. Some (very few) programs rely on this memory being read-only # (Prehistorik 2); to run such programs, disable this option. @@ -287,22 +267,6 @@ # $_umb_f0 = (on) -# Enable HMA usage and a20 gating. -# HMA is the ~64K area above 1Mb of RAM. -# Default: on - -# $_hma = (on) - -# Load DOS kernel to upper memory (UMB or HMA). -# 0 or off means load low, 1 means UMB, 2 means UMB+HMA. -# This gives more free conventional memory but may lead to incompatibilities. -# You can freely disable that option and most of the DOS memory will remain -# in UMB nevertheless (given the proper config.sys). -# Note: only relevant for fdpp. -# Default: 1 (use only UMB, minor incompatibilities) - -# $_dos_up = (1) - # EMS (expanded memory) size in Kbytes; # Warning: disabling EMS (off) is not recommended. Doing so will # give you the additional 64K of UMB space, but as a side-effect @@ -329,15 +293,23 @@ # $_ems_conv_pages = (24) -# DPMI memory size in Kbytes -# Default: 0x20000 (128Mb) +# DPMI memory size in Kbytes; default: 0x20000 # $_dpmi = (0x20000) -# DPMI base address -# Default: 0x20000000 (at 512Mb) +# Reserve linear address space for DPMI. +# This is mostly needed for HX extender to be able to load +# non-relocatable win32 binaries. +# Specify the DOS-relative address here or auto for reserve +# adjacent to DOS memory. +# Default: auto -# $_dpmi_base = (0x20000000) +# $_dpmi_lin_rsv_base = (auto) + +# Size of reserved linear address space for DPMI. +# Default: 0x8000 (reserve 32Mb) + +# $_dpmi_lin_rsv_size = (0x8000) # Some DJGPP-compiled programs have the NULL pointer dereference bugs. # They may work under Windows or QDPMI as these unfortunately do not @@ -383,11 +355,6 @@ # $_cli_timeout = (10) -# apply some tweaks on emulated timers to make some old games more reliable. -# See tweaks.html for more info. - -# $_timer_tweaks = (off) - ############################################################################## ## Terminal related settings @@ -423,7 +390,7 @@ # xterm, putty and compatibles window title. Default: %s - DOSEMU # where %s is the DOS program's name. Use "" to not change the title -# $_xterm_title = "%s - dosemu2" +# $_xterm_title = "%s - DOSEMU" ############################################################################## ## Keyboard related settings @@ -482,21 +449,14 @@ # $_mouse_baud = (0) -# alternative behaviour in ungrabbed mode -# May fix some problems with cursor positioning, but enabling mouse -# grab is always more reliable. -# Default: off - -# $_mouse_ungrab_tweak = (off) - ############################################################################## ## Joystick config # 1st and 2nd joystick device -# e.g. "/dev/input/js0" or default: "/dev/input/js0 /dev/input/js1" +# e.g. "/dev/js0" or default: "/dev/js0 /dev/js1" # (or "" if you don't want joystick support) -# $_joy_device = "/dev/input/js0 /dev/input/js1" +# $_joy_device = "/dev/js0 /dev/js1" # range for joystick axis readings, must be > 0, default: 1 @@ -524,9 +484,6 @@ # All "/dev/ttyXX" may be suffixed by the IRQ # used (instead of the default one), such as "/dev/ttyS2 irq 5" # or "/dev/ttyS3 irq 9". -# Note: you can use any file here, eg fifo or even a regular file. -# In case of reading a regular file, don't forget to put ^Z (0x1a) -# at the end or there will be no EOF. # # "pseudo" keyword may be used to force the pseudo-TTY mode. # A wrong but quick way to bypass the hardware flow control. @@ -537,14 +494,6 @@ # "virtual" keyword may be used to redirect the COM port to the terminal. # A wrong but quick way for the sysop to play his BBS door games locally. # -# "exec " execute command and pipe it to the serial port. -# For example "exec rxvt -pty-fd 0" launches rxvt that can communicate -# with that serial port. Can also be used to play door games locally. -# -# "pts " create pts and attach its pty to serial port. -# For example "pts /tmp/com1" creates /tmp/com1 for communicating -# with the serial port. -# # "mouse" keyword enables the serial mouse emulation on the specified port. # You can then use native mouse driver, like mouse.com. # Note: if you configured this as a second mouse ($_mouse_internal = (on)), @@ -557,15 +506,6 @@ # You can then dial to the IP addresses, which will establish the telnet # connection. # -# "nullmodem " - connect this port to port with a -# null-modem cable. You need to also set up port and connect -# it to this port the same way. -# -# "ro" - read-only. Write to the port is ignored unless the option below -# is set. -# -# "wrfile " - use file for com port output. -# # Default: "" # $_com1 = "" @@ -646,17 +586,13 @@ # MPU-401 base i/o port -# $_mpu_base = (0x300) +# $_mpu_base = (0x330) -# MT32 MPU-401 base i/o port - -# $_mpu_base_mt32 = (0x330) - -# MIDI synth mode for MPU-401 at $_mpu_base_mt32 +# MIDI synth mode # Supported values: "gm", "mt32" -# Default: "mt32" +# Default: "gm" -# $_midi_synth = "mt32" +# $_midi_synth = "gm" # MPU-401 irq for GM synth mode # Default: auto (which is equal to $_sb_irq) @@ -664,9 +600,9 @@ # $_mpu_irq = (auto) # MPU-401 irq for mt32 synth mode -# Default: 9 +# Default: 2 -# $_mpu_irq_mt32 = (9) +# $_mpu_irq_mt32 = (2) # Sound output driver. # Supported drivers: ao, sdl (if compiled in) @@ -676,12 +612,8 @@ # MIDI output drivers. # Comma-separated list of midi drivers to enable. -# Supported GM drivers: -# fluid, timidity, alsa_midi, oss_midi, pipe_midi -# Supported MT-32 drivers: -# munt, alsa_virmidi -# It is better to specify 2 drivers at once, one for GM and one for MT-32. -# Example: "alsa_midi,alsa_virmidi" +# Supported drivers: +# fluid, timidity, munt, alsa_midi, oss_midi, pipe_midi # Default: "" (which means auto) # Note: if you use $_wav_file option to record the sound and want # the rendered midi to also be recorded there, you need to select @@ -690,16 +622,6 @@ # $_midi_driver = "" -# fluidsynth soundfont path - -# $_fluid_sfont = "" - -# fluidsynth volume -# Values: 0 to 10 (larger than 10 is possible but results in distortion) -# Default: 6 - -# $_fluid_volume = (6) - # munt ROMs path. # Path to munt ROM files. # Default: "roms" (which means ~/.dosemu/roms) @@ -719,16 +641,12 @@ # $_opl2lpt_type = "opl2" # Sound and MIDI plugin parameters. -# Syntax: plugin1:param1=val1 plugin2:param2=val2..." +# Syntax: plugin1:param1=val1,plugin2:param2=val2..." # Description: dosemu implements many sound and midi plugins. # Some of them may be selected with the $_sound_driver and $_midi_driver # options above; some are managed by dosemu automatically. # This option allows to pass the parameters to any of them. # Example: "alsa_virmidi:dev_name=munt" -# If your /etc/asound.conf doesn't define the rawmidi device index, -# you can set it like in this example: -# Example: "alsa_midi:dev_name=hw:3,0 alsa_virmidi:dev_name=hw:3,1" -# You can disable some plugins this way: "alsa_virmidi:enabled=0" # Default: "" # $_snd_plugin_params = "" @@ -764,9 +682,9 @@ # $_pktdriver = (on) -# NE2000 emulation (experimental). Default: on +# NE2000 emulation (experimental). Default: off -# $_ne2k = (on) +# $_ne2k = (off) # Virtual networking type. "eth" for exclusive NIC access, "tap" for # using the TAP virtual device, "vde" for vde2 and "slirp" for slirp. @@ -789,12 +707,6 @@ # $_tapdev = "tap0" -# Network daemon socket name (for passt mainly). -# Set to "/tmp/passt_1.socket" to use with passt. -# Default: "" - -# $_netsock = "" - # vdeswitch socket name for packet driver in "vde" mode. # If empty string is specified, dosemu will try to set up the VDE switch # automatically. @@ -830,7 +742,7 @@ # Title in the top bar of the window. Default = "DOSEMU2" -# $_X_title = "dosemu2" +# $_X_title = "DOSEMU2" # Show name of running app in the top bar of the window. Default: on @@ -918,14 +830,6 @@ # $_X_background_pause = (off) -# Hide the Close button and disable the Close menu item - -# $_X_noclose = (off) - -# Disable resize by dragging window borders - -# $_X_noresize = (off) - ############################################################################## ## Settings specific to SDL video driver (dosemu -S) @@ -939,19 +843,6 @@ # $_SDL_fonts = "Flexi IBM VGA False, Flexi IBM VGA True" -# Show window controls. -# It is not a common need to disable them, and can be done at run-time -# by pressing Ctrl-Alt-b. -# Default: on - -# $_SDL_wcontrols = (on) - -# Enable native clipboard access. -# Can be toggled at run-time by pressing Ctrl-Alt-c. -# Default: off - -# $_SDL_clip_native = (off) - ############################################################################## ## Common video driver settings @@ -972,6 +863,12 @@ # [priv] list of portnumbers such as "0x1ce 0x1cf 0x238" or # "0x1ce range 0x280,0x29f 310" or "range 0x1a0,(0x1a0+15)". Default: "" +# $_ports = "device /dev/null fast 0x200" +# $_ports = $_ports, " device /dev/lp0 range 0x378 0x37a" +# The blank is important +# "device" means: if the ports are registered, open this device to block +# access. The open must be successful or access to the ports will be denied. +# If you know what you are doing, use /dev/null to fake a device to block # $_ports = "" diff --git a/etc/global.conf b/etc/global.conf index 852bc75..48a54ec 100644 --- a/etc/global.conf +++ b/etc/global.conf @@ -108,6 +108,7 @@ else if (strlen($_trace_mmio)) trace_mmio { $$_trace_mmio } endif cpuspeed $_cpuspeed + rdtsc $_rdtsc timer 0 mathco $_mathco @@ -130,17 +131,18 @@ else endif umb_a0 $_umb_a0 umb_b0 $_umb_b0 - umb_b8 $_umb_b8 umb_f0 $_umb_f0 - hma $_hma - dos_up $_dos_up dpmi $_dpmi - dpmi_base $_dpmi_base + dpmi_lin_rsv_base $_dpmi_lin_rsv_base + dpmi_lin_rsv_size $_dpmi_lin_rsv_size pm_dos_api 1 ignore_djgpp_null_derefs $_ignore_djgpp_null_derefs dosmem $_dosmem - ext_mem $_ext_mem - xms $_xms + if ($_ext_mem) + ext_mem $_ext_mem + else + ext_mem $_xms + endif if ($_emusys ne "") emusys $_emusys endif @@ -187,13 +189,11 @@ else fixed_aspect $_X_fixed_aspect vgaemu_memsize $_X_vgaemu_memsize lfb $_X_lfb pm_interface $_X_pm_interface mitshm $_X_mitshm background_pause $_X_background_pause fullscreen $_X_fullscreen - noclose $_X_noclose - noresize $_X_noresize $$xxx } ## SDL settings - SDL { sdl_hwrend $_SDL_hwrend sdl_fonts $_SDL_fonts sdl_wcontrols $_SDL_wcontrols sdl_clip_native $_SDL_clip_native } + SDL { sdl_hwrend $_SDL_hwrend sdl_fonts $_SDL_fonts } # video settings vga_fonts $$_force_vga_fonts @@ -224,19 +224,17 @@ else ## sound settings sound $_sound - sound_emu { sb_base $_sb_base + if ($_sound) + sound_emu { sb_base $_sb_base sb_irq $_sb_irq sb_dma $_sb_dma sb_hdma $_sb_hdma mpu_base $_mpu_base - mpu_base_mt32 $_mpu_base_mt32 midi_synth $_midi_synth mpu_irq $_mpu_irq mpu_irq_mt32 $_mpu_irq_mt32 sound_driver $_sound_driver midi_driver $_midi_driver - fluid_sfont $_fluid_sfont - fluid_volume $_fluid_volume munt_roms $_munt_roms opl2lpt_dev $_opl2lpt_dev opl2lpt_type $_opl2lpt_type @@ -244,7 +242,8 @@ else pcm_hpf $_pcm_hpf midi_file $_midi_file wav_file $_wav_file - } + } + endif ## joystick settings joystick_emu { joy_device $_joy_device joy_dos_min $_joy_dos_min @@ -254,7 +253,6 @@ else ## hacks cli_timeout $_cli_timeout timemode $_timemode - timer_tweaks $_timer_tweaks file_lock_limit $$_file_lock_limit lfn_support $_lfn_support @@ -268,33 +266,19 @@ else ttylocks { directory $$xxx namestub LCK.. } if (1) # no idea why but we need this... foreach $xxx (" ", "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16") + $yyy = "com", $xxx $zzz = "$_com", $xxx $zzz = $$zzz if (strlen($zzz)) - $jjj = "" - if (strchr($zzz, " ") > 0) - $yyy = strsplit($zzz, strchr($zzz, " ") + 1, 999) - $zzz = strdel($zzz, strchr($zzz, " "), 999) - else - $yyy = "" - endif - if (strchr($zzz, "/") == 0) - if (strchr($yyy, " ") > 0) - $jjj = strsplit($yyy, strchr($yyy, " ") + 1, 999) - $yyy = strdel($yyy, strchr($yyy, " "), 999) - endif - if (strlen($jjj) > 0) - serial { com $xxx device $zzz $$yyy $jjj } + if ($zzz eq "virtual") + serial { com $xxx virtual } + else if ($zzz eq "mouse") + serial { com $xxx mouse } + else if ($zzz eq "vmodem") + serial { com $xxx vmodem } else - serial { com $xxx device $zzz $$yyy } - endif - else - if (strlen($yyy) > 0) - serial { com $xxx $$zzz $yyy } - else - serial { com $xxx $$zzz } - endif - endif + serial { com $xxx device $$zzz } + endif endif endif done endif @@ -306,7 +290,7 @@ else $xxx = "baudrate ", $_mouse_baud endif $xxx = $xxx, " device '", $_mouse_dev, "'" - mouse { $$_mouse $$_mouse_flags $$xxx internaldriver mouse_ungrab_tweak $_mouse_ungrab_tweak } + mouse { $$_mouse $$_mouse_flags $$xxx internaldriver } else $xxx = "'", $_mouse_dev, "'" mouse { $$_mouse device $$xxx } @@ -428,9 +412,9 @@ else $xxx_pref = strdel($xxxx, strchr($xxxx, "*"), 999); $xxx_suff = strsplit($xxxx, strchr($xxxx, "*") + 1, 999); if (strchr($xxx_pref, "/") == 0) - $xxxx = shell("cd '", $xxx_pref, "' 2>/dev/null && printf *") + $xxxx = shell("cd '", $xxx_pref, "' 2>/dev/null && echo -n *") else - $xxxx = shell("cd '", $DOSEMU_IMAGE_DIR, "/", $xxx_pref, "' 2>/dev/null && printf *") + $xxxx = shell("cd '", $DOSEMU_IMAGE_DIR, "/", $xxx_pref, "' 2>/dev/null && echo -n *") endif if ($DOSEMU_SHELL_RETURN) abort "**** directory ", $xxx_pref, " not accessible"; @@ -444,27 +428,58 @@ else foreach $xxx ($LIST_DELIM, $xxxx) $xxx = $xxx_pref, $xxx, $xxx_suff if (!strncmp($xxx, "/dev/", 4)) - $yyy = strdel($xxx, strstr($xxx, ":"), 999); - $zzz = strsplit($xxx, strstr($xxx, ":"), 999); + $yyy = strdel($xxx, strstr($xxx, ":ro"), 999); + $zzz = strsplit($xxx, strstr($xxx, ":ro"), 999); if (strtol(strdel($xxx,0,8)) > 0) - disk { partition $yyy $$zzz }; + $yyy = "disk { partition ", $yyy; else - disk { wholedisk $yyy $$zzz }; + $yyy = "disk { wholedisk ", $yyy; endif + if (strlen($zzz)) + $yyy = $yyy, " readonly" + endif + $yyy = $yyy, " }"; + $$yyy; else - $yyy = strdel($xxx, strstr($xxx, ":"), 999); - $zzz = strsplit($xxx, strstr($xxx, ":"), 999); + $yyy3 = strdel($xxx, strstr($xxx, ":ro"), 999); + $yyy2 = strdel($yyy3, strstr($xxx, ":hdtype1"), 999); + $yyy1 = strdel($yyy2, strstr($xxx, ":hdtype2"), 999); + $yyy = strdel($yyy1, strstr($xxx, ":hdtype9"), 999); + $zzz = strsplit($xxx, strstr($xxx, ":ro"), 999); + $uuu = strsplit($xxx, strstr($xxx, ":hdtype1"), 999); + $vvv = strsplit($xxx, strstr($xxx, ":hdtype2"), 999); + $www = strsplit($xxx, strstr($xxx, ":hdtype9"), 999); if (strchr($yyy, "/") != 0) $yyyy = $DOSEMU_IMAGE_DIR, "/", $yyy $yyy = $yyyy endif shell("test -d '", $yyy, "'") if (!$DOSEMU_SHELL_RETURN) - disk { directory $yyy $$zzz }; + if (strlen($zzz)) + disk { directory $yyy readonly }; + else if (strlen($uuu)) + disk { directory $yyy hdtype1 }; + else if (strlen($vvv)) + disk { directory $yyy hdtype2 }; + else if (strlen($www)) + disk { directory $yyy hdtype9 }; + else + disk { directory $yyy }; + endif endif endif endif else shell("test -f '", $yyy, "'") if (!$DOSEMU_SHELL_RETURN) - disk { image $yyy $$zzz }; + if (strlen($zzz)) + disk { image $yyy readonly }; + else if (strlen($uuu)) + disk { image $yyy hdtype1 }; + else if (strlen($vvv)) + disk { image $yyy hdtype2 }; + else if (strlen($www)) + disk { image $yyy hdtype9 }; + else + disk { image $yyy }; + endif endif endif endif else abort "hdimage ", $yyy, " not found" endif @@ -557,7 +572,6 @@ else tapdev $_tapdev vdeswitch $_vdeswitch slirpargs $_slirpargs - netsock $_netsock vnet $_vnet pktdriver $_pktdriver ne2k $_ne2k diff --git a/etc/locales.conf b/etc/locales.conf index c8c3bc2..8ec8e90 100644 --- a/etc/locales.conf +++ b/etc/locales.conf @@ -1,7 +1,6 @@ { /* add your mappings below and send a patch */ "locales": [ - { "lang": "C", "codepage": "cp437", "country": 001 }, { "lang": "en_US", "codepage": "cp437", "country": 001 }, { "lang": "cs_CZ", "codepage": "cp852", "country": 042 }, { "lang": "af_ZA", "codepage": "cp858", "country": 785 }, @@ -61,7 +60,6 @@ { "lang": "nl_NL", "codepage": "cp858", "country": 031 }, { "lang": "nn_NO", "codepage": "cp858", "country": 047 }, { "lang": "no_NO", "codepage": "cp858", "country": 047 }, - { "lang": "pl_PL", "codepage": "cp852", "country": 048 }, { "lang": "pt_BR", "codepage": "cp858", "country": 055 }, { "lang": "pt_PT", "codepage": "cp858", "country": 351 }, { "lang": "sv_FI", "codepage": "cp858", "country": 358 }, diff --git a/git-rev.sh b/git-rev.sh index 9b110aa..af49811 100755 --- a/git-rev.sh +++ b/git-rev.sh @@ -4,14 +4,14 @@ if [ $# != 2 ]; then echo "Usage: $0 " >&2 exit 1 fi -DATE=`git -C $1 log -1 --format=%cd --date=format-local:'%m%d%H%M.%S'` +DATE=`git -C $1 log -1 --format=%cd --date=rfc` if [ $? != 0 ]; then echo "Non-git builds deprecated" >&2 exit 1 fi TSTAMP=$2/.tstamp -if ! touch -t "$DATE" $TSTAMP 2>/dev/null; then - echo "touch doesnt support -t, build may be incomplete" >&2 +if ! touch --date="$DATE" $TSTAMP 2>/dev/null; then + echo "touch doesnt support --date, build may be incomplete" >&2 if [ ! -f "$TSTAMP" ]; then touch $TSTAMP fi diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..4d4a951 --- /dev/null +++ b/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-05-14.22 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# 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 +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/m4/m4_ax_prog_cc_for_build.m4 b/m4/m4_ax_prog_cc_for_build.m4 deleted file mode 100644 index 1db8d73..0000000 --- a/m4/m4_ax_prog_cc_for_build.m4 +++ /dev/null @@ -1,155 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PROG_CC_FOR_BUILD -# -# DESCRIPTION -# -# This macro searches for a C compiler that generates native executables, -# that is a C compiler that surely is not a cross-compiler. This can be -# useful if you have to generate source code at compile-time like for -# example GCC does. -# -# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything -# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). -# The value of these variables can be overridden by the user by specifying -# a compiler with an environment variable (like you do for standard CC). -# -# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object -# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if -# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are -# substituted in the Makefile. -# -# LICENSE -# -# Copyright (c) 2008 Paolo Bonzini -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 21 - -AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) -AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_CPP])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl - -dnl Use the standard macros, but make them use other variable names -dnl -pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl -pushdef([ac_cv_prog_cc_c89], ac_cv_build_prog_cc_c89)dnl -pushdef([ac_cv_prog_cc_c99], ac_cv_build_prog_cc_c99)dnl -pushdef([ac_cv_prog_cc_c11], ac_cv_build_prog_cc_c11)dnl -pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl -pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl -pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl -pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl -pushdef([ac_cv_c_compiler_gnu], ac_cv_build_c_compiler_gnu)dnl -pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl -pushdef([ac_cv_objext], ac_cv_build_objext)dnl -pushdef([ac_exeext], ac_build_exeext)dnl -pushdef([ac_objext], ac_build_objext)dnl -pushdef([CC], CC_FOR_BUILD)dnl -pushdef([CPP], CPP_FOR_BUILD)dnl -pushdef([GCC], GCC_FOR_BUILD)dnl -pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl -pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl -pushdef([EXEEXT], BUILD_EXEEXT)dnl -pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl -pushdef([OBJEXT], BUILD_OBJEXT)dnl -pushdef([host], build)dnl -pushdef([host_alias], build_alias)dnl -pushdef([host_cpu], build_cpu)dnl -pushdef([host_vendor], build_vendor)dnl -pushdef([host_os], build_os)dnl -pushdef([ac_cv_host], ac_cv_build)dnl -pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl -pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl -pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl -pushdef([ac_cv_host_os], ac_cv_build_os)dnl -pushdef([ac_tool_prefix], ac_build_tool_prefix)dnl -pushdef([am_cv_CC_dependencies_compiler_type], am_cv_build_CC_dependencies_compiler_type)dnl -pushdef([am_cv_prog_cc_c_o], am_cv_build_prog_cc_c_o)dnl -pushdef([cross_compiling], cross_compiling_build)dnl - -cross_compiling_build=no - -ac_build_tool_prefix= -AS_IF([test -n "$build"], [ac_build_tool_prefix="$build-"], - [test -n "$build_alias"],[ac_build_tool_prefix="$build_alias-"]) - -AC_LANG_PUSH([C]) - -dnl The pushdef([ac_cv_c_compiler_gnu], ...) currently does not cover -dnl the use of this variable in _AC_LANG_COMPILER_GNU called by -dnl AC_PROG_CC. Unset this cache variable temporarily as a workaround. -was_set_c_compiler_gnu=${[ac_cv_c_compiler_gnu]+y} -AS_IF([test ${was_set_c_compiler_gnu}], - [saved_c_compiler_gnu=$[ac_cv_c_compiler_gnu] - AS_UNSET([[ac_cv_c_compiler_gnu]])]) - -AC_PROG_CC - -dnl Restore ac_cv_c_compiler_gnu -AS_IF([test ${was_set_c_compiler_gnu}], - [[ac_cv_c_compiler_gnu]=$[saved_c_compiler_gnu]]) - -_AC_COMPILER_EXEEXT -_AC_COMPILER_OBJEXT -AC_PROG_CPP - -dnl Restore the old definitions -dnl -popdef([cross_compiling])dnl -popdef([am_cv_prog_cc_c_o])dnl -popdef([am_cv_CC_dependencies_compiler_type])dnl -popdef([ac_tool_prefix])dnl -popdef([ac_cv_host_os])dnl -popdef([ac_cv_host_vendor])dnl -popdef([ac_cv_host_cpu])dnl -popdef([ac_cv_host_alias])dnl -popdef([ac_cv_host])dnl -popdef([host_os])dnl -popdef([host_vendor])dnl -popdef([host_cpu])dnl -popdef([host_alias])dnl -popdef([host])dnl -popdef([OBJEXT])dnl -popdef([LDFLAGS])dnl -popdef([EXEEXT])dnl -popdef([CPPFLAGS])dnl -popdef([CFLAGS])dnl -popdef([GCC])dnl -popdef([CPP])dnl -popdef([CC])dnl -popdef([ac_objext])dnl -popdef([ac_exeext])dnl -popdef([ac_cv_objext])dnl -popdef([ac_cv_exeext])dnl -popdef([ac_cv_c_compiler_gnu])dnl -popdef([ac_cv_prog_cc_g])dnl -popdef([ac_cv_prog_cc_cross])dnl -popdef([ac_cv_prog_cc_works])dnl -popdef([ac_cv_prog_cc_c89])dnl -popdef([ac_cv_prog_gcc])dnl -popdef([ac_cv_prog_CPP])dnl - -dnl restore global variables ac_ext, ac_cpp, ac_compile, -dnl ac_link, ac_compiler_gnu (dependant on the current -dnl language after popping): -AC_LANG_POP([C]) - -dnl Finally, set Makefile variables -dnl -AC_SUBST(BUILD_EXEEXT)dnl -AC_SUBST(BUILD_OBJEXT)dnl -AC_SUBST([CFLAGS_FOR_BUILD])dnl -AC_SUBST([CPPFLAGS_FOR_BUILD])dnl -AC_SUBST([LDFLAGS_FOR_BUILD])dnl -]) diff --git a/man/Makefile b/man/Makefile index 53592e1..aa13d34 100644 --- a/man/Makefile +++ b/man/Makefile @@ -9,8 +9,7 @@ MANPAGES = dosemu.1 dosemu.bin.1 ru/dosemu.1 ru/dosemu.bin.1 default all: $(MANPAGES) .NOTPARALLEL: $(MANPAGES) -$(MANPAGES): $(top_builddir)/config.status $(wildcard $(top_srcdir)/man/*.1.in) \ - $(wildcard $(top_srcdir)/man/ru/*.1.in) +$(MANPAGES): $(top_builddir)/config.status $(wildcard $(top_srcdir)/man/*.1.in) cd $(top_builddir) && ./config.status install: all @@ -25,5 +24,6 @@ install: all clean realclean: for i in `ls $(top_srcdir)/man/*.1.in $(top_srcdir)/man/ru/*.1.in` ; do \ - rm -f `echo $$i | sed -E -e 's=$(top_srcdir)/man/(.+).in$$=\1='`; \ + rm -f `echo $$i | sed -s -e 's/\.in$$//' \ + -e 's=$(top_srcdir)/man/=='`; \ done diff --git a/man/dosemu.1.in b/man/dosemu.1.in index d53cea0..e557aa6 100644 --- a/man/dosemu.1.in +++ b/man/dosemu.1.in @@ -1,7 +1,7 @@ .\" -*- nroff -*- (This is for Emacs) .TH DOSEMU 1 "@RELEASE_DATE@" "Version @PACKAGE_VERSION@" "DOS Emulation" .SH NAME -dosemu \- run DOS and DOS programs under Linux +dosemu, xdosemu \- run DOS and DOS programs under Linux .SH SYNOPSIS .B dosemu [ @@ -15,19 +15,31 @@ dosemu \- run DOS and DOS programs under Linux .B \-s ] [ -.I env1=val1 -.I ... +.B \-install +.I [ bootdir ] ] [ -.I unix_path_to_dos_prog -[ -.I -- -] -[ -.I dos_cmd_args -] +.B args ] .PP +.B xdosemu +[ +.B \-dumb +] +[ +.B \-input +.I keystroke-string +] +[ +.B \-s +] +[ +.B \-install +.I [ bootdir ] +] +[ +.B args +] .SH DESCRIPTION .B dosemu is the wrapper script for @@ -35,6 +47,9 @@ is the wrapper script for (1) which invokes the Linux dos emulator, also known as .BR DOSEMU . +The wrapper also takes care of (eventually) installing the private instance of +.BR DOSEMU +in the user's $HOME, if this doesn't exist. .br .SH OPTIONS @@ -68,7 +83,17 @@ of the string look at README.txt. Invoke dosemu via sudo. This is necessary to get access to certain I/O ports and to get graphics on the Linux console. Please refer to the documentation (INSTALL and README.txt) to see which files need to be adjusted before -attempting this. +attempting this. +.TP +.I -install [ bootdir ] +launched as part of a systemwide installation, this option (re-)installs +a DOS that is used in DOSEMU (this can be the DOSEMU distributed +FreeDOS or any proprietary DOS, which is bootable via fatfs). +.I bootdir +is the base name of a directory. The symbolic link ~/.dosemu/drives/c +will be changed to point to this directory. +Re-installing is only rarely necessary, since in practise the symbolic +link(s) will automatically point to updated files. .TP .I --version print version of dosemu and list of available options. diff --git a/man/dosemu.bin.1.in b/man/dosemu.bin.1.in index ebe46a1..4ad84d1 100644 --- a/man/dosemu.bin.1.in +++ b/man/dosemu.bin.1.in @@ -64,7 +64,11 @@ dosemu.bin, dosdebug \- run DOS and DOS programs under Linux ] [ .B \-i -.I \h'-1' input_data +.I \h'-1'[bootdir] +] +[ +.B \-U +.I number of path components ] [ .B \-E @@ -72,20 +76,7 @@ dosemu.bin, dosdebug \- run DOS and DOS programs under Linux ] [ .B \-K -.I unix_path[:dos_path] -] -[ -.I env1=val1 -.I ... -] -[ -.I unix_path_to_dos_prog -[ -.I -- -] -[ -.I dos_cmd_args -] +.I unix_path ] .sp .B dosdebug @@ -170,28 +161,18 @@ command. .TP .I -K unix_path[:dos_path] Specify unix path for the program running with \-E. -You can omit \-E and specify the full unix path with \-K, but it is -not recommended and may be removed in the future. You need to specify -a directory path to \-K. -.br -If dos_path is specified, then it is used as a current directory when -invoking the command. If unix_path is empty then the drive letter is -taken from dos_path: +You can omit \-E and specify the full unix path with \-K, but passing +command-line arguments via \-K is not recommended and may be removed +in the future. The following may nevertheless work: .nf -dosemu -K :C:\\\\games\\\\carma -E carma.exe +dosemu -K "/home/joeuser/dosemu/freedos/bin/xcopy.exe my_file my_dir" .fi -This runs carma.exe from C:\\games\\carma +If dos_path is specified, then it is used as a current directory when +invoking the command. .TP -.I -T[flags] -Sets flags for -E and -K commands. "flags" is the string of the -following chars: - -1: don't terminate DOSEMU after running the command specified either +.I -T +Don't terminate DOSEMU after running the command specified either with -E or -K. - -h: try to load the specified command into UMB (loadhigh). - -If -T is specified without flags, then "1h" flags string is assumed. .TP .I -q Quiet mode. Suppress all DOS output except that of the command specified @@ -219,12 +200,10 @@ Bypass the default directory for bootdirectory and hdimages (DOSEMU_IMAGE_DIR) and use this directory instead. .TP .I -f -Parse this config-file instead of .dosemurc. If -n is also specified, then -this config file is parsed instead of the primary dosemu.conf. +Parse this config-file instead of .dosemurc .TP .I -n -Bypass (don't use) default user's config .dosemurc. The config specified -with -f is still parsed, but in that case it replaces the main dosemu.conf. +Bypass (don't use) user's config .dosemurc. .TP .I -L Writes provided to a log. @@ -255,12 +234,15 @@ because it is expected to be .I one argument. .TP -.I -i input_data -Type -.I input_data -on the emulated keyboard. Use \\r for Enter. Various other special escapes -are available, for example you can insert pauses with "\\p10;" where -10 is a delay in tens of milliseconds. +.I -i[bootdir] +launched as part of a systemwide installation, this option (re-)installs +a DOS that is used in DOSEMU (this can be the DOSEMU distributed +FreeDOS or any proprietary DOS, which is bootable via fatfs). +.I bootdir +is the base name of a directory. The symbolic link ~/.dosemu/drives/c +will be changed to point to this directory. +Re-installing is only rarely necessary, since in practise the symbolic +link(s) will automatically point to updated files. .TP .I -D specify which Debugging messages to allow/suppress @@ -309,13 +291,11 @@ DIRECT HARDWARE ACCESS TO DOS PROGRAMS MAY GIVE THESE THE ABILITY TO LOCK YOUR COMPUTER, OR (IN RARE CASES) EVEN DAMAGE HARDWARE. ONLY TRUSTED LOCAL USERS SHOULD BE GIVEN THIS TYPE OF ACCESS. .TP -.I -t[de[flag]] +.I -t[de] terminal mode: run using the S-Lang library by default, or, if 'd' is specified - use "dumb" terminal mode. If 'de' is specified, use stderr in dumb terminal mode, except for the output of the -program started with -E that still goes to stdout. If 'de2' is -specified (flag==2), then also the output of -E-started program -goes to stderr. +program started with -E that still goes to stdout. .TP .I -V use direct console video with VGA graphics and use the native graphics diff --git a/man/ru/dosemu.1.in b/man/ru/dosemu.1.in index 9314f2c..f9343d0 100644 --- a/man/ru/dosemu.1.in +++ b/man/ru/dosemu.1.in @@ -1,7 +1,7 @@ .\" -*- nroff -*- (This is for Emacs) .TH DOSEMU 1 "@RELEASE_DATE@" "Версия @PACKAGE_VERSION@" "Эмуляция DOS" .SH ИМЯ -dosemu \- запускает DOS и приложения DOS под Linux +dosemu, xdosemu \- запускает DOS и приложения DOS под Linux .SH СИНТАКСИС .B dosemu [ @@ -15,18 +15,31 @@ dosemu \- запускает DOS и приложения DOS под Linux .I строка_клавиш ] [ -.I env1=val1 -.I ... +.B \-install +.I загрузочный_каталог ] [ -.I unix_путь_к_дос_программе -[ -.I -- -] -[ -.I аргументы_дос_команды +.B аргументы ] .PP +.B xdosemu +[ +.B \-dumb +] +[ +.B \-home +] +[ +.B \-input +.I строка_клавиш +] +[ +.B \-install +.I загрузочный_каталог +] +[ +.B аргументы +] .SH ОПИСАНИЕ .B dosemu является оберточным скриптом для @@ -75,6 +88,16 @@ dosemu \- запускает DOS и приложения DOS под Linux нажатия на клавишу F8. Так в этом случае всегда необходимо добавлять символ "\\r" в начало строки_клавиш. Как побочный эффект это даст проход ожидания "F8", и FreeDos будет загружаться быстрее ;-) +.TP +.I -install +стартуя как часть общесистемной установки, такая опция устанавливает +частный вариант отличающегося от распространяемого с DOSEMU dosemu-freedos-bin +DOS (возможен любой проприетарный DOS, который загружается через fatfs). +.I загрузочный_каталог +является базовым именем каталога, пользователи имеют возможность +установки его внутри аналогичного каталога, где будет создан вариант +DOSEMU. Настройки в файле conf/dosemu.conf будут перекрыты этим +загрузочным каталогом. .SH АВТОРЫ .B DOSEMU diff --git a/man/ru/dosemu.bin.1.in b/man/ru/dosemu.bin.1.in index 4d3e529..95bade6 100644 --- a/man/ru/dosemu.bin.1.in +++ b/man/ru/dosemu.bin.1.in @@ -63,24 +63,8 @@ dosemu.bin, dosdebug \- запускает DOS и приложения DOS по .I опции_настройки ] [ -.B \-E -.I dos-команда -] -[ -.B \-K -.I unix_путь[:dos_путь] -] -[ -.I env1=val1 -.I ... -] -[ -.I unix_путь_к_дос_программе -[ -.I -- -] -[ -.I аргументы_дос_команды +.B \-U +.I вх_канал[:вых_канал] ] .sp .B dosdebug @@ -154,31 +138,6 @@ facilities, смотрите монтировать путь path как дополнительный диск в DOS. Можно указывать более одного раза. .TP -.I -E dos-команда -Запуск команды DOS в DOSEMU. -Путь к бинарнику можно указать с помощью опции \-K. -Например, -.nf -dosemu -K /home/joeuser/dosemu/freedos/bin -E "xcopy my_file my_dir" -.fi -запустит /home/joeuser/dosemu/freedos/bin/xcopy.exe с 2 аргументами. -.br -Замечание: это только работает с дефолтным autoexec.bat, в котором -есть вызов "system \-e". -.TP -.I -K unix_путь[:dos_путь] -Указать путь unix к программе, запускаемой через \-E. -Можно не использовать \-E, а указать полный путь через \-K, но это не -рекомендуется, и может быть удалено в будущем. Указывать в \-K надо -только путь к каталогу. -.br -Если указан dos_путь, тогда он используется в качестве директории запуска -dos-программы. Если unix_путь не указан, то буква диска берётся из dos_пути: -.nf -dosemu -K :C:\\\\games\\\\carma -E carma.exe -.fi -Так запустится carma.exe из C:\\games\\carma -.TP .I -V использовать VGA спефицичную оптимизацию видео .TP @@ -209,14 +168,7 @@ dosemu.users) и использовать предоставленный кат имеет флага suid-root). .TP .I -f -Разобрать предоставленный конфигурационный файл вместо .dosemurc. Если -задействована опция -n, то указанный здесь конфигурационный файл будет -использован вместо основного dosemu.conf. -.TP -.I -n -Пропустить (не разбирать) пользовательский файл конфигурации .dosemurc. -Конфигурационный файл, указанный в -f, будет разобран, но, в этом случае, -он заменит основной конфиг dosemu.conf. +Разобрать предоставленный настроечный файл вместо .dosemurc .TP .I -L Записывает в лог-файл. @@ -248,14 +200,6 @@ dosemu.users) и использовать предоставленный кат .I один аргумент. .TP -.I -i input_data -Вводит -.I input_data -с эмулируемой клавиатуры. Можно использовать \\r в качестве Enter. -Так же обрабатываются другие эскейп-последовательности, например -можно вставлять задержки с помощью конструкций вида "\\p10;", где -10 - величина задержки в десятках миллисекунд. -.TP .I -D определяет какие отладочные сообщения позволить, а какие запретить .TP @@ -297,6 +241,53 @@ DOSEMU будет затем заблокирован перед переход .B DOSEMU в режим 286.) .TP +.I -U +определяет входной и выходной каналы для асинхронного управления +.B DOSEMU +из других процессов. Формат такой (без пробелов между словами): +.TP + вх_канал:вых_канал + +где `:вых_канал' может быть опущен. В последнем случае можно не ожидать +обратной связи от +.B DOSEMU. + +По соображениям безопастности +.B DOSEMU +не создает именованные каналы самому себе, так пользователь отвечает за +установку корректных прав доступа на каналы. Заметьте, что при использовании +этих опций, инородный процесс может контроллировать сессию +.B DOSEMU +(типа ввода с клавиатуры). Опция будет следоватьльно использована только +внешними интерфейсами (типа kdos), которые вначале содадут соответствующие +именованные каналы и затем запустят на исполнение +.B DOSEMU. +Специальные управляющяя команда ( +.I ack on +) может быть использована, чтобы принудить +.B DOSEMU +возвратить признаки установки связи через `вых_канал' такой, чтобы внешний +интерфейс знал когда управляющая команда началась или закончилась и была ли +она успешна. Формат такого диалога признаков показан ниже +.TP + SYN: <имя_команды> +.TP + <различный вывод от команды> +.TP + ACK: code=n + +где +.I n +равно 0 в случае успеха. +Простой управляющий терминал, который служит как пример, замещается программой +.I dosctrl. +Она берет только два канала как аргументы и дает возможность затем +вводить управляющие команды, из которых `help' наиболее важна ;-) +Заметьте, +.I dosctrl +не запускает на выполнение +.B DOSEMU, +что необходимо сделать вручную. .PD 1 .SH ЖЕСТКИЕ ДИСКИ diff --git a/plugin_list b/plugin_list index 444db4e..98f60e5 100644 --- a/plugin_list +++ b/plugin_list @@ -21,4 +21,3 @@ doscmd periph debugger fdpp -dj64 diff --git a/scripts/aconf.sh b/scripts/aconf.sh index 3a67749..2a539af 100755 --- a/scripts/aconf.sh +++ b/scripts/aconf.sh @@ -1,5 +1,3 @@ -#!/bin/sh - if [ $# != 2 ]; then exit 1 fi diff --git a/scripts/buildwithfdpp.sh b/scripts/buildwithfdpp.sh index 1b69bcd..1abd064 100755 --- a/scripts/buildwithfdpp.sh +++ b/scripts/buildwithfdpp.sh @@ -50,7 +50,7 @@ fi # make distclean if grep -q fdpp-build-path default-configure ; then - CC=clang ./default-configure -d fdpp-build-path=${FDPP_LIBRARY_SOURCE}/fdpp \ + ./default-configure -d fdpp-build-path=${FDPP_LIBRARY_SOURCE}/fdpp \ fdpp-include-path=${FDPP_LIBRARY_SOURCE}/include && make else [ -d pkgconfig ] || mkdir pkgconfig @@ -60,5 +60,5 @@ else -e "s,^includedir=.*$,includedir=${FDPP_LIBRARY_SOURCE},g" \ ${FDPP_LIBRARY_SOURCE}/fdpp/fdpp.pc > pkgconfig/fdpp.pc - env PKG_CONFIG_PATH=`pwd`/pkgconfig CC=clang ./default-configure -d && make + env PKG_CONFIG_PATH=`pwd`/pkgconfig ./default-configure -d && make fi diff --git a/scripts/config.guess b/scripts/config.guess deleted file mode 100755 index f50dcdb..0000000 --- a/scripts/config.guess +++ /dev/null @@ -1,1480 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright 1992-2018 Free Software Foundation, Inc. - -timestamp='2018-02-24' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. -# -# You can get the latest version of this script from: -# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess -# -# Please send patches to . - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Options: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2018 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > "$dummy.c" ; - for c in cc gcc c89 c99 ; do - if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "$UNAME_SYSTEM" in -Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu - - eval "$set_cc_for_build" - cat <<-EOF > "$dummy.c" - #include - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #else - LIBC=gnu - #endif - EOF - eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" - - # If ldd exists, use it to detect musl libc. - if command -v ldd >/dev/null && \ - ldd --version 2>&1 | grep -q ^musl - then - LIBC=musl - fi - ;; -esac - -# Note: order is significant - the case branches are not exclusive. - -case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - "/sbin/$sysctl" 2>/dev/null || \ - "/usr/sbin/$sysctl" 2>/dev/null || \ - echo unknown)` - case "$UNAME_MACHINE_ARCH" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - earmv*) - arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` - endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` - machine="${arch}${endian}"-unknown - ;; - *) machine="$UNAME_MACHINE_ARCH"-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently (or will in the future) and ABI. - case "$UNAME_MACHINE_ARCH" in - earm*) - os=netbsdelf - ;; - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval "$set_cc_for_build" - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # Determine ABI tags. - case "$UNAME_MACHINE_ARCH" in - earm*) - expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "$UNAME_VERSION" in - Debian*) - release='-gnu' - ;; - *) - release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "$machine-${os}${release}${abi}" - exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" - exit ;; - *:LibertyBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" - exit ;; - *:MidnightBSD:*:*) - echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" - exit ;; - *:ekkoBSD:*:*) - echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" - exit ;; - *:SolidBSD:*:*) - echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd"$UNAME_RELEASE" - exit ;; - *:MirBSD:*:*) - echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" - exit ;; - *:Sortix:*:*) - echo "$UNAME_MACHINE"-unknown-sortix - exit ;; - *:Redox:*:*) - echo "$UNAME_MACHINE"-unknown-redox - exit ;; - mips:OSF1:*.*) - echo mips-dec-osf1 - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE=alpha ;; - "EV4.5 (21064)") - UNAME_MACHINE=alpha ;; - "LCA4 (21066/21068)") - UNAME_MACHINE=alpha ;; - "EV5 (21164)") - UNAME_MACHINE=alphaev5 ;; - "EV5.6 (21164A)") - UNAME_MACHINE=alphaev56 ;; - "EV5.6 (21164PC)") - UNAME_MACHINE=alphapca56 ;; - "EV5.7 (21164PC)") - UNAME_MACHINE=alphapca57 ;; - "EV6 (21264)") - UNAME_MACHINE=alphaev6 ;; - "EV6.7 (21264A)") - UNAME_MACHINE=alphaev67 ;; - "EV6.8CB (21264C)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8AL (21264B)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8CX (21264D)") - UNAME_MACHINE=alphaev68 ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE=alphaev69 ;; - "EV7 (21364)") - UNAME_MACHINE=alphaev7 ;; - "EV7.9 (21364A)") - UNAME_MACHINE=alphaev79 ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix"$UNAME_RELEASE" - exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux"$UNAME_RELEASE" - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval "$set_cc_for_build" - SUN_ARCH=i386 - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH=x86_64 - fi - fi - echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos"$UNAME_RELEASE" - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos"$UNAME_RELEASE" - ;; - sun4) - echo sparc-sun-sunos"$UNAME_RELEASE" - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos"$UNAME_RELEASE" - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint"$UNAME_RELEASE" - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint"$UNAME_RELEASE" - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint"$UNAME_RELEASE" - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten"$UNAME_RELEASE" - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten"$UNAME_RELEASE" - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix"$UNAME_RELEASE" - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix"$UNAME_RELEASE" - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix"$UNAME_RELEASE" - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval "$set_cc_for_build" - sed 's/^ //' << EOF > "$dummy.c" -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o "$dummy" "$dummy.c" && - dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`"$dummy" "$dummyarg"` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos"$UNAME_RELEASE" - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] - then - if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ - [ "$TARGET_BINARY_INTERFACE"x = x ] - then - echo m88k-dg-dgux"$UNAME_RELEASE" - else - echo m88k-dg-dguxbcs"$UNAME_RELEASE" - fi - else - echo i586-dg-dgux"$UNAME_RELEASE" - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" - fi - echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval "$set_cc_for_build" - sed 's/^ //' << EOF > "$dummy.c" - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/lslpp ] ; then - IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | - awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` - else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" - fi - echo "$IBM_ARCH"-ibm-aix"$IBM_REV" - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` - case "$UNAME_MACHINE" in - 9000/31?) HP_ARCH=m68000 ;; - 9000/[34]??) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "$sc_cpu_version" in - 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 - 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "$sc_kernel_bits" in - 32) HP_ARCH=hppa2.0n ;; - 64) HP_ARCH=hppa2.0w ;; - '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "$HP_ARCH" = "" ]; then - eval "$set_cc_for_build" - sed 's/^ //' << EOF > "$dummy.c" - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ "$HP_ARCH" = hppa2.0w ] - then - eval "$set_cc_for_build" - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH=hppa2.0w - else - HP_ARCH=hppa64 - fi - fi - echo "$HP_ARCH"-hp-hpux"$HPUX_REV" - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux"$HPUX_REV" - exit ;; - 3050*:HI-UX:*:*) - eval "$set_cc_for_build" - sed 's/^ //' << EOF > "$dummy.c" - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo "$UNAME_MACHINE"-unknown-osf1mk - else - echo "$UNAME_MACHINE"-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi"$UNAME_RELEASE" - exit ;; - *:BSD/OS:*:*) - echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case "$UNAME_PROCESSOR" in - amd64) - UNAME_PROCESSOR=x86_64 ;; - i386) - UNAME_PROCESSOR=i586 ;; - esac - echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" - exit ;; - i*:CYGWIN*:*) - echo "$UNAME_MACHINE"-pc-cygwin - exit ;; - *:MINGW64*:*) - echo "$UNAME_MACHINE"-pc-mingw64 - exit ;; - *:MINGW*:*) - echo "$UNAME_MACHINE"-pc-mingw32 - exit ;; - *:MSYS*:*) - echo "$UNAME_MACHINE"-pc-msys - exit ;; - i*:PW*:*) - echo "$UNAME_MACHINE"-pc-pw32 - exit ;; - *:Interix*:*) - case "$UNAME_MACHINE" in - x86) - echo i586-pc-interix"$UNAME_RELEASE" - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix"$UNAME_RELEASE" - exit ;; - IA64) - echo ia64-unknown-interix"$UNAME_RELEASE" - exit ;; - esac ;; - i*:UWIN*:*) - echo "$UNAME_MACHINE"-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; - *:GNU:*:*) - # the GNU system - echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" - exit ;; - i*86:Minix:*:*) - echo "$UNAME_MACHINE"-pc-minix - exit ;; - aarch64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - arm*:Linux:*:*) - eval "$set_cc_for_build" - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi - else - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - cris:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" - exit ;; - crisv32:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" - exit ;; - e2k:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - frv:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - hexagon:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - i*86:Linux:*:*) - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" - exit ;; - ia64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - k1om:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - m32r*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - m68*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval "$set_cc_for_build" - sed 's/^ //' << EOF > "$dummy.c" - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" - test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } - ;; - mips64el:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - openrisc*:Linux:*:*) - echo or1k-unknown-linux-"$LIBC" - exit ;; - or32:Linux:*:* | or1k*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-"$LIBC" - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-"$LIBC" - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; - PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; - *) echo hppa-unknown-linux-"$LIBC" ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-"$LIBC" - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-"$LIBC" - exit ;; - ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-"$LIBC" - exit ;; - ppcle:Linux:*:*) - echo powerpcle-unknown-linux-"$LIBC" - exit ;; - riscv32:Linux:*:* | riscv64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" - exit ;; - sh64*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - sh*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - tile*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - vax:Linux:*:*) - echo "$UNAME_MACHINE"-dec-linux-"$LIBC" - exit ;; - x86_64:Linux:*:*) - if objdump -f /bin/sh | grep -q elf32-x86-64; then - echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 - else - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" - fi - exit ;; - xtensa*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo "$UNAME_MACHINE"-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo "$UNAME_MACHINE"-unknown-stop - exit ;; - i*86:atheos:*:*) - echo "$UNAME_MACHINE"-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo "$UNAME_MACHINE"-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos"$UNAME_RELEASE" - exit ;; - i*86:*DOS:*:*) - echo "$UNAME_MACHINE"-pc-msdosdjgpp - exit ;; - i*86:*:4.*:*) - UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" - else - echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" - else - echo "$UNAME_MACHINE"-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configure will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos"$UNAME_RELEASE" - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos"$UNAME_RELEASE" - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos"$UNAME_RELEASE" - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos"$UNAME_RELEASE" - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv"$UNAME_RELEASE" - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo "$UNAME_MACHINE"-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo "$UNAME_MACHINE"-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux"$UNAME_RELEASE" - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv"$UNAME_RELEASE" - else - echo mips-unknown-sysv"$UNAME_RELEASE" - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux"$UNAME_RELEASE" - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux"$UNAME_RELEASE" - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux"$UNAME_RELEASE" - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux"$UNAME_RELEASE" - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux"$UNAME_RELEASE" - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux"$UNAME_RELEASE" - exit ;; - SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux"$UNAME_RELEASE" - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody"$UNAME_RELEASE" - exit ;; - *:Rhapsody:*:*) - echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval "$set_cc_for_build" - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc - fi - if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc - if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_PPC >/dev/null - then - UNAME_PROCESSOR=powerpc - fi - fi - elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 - fi - echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = x86; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-*:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk"$UNAME_RELEASE" - exit ;; - NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk"$UNAME_RELEASE" - exit ;; - NSR-*:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk"$UNAME_RELEASE" - exit ;; - NSV-*:NONSTOP_KERNEL:*:*) - echo nsv-tandem-nsk"$UNAME_RELEASE" - exit ;; - NSX-*:NONSTOP_KERNEL:*:*) - echo nsx-tandem-nsk"$UNAME_RELEASE" - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = 386; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo "$UNAME_MACHINE"-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux"$UNAME_RELEASE" - exit ;; - *:DragonFly:*:*) - echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "$UNAME_MACHINE" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" - exit ;; - i*86:rdos:*:*) - echo "$UNAME_MACHINE"-pc-rdos - exit ;; - i*86:AROS:*:*) - echo "$UNAME_MACHINE"-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo "$UNAME_MACHINE"-unknown-esx - exit ;; - amd64:Isilon\ OneFS:*:*) - echo x86_64-unknown-onefs - exit ;; -esac - -echo "$0: unable to guess system type" >&2 - -case "$UNAME_MACHINE:$UNAME_SYSTEM" in - mips:Linux | mips64:Linux) - # If we got here on MIPS GNU/Linux, output extra information. - cat >&2 <&2 </dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = "$UNAME_MACHINE" -UNAME_RELEASE = "$UNAME_RELEASE" -UNAME_SYSTEM = "$UNAME_SYSTEM" -UNAME_VERSION = "$UNAME_VERSION" -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-functions 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/scripts/config.sub b/scripts/config.sub deleted file mode 100755 index 1d8e98b..0000000 --- a/scripts/config.sub +++ /dev/null @@ -1,1801 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2018 Free Software Foundation, Inc. - -timestamp='2018-02-22' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS - -Canonicalize a configuration name. - -Options: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2018 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo "$1" - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | cloudabi*-eabi* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo "$1" | sed 's/-[^-]*$//'` - if [ "$basic_machine" != "$1" ] - then os=`echo "$1" | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | ba \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia16 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pru \ - | pyramid \ - | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | wasm32 \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | ba-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pru-* \ - | pyramid-* \ - | riscv32-* | riscv64-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | wasm32-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-pc - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - asmjs) - basic_machine=asmjs-unknown - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2*) - basic_machine=m68k-bull - os=-sysv3 - ;; - e500v[12]) - basic_machine=powerpc-unknown - os=$os"spe" - ;; - e500v[12]-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=$os"spe" - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - nsv-tandem) - basic_machine=nsv-tandem - ;; - nsx-tandem) - basic_machine=nsx-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - x64) - basic_machine=x86_64-pc - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases that might get confused - # with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # es1800 is here to avoid being matched by es* (a different OS) - -es1800*) - os=-ose - ;; - # Now accept the basic system types. - # The portable systems comes first. - # Each alternative MUST end in a * to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* | -cloudabi* | -sortix* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ - | -midnightbsd*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -xray | -os68k* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo "$os" | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo "$os" | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo "$os" | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4*) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -pikeos*) - # Until real need of OS specific support for - # particular features comes up, bare metal - # configurations are quite functional. - case $basic_machine in - arm*) - os=-eabi - ;; - *) - os=-elf - ;; - esac - ;; - -nacl*) - ;; - -ios) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - c8051-*) - os=-elf - ;; - hexagon-*) - os=-elf - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - pru-*) - os=-elf - ;; - *-be) - os=-beos - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` - ;; -esac - -echo "$basic_machine$os" -exit - -# Local variables: -# eval: (add-hook 'write-file-functions 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/scripts/install-sh b/scripts/install-sh deleted file mode 100755 index ec298b5..0000000 --- a/scripts/install-sh +++ /dev/null @@ -1,541 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2020-11-14.01; # UTC - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# 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 -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# 'make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -tab=' ' -nl=' -' -IFS=" $tab$nl" - -# Set DOITPROG to "echo" to test this script. - -doit=${DOITPROG-} -doit_exec=${doit:-exec} - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -# Create dirs (including intermediate dirs) using mode 755. -# This is like GNU 'install' as of coreutils 8.32 (2020). -mkdir_umask=22 - -backupsuffix= -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -is_target_a_directory=possibly - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -p pass -p to $cpprog. - -s $stripprog installed files. - -S SUFFIX attempt to back up existing files, with suffix SUFFIX. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG - -By default, rm is invoked with -f; when overridden with RMPROG, -it's up to you to specify -f if you want it. - -If -S is not specified, no backups are attempted. - -Email bug reports to bug-automake@gnu.org. -Automake home page: https://www.gnu.org/software/automake/ -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -p) cpprog="$cpprog -p";; - - -s) stripcmd=$stripprog;; - - -S) backupsuffix="$2" - shift;; - - -t) - is_target_a_directory=always - dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; - - -T) is_target_a_directory=never;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -# We allow the use of options -d and -T together, by making -d -# take the precedence; this is for compatibility with GNU install. - -if test -n "$dir_arg"; then - if test -n "$dst_arg"; then - echo "$0: target directory not allowed when installing a directory." >&2 - exit 1 - fi -fi - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call 'install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - if test $# -gt 1 || test "$is_target_a_directory" = always; then - if test ! -d "$dst_arg"; then - echo "$0: $dst_arg: Is not a directory." >&2 - exit 1 - fi - fi -fi - -if test -z "$dir_arg"; then - do_exit='(exit $ret); exit $ret' - trap "ret=129; $do_exit" 1 - trap "ret=130; $do_exit" 2 - trap "ret=141; $do_exit" 13 - trap "ret=143; $do_exit" 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names problematic for 'test' and other utilities. - case $src in - -* | [=\(\)!]) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - # Don't chown directories that already exist. - if test $dstdir_status = 0; then - chowncmd="" - fi - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - dst=$dst_arg - - # If destination is a directory, append the input filename. - if test -d "$dst"; then - if test "$is_target_a_directory" = never; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dstbase=`basename "$src"` - case $dst in - */) dst=$dst$dstbase;; - *) dst=$dst/$dstbase;; - esac - dstdir_status=0 - else - dstdir=`dirname "$dst"` - test -d "$dstdir" - dstdir_status=$? - fi - fi - - case $dstdir in - */) dstdirslash=$dstdir;; - *) dstdirslash=$dstdir/;; - esac - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - # The $RANDOM variable is not portable (e.g., dash). Use it - # here however when possible just to lower collision chance. - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - - trap ' - ret=$? - rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null - exit $ret - ' 0 - - # Because "mkdir -p" follows existing symlinks and we likely work - # directly in world-writeable /tmp, make sure that the '$tmpdir' - # directory is successfully created first before we actually test - # 'mkdir -p'. - if (umask $mkdir_umask && - $mkdirprog $mkdir_mode "$tmpdir" && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - test_tmpdir="$tmpdir/a" - ls_ld_tmpdir=`ls -ld "$test_tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null - fi - trap '' 0;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; - esac - - oIFS=$IFS - IFS=/ - set -f - set fnord $dstdir - shift - set +f - IFS=$oIFS - - prefixes= - - for d - do - test X"$d" = X && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=${dstdirslash}_inst.$$_ - rmtmp=${dstdirslash}_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && - { test -z "$stripcmd" || { - # Create $dsttmp read-write so that cp doesn't create it read-only, - # which would cause strip to fail. - if test -z "$doit"; then - : >"$dsttmp" # No need to fork-exec 'touch'. - else - $doit touch "$dsttmp" - fi - } - } && - $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - set +f && - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # If $backupsuffix is set, and the file being installed - # already exists, attempt a backup. Don't worry if it fails, - # e.g., if mv doesn't support -f. - if test -n "$backupsuffix" && test -f "$dst"; then - $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null - fi - - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC0" -# time-stamp-end: "; # UTC" -# End: diff --git a/scripts/mkpluginhooks b/scripts/mkpluginhooks index 8053275..2368b55 100755 --- a/scripts/mkpluginhooks +++ b/scripts/mkpluginhooks @@ -20,7 +20,7 @@ gendummy() { if [ "$1" = "clean" ]; then rm -f $INC/$HDR else - printf "" >$INC/$HDR.$$ + echo -n "" >$INC/$HDR.$$ fi done } diff --git a/scripts/plugctl.sh b/scripts/plugctl.sh index 6e6fde6..4511054 100755 --- a/scripts/plugctl.sh +++ b/scripts/plugctl.sh @@ -22,7 +22,7 @@ if [ "$on" = "yes" -a -f $SRCDIR/$dir/$CONFIGURE ]; then ln -s $SRCDIR/$dir/Makefile.conf.in Makefile.conf.in echo "=== configuring in $dir" trap "echo ; exit 130" INT - ${MAKE} ./configure REALTOPDIR="$TOP" srcdir="$SRCDIR/$dir" + make ./configure REALTOPDIR="$TOP" srcdir="$SRCDIR/$dir" if [ ! -f ./configure ]; then on="no" else diff --git a/src/Makefile b/src/Makefile index 70e205f..18ae9bd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,4 +8,4 @@ all: default top_builddir=.. include $(top_builddir)/Makefile.conf include $(REALTOPDIR)/src/Makefile.common -include $(REALTOPDIR)/src/arch/linux/Makefile.main +include $(REALTOPDIR)/src/arch/$(OS)/Makefile.main diff --git a/src/Makefile.common.inc b/src/Makefile.common.inc index 88e071e..6e6660f 100644 --- a/src/Makefile.common.inc +++ b/src/Makefile.common.inc @@ -5,6 +5,5 @@ LIBNAME := $(subst /,_,$(SUBDIR)) vpath %.c $(srcdir) vpath %.h $(srcdir) vpath %.S $(srcdir) -vpath %.SS $(srcdir) vpath %.s $(srcdir) vpath %.sgml $(srcdir) diff --git a/src/Makefile.common.post b/src/Makefile.common.post index 8a15939..3c2f23a 100644 --- a/src/Makefile.common.post +++ b/src/Makefile.common.post @@ -1,15 +1,17 @@ ifndef OBJS -OBJS=$(CFILES:.c=.o) $(SFILES:.S=.o) $(XSFILES:.s=.o) $(SSFILES:.SS=.o) +OBJS=$(CFILES:.c=.o) $(SFILES:.S=.o) endif GENOBJS = $(GENSRC:.c=.o) ifndef DEPENDS -DEPENDS=$(OBJS:.o=.d) +DEPENDS=$(OBJS:.o=.d) $(XSFILES:.s=.d) endif GENERATED = $(top_builddir)/src/include/version.hh \ - $(top_builddir)/src/plugin/include/plugin_config.hh + $(top_builddir)/src/plugin/include/plugin_config.hh \ + $(top_builddir)/src/base/bios/x86/bios_offsets.hh \ + $(top_builddir)/src/base/bios/x86/bios_data.xxd ifneq ($(GENHDRS),) GENERATED += $(GENHDRS) @@ -26,23 +28,23 @@ $(BINPATH) $(BINPATH)/bin $(BINPATH)/commands $(BINPATH)/lib: mkdir -p $@ $(BINPATH)/bat: | $(BINPATH) - $(LN_SFT) ../src/bindist/bat $@ + ln -sfT ../src/bindist/bat $@ $(top_builddir)/commands: | $(BINPATH)/commands $(BINPATH)/bat rm -rf $@ mkdir $@ mkdir $@/dosemu - $(LN_S) -f ../src/bindist/fdppconf.sys $@/fdppconf.sys - $(LN_S) -f ../src/bindist/fdppauto.bat $@/fdppauto.bat - for i in `ls $(BINPATH)/bat/`; do $(LN_SFT) ../../$(THISVERSION)/bat/$$i $@/dosemu/$$i; done + ln -sf ../src/bindist/fdppconf.sys $@/fdppconf.sys + ln -sf ../src/bindist/fdppauto.bat $@/fdppauto.bat + for i in `ls $(BINPATH)/bat/`; do ln -sfT ../../$(THISVERSION)/bat/$$i $@/dosemu/$$i; done $(top_builddir)/bin: | $(BINPATH)/bin rm -f $@ - $(LN_S) -f $(THISVERSION)/bin $@ + ln -sf $(THISVERSION)/bin $@ $(top_builddir)/lib: | $(BINPATH)/lib rm -f $@ - $(LN_S) -f $(THISVERSION)/lib $@ + ln -sf $(THISVERSION)/lib $@ GIT_REV := $(shell $(REALTOPDIR)/git-rev.sh $(REALTOPDIR) $(top_builddir)) .LOW_RESOLUTION_TIME: $(GIT_REV) @@ -58,6 +60,12 @@ $(top_builddir)/src/include/version.hh: $(top_builddir)/Makefile.conf $(REALTOPD echo "#define VERDATE \"$(RELEASE_DATE)\"" >> $@; \ echo "#endif /* VERSION_H */" >> $@ +$(top_builddir)/src/base/bios/x86/bios_offsets.hh \ + $(top_builddir)/src/base/bios/x86/bios_data.xxd : \ + $(REALTOPDIR)/src/base/bios/x86/bios.s \ + $(top_builddir)/src/include/version.hh + $(MAKE) -C $(top_builddir)/src/base/bios/x86 SUBDIR=base/bios/x86 $(notdir $@) + $(LIB): $(OBJS) $(GENOBJS) | $(BINPATH)/lib rm -f $@ $(AR) cr $@ $^ @@ -65,12 +73,11 @@ $(LIB): $(OBJS) $(GENOBJS) | $(BINPATH)/lib .PHONY: clean realclean lib echo all install default -# Use wildcards instead of OBJS and DEPENDS because they may depend on -# a make target. The reason is that on clean we do not include Makefile.conf. clean:: - -rm -f *.o $(LIB) $(GENSRC) *.d $(GENHDRS) configure *~ + -rm -f $(OBJS) $(LIB) $(GENSRC) $(DEPENDS) $(GENHDRS) configure *~ realclean:: clean + rm -f $(DEPENDS) rm -rf autom4te*.cache rm -f Makefile.conf config.log config.status configure aclocal.m4 rm -rf plugin/include @@ -81,46 +88,10 @@ $(GENOBJS): $(GENSRC) %.o: %.c $(CC) -c $(ALL_CPPFLAGS) $(ALL_CFLAGS) -o $@ $< -%.o: %.s $(top_builddir)/src/include/version.hh +$(XSFILES:.s=.o): %.o: %.s $(top_builddir)/src/include/version.hh $(CPP) $(ALL_CPPFLAGS) -x assembler-with-cpp $< | $(XAS) $(XASFLAGS) -o $@ -VS = $(subst .,_,$(notdir $(1)))_START - %.o: %.S $(top_builddir)/src/include/version.hh - $(CPP) $(ALL_CPPFLAGS) -x assembler-with-cpp $< | $(XAS) $(XASFLAGS) -o _$@ - $(AS_LD) $(AS_LDFLAGS) -static $(if $($(call VS,$<)), \ - --section-start .text=$($(call VS,$<))) -o $@.elf _$@ - $(XOBJCOPY) -j .text -O binary $@.elf $@.bin - nm -g -n _$@ | gawk '\ - BEGIN {\ - print "// Warning: autogenerated";\ - print "";\ - print "asm(";\ - print "\".data\\n\"";\ - print "\".globl _binary_$(@:.o=)_o_bin_start\\n\"";\ - print "\"_binary_$(@:.o=)_o_bin_start:\\n\"";\ - print "\".incbin \\\"$@.bin\\\"\\n\"";\ - print "\".globl _binary_$(@:.o=)_o_bin_end\\n\"";\ - print "\"_binary_$(@:.o=)_o_bin_end:\\n\"";\ - print "\".previous\\n\"";\ - print ");";\ - print "#include \"$(srcdir)/$(@:.o=)_offsets.h\"";\ - }\ - {\ - HEXSTR = sprintf("0x%s", $$1);\ - ADDR = strtonum(HEXSTR) $(if $($(call VS,$<)),+ $($(call VS,$<)));\ - if ($$3 != "_start") {\ - printf "const unsigned %s = 0x%04x;\n", $$3, ADDR;\ - }\ - }\ - END {\ - print "";\ - }\ - ' > $@_offsets.c - $(CC) -c -o $@ $@_offsets.c - $(RM) _$@ $@.bin $@.elf $@_offsets.c - -%.o: %.SS $(CPP) $(ALL_CPPFLAGS) -x assembler-with-cpp $< | $(AS) $(ASFLAGS) -o $@ ifndef CLEANING diff --git a/src/arch/linux/Makefile.main b/src/arch/linux/Makefile.main index 8ea70af..f0b23ee 100644 --- a/src/arch/linux/Makefile.main +++ b/src/arch/linux/Makefile.main @@ -17,32 +17,24 @@ NET=dosext/net # This is defined when the SB Emulation is required. You should re-configure, # rather than just change this. # -SBEMU=base/dev/sb16 base/dev/sb16/softmpu base/sound +SBEMU=base/dev/sb16 base/sound # # This is defined when the CPU emulator is required. You should # re-configure, rather than just change this. # -ifeq ($(X86_EMULATOR),1) -XCPUEMU = base/emu-i386/simx86 -ifeq ($(USE_SOFTFLOAT),1) -XCPUEMU += base/emu-i386/simx86/softfloat -endif +ifdef X86_EMULATOR +XCPUEMU=base/emu-i386/simx86 endif -ifeq ($(MCONTEXT),1) -LIBMC = base/lib/mcontext -endif +# No longer need midid +#REQUIRED += $(MIDID) -DPMI = dosext/dpmi dosext/dpmi/msdos dosext/dpmi/doslib -ifeq ($(DNATIVE),1) -DPMI += dosext/dpmi/dnative -endif +DPMI = dosext/dpmi dosext/dpmi/msdos _LIBSUBDIRS=base/video base/dev/vga base/core base/kbd_unicode \ - arch/linux/async base/lib/mapping $(LIBMC) \ - base/misc base/lib/misc base/lib/libpcl base/lib/timer \ - base/dev/misc \ + arch/linux/async arch/linux/mapping base/lib/mcontext \ + base/misc base/lib/misc base/lib/libpcl base/dev/misc \ base/emu-i386 $(XCPUEMU) base/speaker \ base/dev/pic base/dev/ne2k \ dosext/mfs dosext/misc dosext/builtins \ @@ -80,15 +72,9 @@ $(top_builddir)/etc/Xfonts/%.pcf.gz: $(REALTOPDIR)/etc/%.bdf | $(top_builddir)/e $(LIBS_): | $(top_builddir)/lib $(BINPATH)/bin/$(DOSBIN): $(LIBS_) -ifeq ($(OS),Darwin) - $(LD) $(ALL_LDFLAGS) $(DOSBIN_LDFLAGS) -o $@ \ - -Wl,-all_load $(LIBS_) $(LIBS) \ - -Wl,-map,$(BINPATH)/bin/dosemu.map -else $(LD) $(ALL_LDFLAGS) $(DOSBIN_LDFLAGS) -o $@ \ -Wl,--whole-archive $(LIBS_) -Wl,--no-whole-archive $(LIBS) \ -Wl,-Map=$(BINPATH)/bin/dosemu.map -endif $(BINPATH)/bin/dosemu: $(SRCPATH)/dosemu.systemwide $(SRCPATH)/dosemu cp $< $@ @@ -135,14 +121,17 @@ install: for i in `find $(SRCPATH)/bindist -maxdepth 1 -type f`; do \ $(INSTALL) -m 0644 $$i $(sysdir); \ done - $(INSTALL) -d $(sysdir)/c + $(INSTALL) -m 0644 -D $(SRCPATH)/bindist/c/* -t $(sysdir)/c + $(INSTALL) -m 0644 -D $(SRCPATH)/bindist/bat/*.bat -t $(sysdir)/dosemu + $(INSTALL) -m 0644 -D $(SRCPATH)/bindist/bat/dosrc.d/* -t $(sysdir)/dosemu/dosrc.d $(INSTALL) -d $(cmddir) - $(INSTALL) -d $(cmddir)/dosrc.d - $(INSTALL) -m 0644 -D $(SRCPATH)/bindist/c/* $(sysdir)/c - $(INSTALL) -m 0644 -D $(SRCPATH)/bindist/bat/*.bat $(cmddir) - $(INSTALL) -m 0644 -D $(SRCPATH)/bindist/bat/dosrc.d/* $(cmddir)/dosrc.d - cp -f -d $(SYS)/* $(cmddir) - $(LN_S) -f $(cmdsuff) $(DESTDIR)$(dosemudir)/commands + for i in `find -L $(SYS) -xtype f`; do \ + $(INSTALL) -m 0644 $$i $(cmddir); \ + done + cd $(SYS); for i in `find * -type l`; do \ + ln -sf generic.com $(cmddir)/$$i; \ + done + ln -sf $(cmdsuff) $(DESTDIR)$(dosemudir)/commands if [ ! -f $(DESTDIR)$(etcdir)/dosemu.conf ]; then \ $(INSTALL) -m 0644 $(REALTOPDIR)/etc/dosemu.conf $(DESTDIR)$(etcdir); \ fi @@ -167,7 +156,7 @@ install: fi; \ done $(INSTALL) -d $(DESTDIR)$(docdir) - for i in NEWS.md THANKS BUGS; do \ + for i in NEWS THANKS BUGS; do \ $(INSTALL) -m 0644 $(REALTOPDIR)/$$i $(DESTDIR)$(docdir); \ done $(INSTALL) -m 0644 $(top_builddir)/changelog $(DESTDIR)$(docdir) @@ -186,7 +175,7 @@ install: ! which mkfontdir >/dev/null || mkfontdir $(DESTDIR)$(x11fontdir) if [ -d "$(DESTDIR)$(sysconfdir)/X11/fontpath.d" ]; then \ rm -f $(DESTDIR)$(sysconfdir)/X11/fontpath.d/$(PACKAGE_NAME):unscaled:pri=20; \ - $(LN_S) -f $(x11fontdir) $(DESTDIR)$(sysconfdir)/X11/fontpath.d/$(PACKAGE_NAME):unscaled:pri=20; \ + ln -sf $(x11fontdir) $(DESTDIR)$(sysconfdir)/X11/fontpath.d/$(PACKAGE_NAME):unscaled:pri=20; \ fi install -m 0644 -D $(REALTOPDIR)/etc/ttf/* $(DESTDIR)$(ttffontdir) @@ -206,9 +195,9 @@ install: rm -rf $(DESTDIR)$(dosemuxdir)/fdboot; \ $(INSTALL) -d $(DESTDIR)$(dosemuxdir)/fdboot; \ cd $(DESTDIR)$(dosemuxdir)/fdboot; \ - $(LN_S) ../../dosemu/commands/c/fdconfig.sys fdconfig.sys; \ - $(LN_S) ../freedos/kernel.sys kernel.sys; \ - $(LN_S) ../freedos/command.com command.com; \ + ln -s ../../dosemu/commands/c/fdconfig.sys fdconfig.sys; \ + ln -s ../freedos/kernel.sys kernel.sys; \ + ln -s ../freedos/command.com command.com; \ fi @if test $(etcdir) != /etc; then \ diff --git a/src/arch/linux/async/Makefile b/src/arch/linux/async/Makefile index 11961a4..9af57de 100644 --- a/src/arch/linux/async/Makefile +++ b/src/arch/linux/async/Makefile @@ -1,11 +1,13 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.conf -CFILES = signal.c debug.c +CFILES=sigsegv.c signal.c debug.c ifeq ($(HAVE_LIBBFD),1) CFILES += backtrace-symbols.c endif +ALL_CPPFLAGS += -I$(REALTOPDIR)/src/base/lib/mcontext + include $(REALTOPDIR)/src/Makefile.common all: lib diff --git a/src/arch/linux/async/backtrace-symbols.c b/src/arch/linux/async/backtrace-symbols.c index a40dca7..cc9d616 100644 --- a/src/arch/linux/async/backtrace-symbols.c +++ b/src/arch/linux/async/backtrace-symbols.c @@ -145,7 +145,7 @@ static char** translate_addresses_buf(bfd * abfd, bfd_vma *addr, int naddr) char *buf = &b; int len = 0; char **ret_buf = NULL; - /* iterate over the formatting twice. + /* iterate over the formating twice. * the first time we count how much space we need * the second time we do the actual printing */ for (state=Count; state<=Print; state++) { diff --git a/src/arch/linux/async/debug.c b/src/arch/linux/async/debug.c index 9162ecb..cd4978f 100644 --- a/src/arch/linux/async/debug.c +++ b/src/arch/linux/async/debug.c @@ -1,8 +1,6 @@ #include "emu.h" #include "dosemu_config.h" #include "debug.h" -#include "emudpmi.h" -#include "cpu-emu.h" #include "sig.h" #include #include @@ -35,11 +33,7 @@ static int start_gdb(pid_t dosemu_pid) printf("Debug info:\n"); fflush(stdout); -#ifdef __APPLE__ - ret = asprintf(&buf, "lldb %s", dosemu_proc_self_exe); -#else - ret = asprintf(&buf, "gdb --readnow %s", dosemu_proc_self_exe); -#endif + ret = asprintf(&buf, "gdb %s", dosemu_proc_self_exe); assert(ret != -1); printf("%s", buf); @@ -63,15 +57,9 @@ static int start_gdb(pid_t dosemu_pid) static void do_debug(void) { -#ifdef __APPLE__ - const char *cmd1 = "register read\n"; -// const char *cmd2 = "bt\n"; - const char *cmd3 = "thread backtrace all\n"; -#else const char *cmd1 = "info registers\n"; // const char *cmd2 = "backtrace\n"; const char *cmd3 = "thread apply all backtrace full\n"; -#endif gdb_command(cmd1); // gdb_command(cmd2); @@ -165,7 +153,7 @@ static int do_gdb_debug(void) pid_t dosemu_pid = getpid(); pid_t dbg_pid; int status; - sigset_t oset; + sigset_t set, oset; if (getuid() != geteuid()) return 0; @@ -173,7 +161,10 @@ static int do_gdb_debug(void) #ifdef __linux__ prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY); #endif - sigprocmask(SIG_BLOCK, &q_mask, &oset); + sigemptyset(&set); + sigaddset(&set, SIGIO); + sigaddset(&set, SIGALRM); + sigprocmask(SIG_BLOCK, &set, &oset); switch ((dbg_pid = fork())) { case 0: signal_done(); @@ -221,14 +212,8 @@ void gdb_debug(void) #else /* the problem with the above is that gdb usually doesn't work * because of the security restrictions */ - error("Please "); if (!ret) - error("@install gdb, "); - error("@update dosemu from git, compile it with debug\n" - "info and make a bug report with the content of ~/.dosemu/boot.log at\n" -"https://github.com/dosemu2/dosemu2/issues\n"); - error("@Please provide any additional info you can, like the test-cases,\n" - "URLs and all the rest that fits.\n\n"); + error("Please install gdb!\n"); #ifdef HAVE_BACKTRACE print_trace(); #endif @@ -238,23 +223,3 @@ void gdb_debug(void) fflush(dbg_fd); dump_state(); } - -void siginfo_debug(const siginfo_t *si) -{ - error("@\n"); - error("cpu exception in dosemu code outside of %s!\n", - (in_dpmi_pm() ? "DPMI client" : "VM86()")); -#ifdef __linux__ - psiginfo(si, ""); -#endif - error("@\n"); - dbug_printf("%s\nsig: %i code: 0x%02x errno: 0x%08x fault address: %p\n", - strsignal(si->si_signo), - si->si_signo, si->si_code, si->si_errno, si->si_addr); - -#ifdef X86_EMULATOR - /* gdb_debug() will crash in jit code doing backtrace() */ - if (!(IS_EMU_JIT() && e_in_compiled_code())) -#endif - gdb_debug(); -} diff --git a/src/arch/linux/async/debug.h b/src/arch/linux/async/debug.h index a61abbb..7becea6 100644 --- a/src/arch/linux/async/debug.h +++ b/src/arch/linux/async/debug.h @@ -1,7 +1,6 @@ #ifndef __DEBUG_H #define __DEBUG_H -void siginfo_debug(const siginfo_t *si); void gdb_debug(void); #endif diff --git a/src/arch/linux/async/signal.c b/src/arch/linux/async/signal.c index fc4052a..9fa7dbe 100644 --- a/src/arch/linux/async/signal.c +++ b/src/arch/linux/async/signal.c @@ -15,9 +15,6 @@ #include #include #endif -#ifdef __FreeBSD__ -#include -#endif #include "emu.h" #ifdef __linux__ @@ -34,7 +31,6 @@ #include "lowmem.h" #include "coopth.h" #include "emudpmi.h" -#include "dnative.h" #include "pic.h" #include "ipx.h" #include "pktdrvr.h" @@ -49,6 +45,79 @@ #include "cpu-emu.h" #include "sig.h" +#define SIGALTSTACK_WA_DEFAULT 1 +#if SIGALTSTACK_WA_DEFAULT + #ifdef DISABLE_SYSTEM_WA + #ifdef SS_AUTODISARM + #define SIGALTSTACK_WA 0 + #else + #ifdef WARN_UNDISABLED_WA + #warning Not disabling SIGALTSTACK_WA, update your kernel + #endif + #define SIGALTSTACK_WA 1 + #endif + #else + /* work-around sigaltstack badness - disable when kernel is fixed */ + #define SIGALTSTACK_WA 1 + #endif + #if defined(WARN_OUTDATED_WA) && defined(SS_AUTODISARM) + #warning SIGALTSTACK_WA is outdated + #endif +#else + #define SIGALTSTACK_WA 0 +#endif +#if SIGALTSTACK_WA +#include "mcontext.h" +#include "mapping.h" +#endif +/* SS_AUTODISARM is a dosemu-specific sigaltstack extension supported + * by some kernels */ +#ifndef SS_AUTODISARM +#define SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ +#endif + +#ifdef __x86_64__ + #define SIGRETURN_WA_DEFAULT 1 +#else + #define SIGRETURN_WA_DEFAULT 0 +#endif +#if SIGRETURN_WA_DEFAULT + #ifdef DISABLE_SYSTEM_WA + #ifdef UC_SIGCONTEXT_SS + #define SIGRETURN_WA 0 + #else + #ifdef WARN_UNDISABLED_WA + #warning Not disabling SIGRETURN_WA, update your kernel + #endif + #define SIGRETURN_WA 1 + #endif + #else + /* work-around sigreturn badness - disable when kernel is fixed */ + #define SIGRETURN_WA 1 + #endif + #if defined(WARN_OUTDATED_WA) && defined(UC_SIGCONTEXT_SS) + #warning SIGRETURN_WA is outdated + #endif +#else + #define SIGRETURN_WA 0 +#endif + +#ifdef __x86_64__ +#ifndef UC_SIGCONTEXT_SS +/* + * UC_SIGCONTEXT_SS will be set when delivering 64-bit or x32 signals on + * kernels that save SS in the sigcontext. Kernels that set UC_SIGCONTEXT_SS + * allow signal handlers to set UC_STRICT_RESTORE_SS; + * if UC_STRICT_RESTORE_SS is set, then sigreturn will restore SS. + * + * For compatibility with old programs, the kernel will *not* set + * UC_STRICT_RESTORE_SS when delivering signals from 32bit code. + */ +#define UC_SIGCONTEXT_SS 0x2 +#define UC_STRICT_RESTORE_SS 0x4 +#endif +#endif + /* Variables for keeping track of signals */ #define MAX_SIG_QUEUE_SIZE 50 #define MAX_SIG_DATA_SIZE 128 @@ -64,8 +133,7 @@ static struct SIGNAL_queue signal_queue[MAX_SIG_QUEUE_SIZE]; #define MAX_SIGCHLD_HANDLERS 10 struct sigchld_hndl { pid_t pid; - void (*handler)(void*); - void *arg; + void (*handler)(void); int enabled; }; static struct sigchld_hndl chld_hndl[MAX_SIGCHLD_HANDLERS]; @@ -78,17 +146,19 @@ struct sigalrm_hndl { static struct sigalrm_hndl alrm_hndl[MAX_SIGALRM_HANDLERS]; static int alrm_hndl_num; -struct callback_s { - void (*func)(void *); - void *arg; - const char *name; -}; - -sigset_t q_mask; -sigset_t nonfatal_q_mask; +static sigset_t q_mask; +static sigset_t nonfatal_q_mask; static sigset_t fatal_q_mask; +static void *cstack; +#if SIGALTSTACK_WA +static void *backup_stack; +static int need_sas_wa; +#endif +#if SIGRETURN_WA +static int need_sr_wa; +#endif +static int block_all_sigs; static int sig_inited; -int sig_threads_wa = 1; static int sh_tid; static int in_handle_signals; @@ -100,14 +170,18 @@ static struct rng_s cbks; #define MAX_CBKS 1000 static pthread_mutex_t cbk_mtx = PTHREAD_MUTEX_INITIALIZER; -static void (*sighandlers[SIGMAX])(siginfo_t *); -static void (*qsighandlers[SIGMAX])(int sig, siginfo_t *si, void *uc); -static void (*asighandlers[SIGMAX])(void *arg); +struct eflags_fs_gs eflags_fs_gs; + +static void (*sighandlers[NSIG])(sigcontext_t *, siginfo_t *); +static void (*qsighandlers[NSIG])(int sig, siginfo_t *si, void *uc); +static void (*asighandlers[NSIG])(void *arg); +static struct sigaction sacts[NSIG]; static void SIGALRM_call(void *arg); static void SIGIO_call(void *arg); static void sigasync(int sig, siginfo_t *si, void *uc); static void sigasync_std(int sig, siginfo_t *si, void *uc); +static void leavedos_sig(int sig); static void _newsetqsig(int sig, void (*fun)(int sig, siginfo_t *si, void *uc)) { @@ -128,8 +202,18 @@ static void newsetqsig(int sig, void (*fun)(int sig, siginfo_t *si, void *uc)) static void init_one_sig(int num, void (*fun)(int sig, siginfo_t *si, void *uc)) { struct sigaction sa; - sa.sa_flags = SA_RESTART | SA_SIGINFO; - sa.sa_mask = nonfatal_q_mask; + + sa.sa_flags = SA_RESTART | SA_ONSTACK | SA_SIGINFO; + if (block_all_sigs) + { + /* initially block all async signals. */ + sa.sa_mask = q_mask; + } + else + { + /* block all non-fatal async signals */ + sa.sa_mask = nonfatal_q_mask; + } sa.sa_sigaction = fun; sigaction(num, &sa, NULL); } @@ -137,7 +221,7 @@ static void init_one_sig(int num, void (*fun)(int sig, siginfo_t *si, void *uc)) static void qsig_init(void) { int i; - for (i = 0; i < SIGMAX; i++) { + for (i = 0; i < NSIG; i++) { if (qsighandlers[i]) init_one_sig(i, qsighandlers[i]); } @@ -161,7 +245,7 @@ static void do_registersig(int sig, void (*fun)(int sig, siginfo_t *si, void *uc } /* registers non-emergency async signals */ -void registersig(int sig, void (*fun)(siginfo_t *)) +void registersig(int sig, void (*fun)(sigcontext_t *, siginfo_t *)) { assert(fun && !sighandlers[sig]); sighandlers[sig] = fun; @@ -179,20 +263,254 @@ static void newsetsig(int sig, void (*fun)(int sig, siginfo_t *si, void *uc)) { struct sigaction sa; - sa.sa_flags = SA_SIGINFO; - /* block all non-fatal async signals */ - sa.sa_mask = nonfatal_q_mask; + sa.sa_flags = SA_RESTART | SA_ONSTACK | SA_SIGINFO; +#ifdef __linux__ + if (kernel_version_code >= KERNEL_VERSION(2, 6, 14)) +#endif + sa.sa_flags |= SA_NODEFER; + if (block_all_sigs) + { + /* initially block all async signals. */ + sa.sa_mask = q_mask; + } + else + { + /* block all non-fatal async signals */ + sa.sa_mask = nonfatal_q_mask; + } sa.sa_sigaction = fun; sigaction(sig, &sa, NULL); } +SIG_PROTO_PFX +static void fixup_handler(int sig, siginfo_t *si, void *uc) +{ + struct sigaction *sa; + ucontext_t *uct = uc; + sigcontext_t *scp = &uct->uc_mcontext; + init_handler(scp, 1); + sa = &sacts[sig]; + if (sa->sa_flags & SA_SIGINFO) { + sa->sa_sigaction(sig, si, uc); + } else { + typedef void (*hdlr_t)(int, siginfo_t *, ucontext_t *); + hdlr_t hdlr = (hdlr_t)sa->sa_handler; + hdlr(sig, si, uc); + } + deinit_handler(scp, &uct->uc_flags); +} + +static void fixupsig(int sig) +{ + struct sigaction sa; + sigaction(sig, NULL, &sa); + if (sa.sa_handler == SIG_DFL || sa.sa_handler == SIG_IGN) + return; + sacts[sig] = sa; + sa.sa_flags |= SA_ONSTACK | SA_SIGINFO; + sa.sa_sigaction = fixup_handler; + sigaction(sig, &sa, NULL); +} + +/* init_handler puts the handler in a sane state that glibc + expects. That means restoring fs and gs for vm86 (necessary for + 2.4 kernels) and fs, gs and eflags for DPMI. */ +SIG_PROTO_PFX +static void __init_handler(sigcontext_t *scp, unsigned long uc_flags) +{ + /* + * FIRST thing to do in signal handlers - to avoid being trapped into int0x11 + * forever, we must restore the eflags. + */ + loadflags(eflags_fs_gs.eflags); + +#ifdef __x86_64__ + /* ds,es, and ss are ignored in 64-bit mode and not present or + saved in the sigcontext, so we need to do it ourselves + (using the 3 high words of the trapno field). + fs and gs are set to 0 in the sigcontext, so we also need + to save those ourselves */ + _ds = getsegment(ds); + _es = getsegment(es); + if (!(uc_flags & UC_SIGCONTEXT_SS)) + _ss = getsegment(ss); + _fs = getsegment(fs); + _gs = getsegment(gs); + if (config.cpu_vm_dpmi == CPUVM_NATIVE && _cs == 0) { + if (config.dpmi +#ifdef X86_EMULATOR + && !EMU_DPMI() +#endif + ) { + fprintf(stderr, "Cannot run DPMI code natively "); +#ifdef __linux__ + if (kernel_version_code < KERNEL_VERSION(2, 6, 15)) + fprintf(stderr, "because your Linux kernel is older than version 2.6.15.\n"); + else + fprintf(stderr, "for unknown reasons.\nPlease contact linux-msdos@vger.kernel.org.\n"); +#endif +#ifdef X86_EMULATOR + fprintf(stderr, "Set $_cpu_emu=\"full\" or \"fullsim\" to avoid this message.\n"); +#endif + } +#ifdef X86_EMULATOR + config.cpu_vm = CPUVM_EMU; + _cs = getsegment(cs); +#else + leavedos_sig(45); +#endif + } +#endif + + if (in_vm86) { +#ifdef __i386__ +#ifdef X86_EMULATOR + if (config.cpu_vm != CPUVM_EMU) +#endif + { + if (getsegment(fs) != eflags_fs_gs.fs) + loadregister(fs, eflags_fs_gs.fs); + if (getsegment(gs) != eflags_fs_gs.gs) + loadregister(gs, eflags_fs_gs.gs); + } +#endif + return; + } + +#if SIGRETURN_WA + if (need_sr_wa && !DPMIValidSelector(_cs)) + dpmi_iret_unwind(scp); +#endif + +#if 0 + /* for async signals need to restore fs/gs even if dosemu code + * was interrupted, because it can be interrupted in a switching + * routine when fs or gs are already switched but cs is not */ + if (!DPMIValidSelector(_cs) && !async) + return; +#else + /* as DIRECT_DPMI_SWITCH support is now removed, the above comment + * applies only to DPMI_iret, which is now unwound. + * We don't need to restore segregs for async signals any more. */ + if (!DPMIValidSelector(_cs)) + return; +#endif + + /* restore %fs and %gs for compatibility with NPTL. */ + if (getsegment(fs) != eflags_fs_gs.fs) + loadregister(fs, eflags_fs_gs.fs); + if (getsegment(gs) != eflags_fs_gs.gs) + loadregister(gs, eflags_fs_gs.gs); +#ifdef __x86_64__ + loadregister(ds, eflags_fs_gs.ds); + loadregister(es, eflags_fs_gs.es); + /* kernel has the following rule: non-zero selector means 32bit base + * in GDT. Zero selector means 64bit base, set via msr. + * So if we set selector to 0, need to use also prctl(ARCH_SET_xS). + * Also, if the bases are not used they are 0 so no need to restore, + * which saves a syscall */ + if (!eflags_fs_gs.fs && eflags_fs_gs.fsbase) + dosemu_arch_prctl(ARCH_SET_FS, eflags_fs_gs.fsbase); + if (!eflags_fs_gs.gs && eflags_fs_gs.gsbase) + dosemu_arch_prctl(ARCH_SET_GS, eflags_fs_gs.gsbase); +#endif +} + +SIG_PROTO_PFX +void init_handler(sigcontext_t *scp, unsigned long uc_flags) +{ + /* Async signals are initially blocked. + * If we don't block them, nested sighandler will clobber SS + * before we manage to save it. + * Even if the nested sighandler tries hard, it can't properly + * restore SS, at least until the proper sigreturn() support is in. + * For kernels that have the proper SS support, only nonfatal + * async signals are initially blocked. They need to be blocked + * because of sas wa and because they should not interrupt + * deinit_handler() after it changed %fs. In this case, however, + * we can block them later at the right places, but this will + * cost a syscall per every signal. + * Note: in 64bit mode some segment registers are neither saved nor + * restored by the signal dispatching code in kernel, so we have + * to restore them by hands. + * Note: most async signals are left blocked, we unblock only few. + * Sync signals like SIGSEGV are never blocked. + */ + __init_handler(scp, uc_flags); + if (!block_all_sigs) + return; +#if SIGALTSTACK_WA + /* for SAS WA we unblock the fatal signals even later if we came + * from DPMI, as then we'll be switching stacks which is racy when + * async signals enabled. */ + if (need_sas_wa && DPMIValidSelector(_cs)) + return; +#endif + /* either came from dosemu/vm86 or having SS_AUTODISARM - + * then we can unblock any signals we want. This is because + * dosemu DOES NOT USE signal stack by itself. We switch to + * dosemu via a direct context switch (including a stack switch), + * before which we make sure either SS_AUTODISARM or sas_wa worked. + * So we are here either on dosemu stack, or on autodisarmed SAS. + * For now leave nonfatal signals blocked as they are rarely needed + * inside sighandlers (needed only for instremu, see + * https://github.com/stsp/dosemu2/issues/477 + * ) */ + sigprocmask(SIG_UNBLOCK, &fatal_q_mask, NULL); +} + +SIG_PROTO_PFX +void deinit_handler(sigcontext_t *scp, unsigned long *uc_flags) +{ +#ifdef X86_EMULATOR + /* in fullsim mode nothing to do */ + if (CONFIG_CPUSIM && EMU_DPMI()) + return; +#endif + + if (!DPMIValidSelector(_cs)) + return; + +#ifdef __x86_64__ + if (*uc_flags & UC_SIGCONTEXT_SS) { + /* + * On Linux 4.4 (possibly) and up, the kernel can fully restore + * SS and ESP, so we don't need any special tricks. To avoid confusion, + * force strict restore. (Some 4.1 versions support this as well but + * without the uc_flags bits. It's not trying to detect those kernels.) + */ + *uc_flags |= UC_STRICT_RESTORE_SS; + } else { +#if SIGRETURN_WA + if (!need_sr_wa) { + need_sr_wa = 1; + warn("Enabling sigreturn() work-around\n"); + } + dpmi_iret_setup(scp); +#else + error("Your kernel does not support UC_STRICT_RESTORE_SS and the " + "work-around in dosemu is not enabled.\n"); + leavedos_sig(11); +#endif + } + + if (_fs != getsegment(fs)) + loadregister(fs, _fs); + if (_gs != getsegment(gs)) + loadregister(gs, _gs); + + loadregister(ds, _ds); + loadregister(es, _es); +#endif +} + static void leavedos_call(void *arg) { int *sig = arg; _leavedos_sig(*sig); } -int sigchld_register_handler(pid_t pid, void (*handler)(void*), void *arg) +int sigchld_register_handler(pid_t pid, void (*handler)(void)) { int i; for (i = 0; i < chd_hndl_num; i++) { @@ -209,7 +527,6 @@ int sigchld_register_handler(pid_t pid, void (*handler)(void*), void *arg) chd_hndl_num++; } chld_hndl[i].handler = handler; - chld_hndl[i].arg = arg; chld_hndl[i].pid = pid; chld_hndl[i].enabled = 1; return 0; @@ -217,7 +534,7 @@ int sigchld_register_handler(pid_t pid, void (*handler)(void*), void *arg) int sigchld_enable_cleanup(pid_t pid) { - return sigchld_register_handler(pid, NULL, NULL); + return sigchld_register_handler(pid, NULL); } int sigchld_enable_handler(pid_t pid, int on) @@ -252,20 +569,12 @@ static void cleanup_child(void *arg) /* SIGCHLD handler is one-shot, disarm */ chld_hndl[i].pid = 0; if (chld_hndl[i].handler) - chld_hndl[i].handler(chld_hndl[i].arg); -} - -static void sigbreak(void *uc) -{ - /* let CPUEMU decide what to do, as it can kick in for any backend */ - e_gen_sigalrm(); - if (!in_vm86 && config.cpu_vm_dpmi == CPUVM_NATIVE) - signative_sigbreak(uc); + chld_hndl[i].handler(); } /* this cleaning up is necessary to avoid the port server becoming a zombie process */ -static void sig_child(siginfo_t *si) +static void sig_child(sigcontext_t *scp, siginfo_t *si) { SIGNAL_save(cleanup_child, &si->si_pid, sizeof(si->si_pid), __func__); } @@ -280,30 +589,40 @@ int sigalrm_register_handler(void (*handler)(void)) void leavedos_from_sig(int sig) { - coopth_abandon(); + /* anything more sophisticated? */ _leavedos_main(0, sig); } -void leavedos_sig(int sig) +static void leavedos_sig(int sig) { - static int cnt; - /* disallow multiple terminations */ - if (cnt) - return; - cnt++; - /* do not log anything from a sighandler or it may hang */ + dbug_printf("Terminating on signal %i\n", sig); SIGNAL_save(leavedos_call, &sig, sizeof(sig), __func__); /* abort current sighandlers */ if (in_handle_signals) { + g_printf("Interrupting active signal handlers\n"); in_handle_signals = 0; } } +/* noinline is needed to prevent gcc from caching tls vars before + * calling to init_handler() */ +__attribute__((noinline)) +static void _leavedos_signal(int sig, sigcontext_t *scp) +{ + leavedos_sig(sig); + if (!in_vm86) + dpmi_sigio(scp); +} + +SIG_PROTO_PFX static void leavedos_signal(int sig, siginfo_t *si, void *uc) { + ucontext_t *uct = uc; + sigcontext_t *scp = &uct->uc_mcontext; + init_handler(scp, uct->uc_flags); signal(sig, SIG_DFL); - leavedos_sig(sig); - sigbreak(uc); + _leavedos_signal(sig, scp); + deinit_handler(scp, &uct->uc_flags); } #if 0 @@ -311,43 +630,22 @@ static void leavedos_signal(int sig, siginfo_t *si, void *uc) SIG_PROTO_PFX static void leavedos_emerg(int sig, siginfo_t *si, void *uc) { + ucontext_t *uct = uc; + sigcontext_t *scp = &uct->uc_mcontext; + init_handler(scp, uct->uc_flags); leavedos_from_sig(sig); + deinit_handler(scp, &uct->uc_flags); } #endif SIG_PROTO_PFX static void abort_signal(int sig, siginfo_t *si, void *uc) { - siginfo_debug(si); - _exit(sig); -} - -SIG_PROTO_PFX -static void minfault(int sig, siginfo_t *si, void *uc) -{ -#ifdef HOST_ARCH_X86 -#if defined(__i386__) || defined(X86_EMULATOR) ucontext_t *uct = uc; sigcontext_t *scp = &uct->uc_mcontext; -#endif -#ifdef __i386__ - if (in_vm86 && config.cpu_vm == CPUVM_VM86) { - true_vm86_fault(scp); - return; - } -#endif -#ifdef __FreeBSD__ - /* freebsd fiddles with trapno */ - if (_scp_trapno == T_PAGEFLT) - _scp_trapno = 0xe; -#endif -#ifdef X86_EMULATOR - if (IS_EMU_JIT() && e_emu_fault(scp, in_vm86)) - return; -#endif -#endif - siginfo_debug(si); - leavedos_from_sig(sig); + init_handler(scp, uct->uc_flags); + gdb_debug(); + _exit(sig); } /* Silly Interrupt Generator Initialization/Closedown */ @@ -389,7 +687,7 @@ void SIG_init(void) g_printf("Gonna monitor the IRQ %d you requested\n", irq); sg->fd = -1; sg->irq = irq; - g_printf("SIG: IRQ%d\n", irq); + g_printf("SIG: IRQ%d, enabling PIC-level %ld\n", irq, pic_irq_list[irq]); sg++; } } @@ -431,7 +729,7 @@ void sig_ctx_restore(int tid, void *arg, void *arg2) static void signal_thr_post(int tid, void *arg, void *arg2) { if (!in_handle_signals) { - dbug_printf("in_handle_signals=0\n"); + dosemu_error("in_handle_signals=0\n"); return; } in_handle_signals--; @@ -452,6 +750,101 @@ static void signal_thr(void *arg) sig_c.signal_handler(sig_c.arg); } +static void sigstack_init(void) +{ +#ifndef MAP_STACK +#define MAP_STACK 0 +#endif + + /* sigaltstack_wa is optional. See if we need it. */ + /* .ss_flags is signed int and SS_AUTODISARM is a sign bit :( */ + stack_t dummy2; + stack_t dummy = { .ss_flags = (int)(SS_DISABLE | SS_AUTODISARM) }; + int err = dosemu_sigaltstack(&dummy, &dummy2); + int errno_save = errno; + + /* needs to drop SS_AUTODISARM or asan will fail. See + * https://github.com/dosemu2/dosemu2/issues/1576 */ + dosemu_sigaltstack(&dummy2, NULL); +#if SIGALTSTACK_WA + if ((err && errno_save == EINVAL) +#ifdef __i386__ +#ifdef __linux__ + /* kernels before 4.11 had the needed functionality only for 64bits */ + || kernel_version_code < KERNEL_VERSION(4, 11, 0) +#endif +#endif + ) + { + need_sas_wa = 1; + warn("Enabling sigaltstack() work-around\n"); + /* for SAS WA block all signals. If we dont, there is a + * race that the signal can come after we switched to backup stack + * but before we disabled sigaltstack. We unblock the fatal signals + * later, only right before switching back to dosemu. */ + block_all_sigs = 1; + } else if (err) { + goto unk_err; + } + + if (need_sas_wa) { + cstack = alloc_mapping(MAPPING_SHARED, SIGSTACK_SIZE); + if (cstack == MAP_FAILED) { + error("Unable to allocate stack\n"); + config.exitearly = 1; + return; + } + backup_stack = alias_mapping_high(MAPPING_OTHER, SIGSTACK_SIZE, + PROT_READ | PROT_WRITE, cstack); + if (backup_stack == MAP_FAILED) { + error("Unable to allocate stack\n"); + config.exitearly = 1; + return; + } + } else { + cstack = mmap(NULL, SIGSTACK_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); + if (cstack == MAP_FAILED) { + error("Unable to allocate stack\n"); + config.exitearly = 1; + return; + } + } +#else + if ((err && errno_save == EINVAL) +#ifdef __i386__ +#ifdef __linux__ + || kernel_version_code < KERNEL_VERSION(4, 11, 0) +#endif +#endif + ) + { + error("Your kernel does not support SS_AUTODISARM and the " + "work-around in dosemu is not enabled.\n"); + config.exitearly = 1; + return; + } else if (err) { + goto unk_err; + } + cstack = mmap(NULL, SIGSTACK_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); + if (cstack == MAP_FAILED) { + error("Unable to allocate stack\n"); + config.exitearly = 1; + return; + } +#endif + + return; + +unk_err: + if (err) { + error("sigaltstack() returned %i, %s\n", errno_save, + strerror(errno_save)); + config.exitearly = 1; + } +} + /* DANG_BEGIN_FUNCTION signal_pre_init * * description: @@ -464,79 +857,88 @@ static void signal_thr(void *arg) void signal_pre_init(void) { + /* initialize user data & code selector values (used by DPMI code) */ + /* And save %fs, %gs for NPTL */ + eflags_fs_gs.fs = getsegment(fs); + eflags_fs_gs.gs = getsegment(gs); + eflags_fs_gs.eflags = getflags(); + dbug_printf("initial register values: fs: 0x%04x gs: 0x%04x eflags: 0x%04lx\n", + eflags_fs_gs.fs, eflags_fs_gs.gs, eflags_fs_gs.eflags); +#ifdef __x86_64__ + eflags_fs_gs.ds = getsegment(ds); + eflags_fs_gs.es = getsegment(es); + eflags_fs_gs.ss = getsegment(ss); + /* get long fs and gs bases. If they are in the first 32 bits + normal 386-style fs/gs switching can happen so we can ignore + fsbase/gsbase */ + dosemu_arch_prctl(ARCH_GET_FS, &eflags_fs_gs.fsbase); + if (((unsigned long)eflags_fs_gs.fsbase <= 0xffffffff) && eflags_fs_gs.fs) + eflags_fs_gs.fsbase = 0; + dosemu_arch_prctl(ARCH_GET_GS, &eflags_fs_gs.gsbase); + if (((unsigned long)eflags_fs_gs.gsbase <= 0xffffffff) && eflags_fs_gs.gs) + eflags_fs_gs.gsbase = 0; + dbug_printf("initial segment bases: fs: %p gs: %p\n", + eflags_fs_gs.fsbase, eflags_fs_gs.gsbase); +#endif + /* first set up the blocking mask: registersig() and newsetqsig() * adds to it */ sigemptyset(&q_mask); sigemptyset(&nonfatal_q_mask); registersig_std(SIGALRM, SIGALRM_call); - /* SIGIO is only used for irqs from vm86 */ - if (config.cpu_vm == CPUVM_VM86) - registersig_std(SIGIO, SIGIO_call); + registersig_std(SIGIO, SIGIO_call); registersig_std(SIG_THREAD_NOTIFY, async_call); registersig(SIGCHLD, sig_child); newsetqsig(SIGQUIT, leavedos_signal); newsetqsig(SIGINT, leavedos_signal); /* for "graceful" shutdown for ^C too*/ - newsetqsig(SIGHUP, leavedos_signal); +// newsetqsig(SIGHUP, leavedos_emerg); // newsetqsig(SIGTERM, leavedos_emerg); /* below ones are initialized by other subsystems */ -#ifdef USE_CONSOLE_PLUGIN +#ifdef X86_EMULATOR + setup_nf_sig(SIGVTALRM); +#endif setup_nf_sig(SIG_ACQUIRE); setup_nf_sig(SIG_RELEASE); -#endif setup_nf_sig(SIGWINCH); - setup_nf_sig(SIGPROF); + fixupsig(SIGPROF); /* call that after all non-fatal sigs set up */ -#ifdef __i386__ - newsetsig(SIGILL, minfault); - newsetsig(SIGTRAP, minfault); - newsetsig(SIGBUS, minfault); -#else - newsetsig(SIGILL, abort_signal); - newsetsig(SIGTRAP, abort_signal); -#ifdef __APPLE__ - newsetsig(SIGBUS, minfault); -#else - newsetsig(SIGBUS, abort_signal); -#endif -#endif - newsetsig(SIGFPE, minfault); - newsetsig(SIGSEGV, minfault); + newsetsig(SIGILL, dosemu_fault); + newsetsig(SIGFPE, dosemu_fault); + newsetsig(SIGTRAP, dosemu_fault); + newsetsig(SIGBUS, dosemu_fault); newsetsig(SIGABRT, abort_signal); + newsetsig(SIGSEGV, dosemu_fault); /* block async signals so that threads inherit the blockage */ sigprocmask(SIG_BLOCK, &q_mask, NULL); -#if 0 -#if defined(HAVE_PTHREAD_ATTR_SETSIGMASK_NP) && defined(HAVE_PTHREAD_SETATTR_DEFAULT_NP) - { - sigset_t mask; - pthread_attr_t attr; - sigprocmask(SIG_SETMASK, NULL, &mask); - pthread_getattr_default_np(&attr); - pthread_attr_setsigmask_np(&attr, &mask); - pthread_setattr_default_np(&attr); - sig_threads_wa = 0; - } -#endif -#endif signal(SIGPIPE, SIG_IGN); #ifdef __linux__ prctl(PR_SET_PDEATHSIG, SIGQUIT); #endif - dosemu_pthread_self = pthread_self(); rng_init(&cbks, MAX_CBKS, sizeof(struct callback_s)); - - if (config.cpu_vm_dpmi == CPUVM_NATIVE) - signative_pre_init(); } void signal_init(void) { /* signal_init is called after dpmi_setup so this check is safe */ - if (config.cpu_vm_dpmi == CPUVM_NATIVE) - signative_init(); + if (config.cpu_vm_dpmi == CPUVM_NATIVE) { + sigstack_init(); +#if SIGRETURN_WA + /* 4.6+ are able to correctly restore SS */ +#ifdef __linux__ + if (kernel_version_code < KERNEL_VERSION(4, 6, 0)) { + need_sr_wa = 1; + warn("Enabling sigreturn() work-around for old kernel\n"); + /* block all sigs for SR WA. If we dont, the signal can come before + * SS is saved, but we can't restore SS on signal exit. */ + block_all_sigs = 1; + } +#endif +#endif + } sh_tid = coopth_create("signal handling", signal_thr); /* normally we don't need ctx handlers because the thread is detached. @@ -568,7 +970,7 @@ void signal_done(void) if (setitimer(ITIMER_VIRTUAL, &itv, NULL) == -1) g_printf("can't turn off vtimer at shutdown: %s\n", strerror(errno)); sigprocmask(SIG_BLOCK, &nonfatal_q_mask, NULL); - for (i = 1; i < SIGMAX; i++) { + for (i = 0; i < NSIG; i++) { if (sigismember(&q_mask, i)) signal(i, SIG_DFL); } @@ -602,7 +1004,7 @@ int signal_pending(void) * Due to signals happening at any time, the actual work to be done * because a signal occurs is done here in a serial fashion. * - * The concept, should this eventually work, is that a signal should only + * The concept, should this eventualy work, is that a signal should only * flag that it has occurred and let DOSEMU deal with it in an orderly * fashion as it executes the rest of it's code. * @@ -611,7 +1013,6 @@ int signal_pending(void) */ void handle_signals(void) { - process_callbacks(); while (signal_pending() && !in_handle_signals) { in_handle_signals++; coopth_start(sh_tid, NULL); @@ -657,10 +1058,9 @@ static void SIGALRM_call(void *arg) } uncache_time(); + /* inject timer before anything else */ timer_tick(); - - if (Video->handle_events && video_initialized) - Video->handle_events(); + process_callbacks(); if ((pic_sys_time-cnt10) >= (PIT_TICK_RATE/100) || dosemu_frozen) { cnt10 = pic_sys_time; @@ -671,6 +1071,25 @@ static void SIGALRM_call(void *arg) for (i = 0; i < alrm_hndl_num; i++) alrm_hndl[i].handler(); + if (config.rdtsc) + update_cputime_TSCBase(); + +#if 0 +/* + * DANG_BEGIN_REMARK + * Check for keyboard coming from client + * For now, first byte is interrupt requests from Client + * DANG_END_REMARK + */ + if (*(u_char *)(shared_qf_memory + CLIENT_REQUEST_FLAG_AREA) & 0x40) { + k_printf("KBD: Client sent key\n"); + pic_request (PIC_IRQ1); + *(u_char *)(shared_qf_memory + CLIENT_REQUEST_FLAG_AREA) &= ~0x40; + } +#endif + + io_select(); /* we need this in order to catch lost SIGIOs */ + alarm_idle(); /* Here we 'type in' prestrokes from commandline, as long as there are any @@ -729,15 +1148,30 @@ void SIGNAL_save(void (*signal_call)(void *), void *arg, size_t len, memcpy(signal_queue[SIGNAL_tail].arg, arg, len); signal_queue[SIGNAL_tail].name = name; SIGNAL_tail = (SIGNAL_tail + 1) % MAX_SIG_QUEUE_SIZE; + if (in_dpmi_pm()) + dpmi_return_request(); } +/* + * DANG_BEGIN_FUNCTION SIGIO_call + * + * description: + * Whenever I/O occurs on devices allowing SIGIO to occur, DOSEMU + * will be flagged to run this call which inturn checks which + * fd(s) was set and execute the proper routine to get the I/O + * from that device. + * + * DANG_END_FUNCTION + * + */ static void SIGIO_call(void *arg){ /* Call select to see if any I/O is ready on devices */ - irq_select(); + io_select(); } -static void sigasync0(int sig) +__attribute__((noinline)) +static void sigasync0(int sig, sigcontext_t *scp, siginfo_t *si) { pthread_t tid = pthread_self(); if (!pthread_equal(tid, dosemu_pthread_self)) { @@ -749,24 +1183,52 @@ static void sigasync0(int sig) dosemu_error("Async signal %i from thread\n", sig); #endif } -} - -static void sigasync(int sig, siginfo_t *si, void *uc) -{ - sigasync0(sig); if (sighandlers[sig]) - sighandlers[sig](si); + sighandlers[sig](scp, si); } -static void sigasync_std(int sig, siginfo_t *si, void *uc) +__attribute__((noinline)) +static void sigasync0_std(int sig, sigcontext_t *scp, siginfo_t *si) { - sigasync0(sig); + pthread_t tid = pthread_self(); + if (!pthread_equal(tid, dosemu_pthread_self)) { +#if defined(HAVE_PTHREAD_GETNAME_NP) && defined(__GLIBC__) + char name[128]; + pthread_getname_np(tid, name, sizeof(name)); + dosemu_error("Async signal %i from thread %s\n", sig, name); +#else + dosemu_error("Async signal %i from thread\n", sig); +#endif + } + if (!asighandlers[sig]) { error("handler for sig %i not registered\n", sig); return; } + e_gen_sigalrm(scp); SIGNAL_save(asighandlers[sig], NULL, 0, __func__); - sigbreak(uc); + if (!in_vm86) + dpmi_sigio(scp); +} + +SIG_PROTO_PFX +static void sigasync(int sig, siginfo_t *si, void *uc) +{ + ucontext_t *uct = uc; + sigcontext_t *scp = &uct->uc_mcontext; + init_handler(scp, uct->uc_flags); + sigasync0(sig, scp, si); + deinit_handler(scp, &uct->uc_flags); +} + +SIG_PROTO_PFX +static void sigasync_std(int sig, siginfo_t *si, void *uc) +{ + ucontext_t *uct = uc; + sigcontext_t *scp = &uct->uc_mcontext; + init_handler(scp, uct->uc_flags); + sigasync0_std(sig, scp, si); + deinit_handler(scp, &uct->uc_flags); } @@ -786,9 +1248,6 @@ void do_periodic_stuff(void) if (video_initialized && Video && Video->change_config) update_xtitle(); - - if (Video->handle_events && video_initialized) - Video->handle_events(); } void add_thread_callback(void (*cb)(void *), void *arg, const char *name) @@ -806,11 +1265,7 @@ void add_thread_callback(void (*cb)(void *), void *arg, const char *name) if (!i) error("callback queue overflow, %s\n", name); } - /* FIXME: remove the hack below */ - if (config.cpu_vm == CPUVM_EMU && config.cpu_vm_dpmi == CPUVM_EMU) - e_gen_sigalrm(); - else - pthread_kill(dosemu_pthread_self, SIG_THREAD_NOTIFY); + pthread_kill(dosemu_pthread_self, SIG_THREAD_NOTIFY); } static void process_callbacks(void) @@ -832,6 +1287,96 @@ static void async_call(void *arg) process_callbacks(); } +static int saved_fc; + +void signal_switch_to_dosemu(void) +{ + saved_fc = fault_cnt; + fault_cnt = 0; +} + +void signal_switch_to_dpmi(void) +{ + fault_cnt = saved_fc; +} + +#if SIGALTSTACK_WA +static void signal_sas_wa(void) +{ + int err; + stack_t ss = {}; + m_ucontext_t hack; + unsigned char *sp; + unsigned char *top = cstack + SIGSTACK_SIZE; + unsigned char *btop = backup_stack + SIGSTACK_SIZE; + ptrdiff_t delta; + + if (getmcontext(&hack) == 0) { + sp = alloca(sizeof(void *)); + delta = top - sp; + /* switch stack to its mirror (same phys addr) to cheat sigaltstack() */ + asm volatile( +#ifdef __x86_64__ + "mov %0, %%rsp\n" +#else + "mov %0, %%esp\n" +#endif + :: "r"(btop - delta)); + } else { + sigprocmask(SIG_UNBLOCK, &fatal_q_mask, NULL); + return; + } + + ss.ss_flags = SS_DISABLE; + /* sas will re-enable itself when returning from sighandler */ + err = dosemu_sigaltstack(&ss, NULL); + if (err) + perror("sigaltstack"); + + setmcontext(&hack); +} +#endif + +void signal_return_to_dosemu(void) +{ +#if SIGALTSTACK_WA + if (need_sas_wa) + signal_sas_wa(); +#endif +} + +void signal_return_to_dpmi(void) +{ +} + +void signal_set_altstack(int on) +{ + stack_t stk = { 0 }; + int err; + + if (!on) { + stk.ss_flags = SS_DISABLE; + err = sigaltstack(&stk, NULL); + } else { + stk.ss_sp = cstack; + stk.ss_size = SIGSTACK_SIZE; +#if SIGALTSTACK_WA + stk.ss_flags = SS_ONSTACK | (need_sas_wa ? 0 : SS_AUTODISARM); +#else + stk.ss_flags = SS_ONSTACK | SS_AUTODISARM; +#endif + err = sigaltstack(&stk, NULL); + if (err && errno == EINVAL) { + /* work-around for musl that doesn't accept extension flags */ + err = dosemu_sigaltstack(&stk, NULL); + } + } + if (err) { + error("sigaltstack(0x%x) returned %i, %s\n", + stk.ss_flags, err, strerror(errno)); + leavedos(err); + } +} void signal_unblock_async_sigs(void) { @@ -847,12 +1392,6 @@ void signal_restore_async_sigs(void) sigprocmask(SIG_BLOCK, &nonfatal_q_mask, NULL); } -void signal_unblock_fatal_sigs(void) -{ - /* unblock only nonfatal, fatals should already be unblocked */ - sigprocmask(SIG_UNBLOCK, &fatal_q_mask, NULL); -} - /* similar to above, but to call from non-signal context */ void signal_block_async_nosig(sigset_t *old_mask) { diff --git a/src/arch/linux/async/sigsegv.c b/src/arch/linux/async/sigsegv.c new file mode 100644 index 0000000..3fac0f8 --- /dev/null +++ b/src/arch/linux/async/sigsegv.c @@ -0,0 +1,553 @@ +#include "mhpdbg.h" +#include "mapping.h" +#include "debug.h" + +/* Define if we want graphics in X (of course we want :-) (root@zaphod) */ +/* WARNING: This may not work in BSD, because it was written for Linux! */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __linux__ +#include +#endif + +#include "emu.h" +#include "utilities.h" +#include "int.h" + +#include "video.h" +#include "vgaemu.h" /* root@zaphod */ + +#include "emudpmi.h" +#include "cpu-emu.h" +#include "dosemu_config.h" +#include "sig.h" + +/* + * All of the functions in this module need to be declared with + * __attribute__((no_instrument_function)) + * so that they can safely handle signals that occur in DPMI context when + * DOSEMU is built with the "-pg" gcc flag (which enables instrumentation for + * gprof profiling). + * + * The reason for this is that mcount(), implicitly called from functions + * instrumented with "-pg", requires access to thread-local state, and on x86, + * TLS is implemented using the GS to refer to a segment in which the + * thread-local variables are stored. + * + * However, in DPMI context, GS does not refer to this segment, and the kernel + * does not (cannot?) restore it to do so when it invokes a signal handler, so + * we must prevent mcount() from being called at all in this context. + */ + + +/* + * DANG_BEGIN_FUNCTION dosemu_fault(int, sigcontext_t); + * + * All CPU exceptions (except 13=general_protection from V86 mode, + * which is directly scanned by the kernel) are handled here. + * + * We have 4 main cases: + * 1. VM86 faults from vm86() (i386 only) + * 2. DPMI faults with LDT _cs (native DPMI only) + * 3. Faults (PF/DE) generated from cpuemu. In this case _cs is the Linux + * userspace _cs + * 4. DOSEMU itself crashes (bad!) + * + * DANG_END_FUNCTION + */ +static void dosemu_fault1(int signum, sigcontext_t *scp) +{ + if (fault_cnt > 1) { + error("Fault handler re-entered! signal=%i _trapno=0x%X\n", + signum, _trapno); + if (!in_vm86 && !DPMIValidSelector(_cs)) { + gdb_debug(); + _exit(43); + } else { + error("BUG: Fault handler re-entered not within dosemu code! in_vm86=%i\n", + in_vm86); + } + goto bad; + } +#ifdef __x86_64__ + if (_trapno == 0x0e && _cr2 > 0xffffffff) + { +#ifdef X86_EMULATOR + if (IS_EMU() && !CONFIG_CPUSIM && e_in_compiled_code()) { + int i; + /* dosemu_error() will SIGSEGV in backtrace(). */ + error("JIT fault accessing invalid address 0x%08"PRI_RG", " + "RIP=0x%08"PRI_RG"\n", _cr2, _rip); + if (mapping_find_hole(_rip, _rip + 64, 1) == MAP_FAILED) { + error("@Generated code dump:\n"); + for (i = 0; i < 64; i++) { + error("@ %02x", *(unsigned char *)(_rip + i)); + if ((i & 15) == 15) + error("@\n"); + } + } + goto bad; + } +#endif + dosemu_error("Accessing invalid address 0x%08"PRI_RG"\n", _cr2); + goto bad; + } +#endif + + +#ifdef __i386__ + /* case 1: note that _cr2 must be 0-based */ + if (in_vm86 && config.cpu_vm == CPUVM_VM86) { + if (_trapno == 0x0e) { + /* we can get to instremu from here, so unblock SIGALRM & friends. + * It is needed to interrupt instremu when it runs for too long. */ + signal_unblock_async_sigs(); + if (vga_emu_fault(_cr2, _err, NULL) == True) + return; + } + vm86_fault(_trapno, _err, _cr2); + return; + } +#endif + + /* case 2: At first let's find out where we came from */ + if (DPMIValidSelector(_cs)) { + int ret = DPMI_RET_FAULT; + assert(config.cpu_vm_dpmi == CPUVM_NATIVE); + if (_trapno == 0x0e) { + int rc; + dosaddr_t cr2 = DOSADDR_REL(LINP(_cr2)); +#ifdef X86_EMULATOR +#ifdef HOST_ARCH_X86 + /* DPMI code touches cpuemu prot */ + if (EMU_V86() && !CONFIG_CPUSIM && + e_handle_pagefault(cr2, _err, scp)) + return; +#endif +#endif + signal_unblock_async_sigs(); + rc = vga_emu_fault(cr2, _err, scp); + /* going for dpmi_fault() or deinit_handler(), + * careful with async signals and sas_wa */ + signal_restore_async_sigs(); + if (rc == True) + ret = dpmi_check_return(); + } + if (_trapno == 0x10) { + dbug_printf("coprocessor exception, calling IRQ13\n"); + print_exception_info(scp); + pic_request(PIC_IRQ13); + dpmi_return(scp, DPMI_RET_DOSEMU); + return; + } + + /* Not in dosemu code: dpmi_fault() will handle that */ + if (ret == DPMI_RET_FAULT) + ret = dpmi_fault(scp); + if (ret != DPMI_RET_CLIENT) + dpmi_return(scp, ret); + return; + } + +#ifdef X86_EMULATOR + /* case 3 */ + if (IS_EMU()) { + /* Possibilities: + * 1. Compiled code touches VGA prot + * 2. Compiled code touches cpuemu prot + * 3. Compiled code touches DPMI prot + * 4. fullsim code touches DPMI prot + * 5. dosemu code touches cpuemu prot (bug) + * Compiled code means dpmi-jit, otherwise vm86 not here. + */ + if (_trapno == 0x0e) { + /* cases 1, 2, 3, 4 */ + if ((in_vm86 || EMU_DPMI()) && e_emu_pagefault(scp, !in_vm86)) + return; + if (!CONFIG_CPUSIM && + e_handle_pagefault(DOSADDR_REL(LINP(_cr2)), _err, scp)) { + /* case 5, any jit, bug */ + dosemu_error("touched jit-protected page%s\n", + in_vm86 ? " in vm86-emu" : ""); + return; + } + } else if ((in_vm86 || EMU_DPMI()) && + !CONFIG_CPUSIM && e_handle_fault(scp)) { + /* compiled code can cause fault (usually DE, Divide Exception) */ + return; + } + } +#endif + + /* case 4 */ + error("Fault in dosemu code, in_dpmi=%i\n", dpmi_active()); + /* TODO - we can start gdb here */ + /* start_gdb() */ + /* Going to die from here */ + +bad: +/* All recovery attempts failed, going to die :( */ + + { +#ifdef __x86_64__ + unsigned char *fsbase, *gsbase; +#endif + error("cpu exception in dosemu code outside of %s!\n" + "sig: %i trapno: 0x%02x errorcode: 0x%08x cr2: 0x%08"PRI_RG"\n" + "eip: 0x%08"PRI_RG" esp: 0x%08"PRI_RG" eflags: 0x%08x\n" + "cs: 0x%04x ds: 0x%04x es: 0x%04x ss: 0x%04x\n" + "fs: 0x%04x gs: 0x%04x\n", + (in_dpmi_pm() ? "DPMI client" : "VM86()"), + signum, _trapno, _err, _cr2, + _rip, _rsp, _eflags, _cs, _ds, _es, _ss, _fs, _gs); +#ifdef __x86_64__ + dosemu_arch_prctl(ARCH_GET_FS, &fsbase); + dosemu_arch_prctl(ARCH_GET_GS, &gsbase); + error("@fsbase: %p gsbase: %p\n", fsbase, gsbase); +#endif + error("@\n"); + + error("Please install gdb, update dosemu from git, compile it with debug\n" + "info and make a bug report with the content of ~/.dosemu/boot.log at\n" +"https://github.com/dosemu2/dosemu2/issues\n"); + error("@Please provide any additional info you can, like the test-cases,\n" + "URLs and all the rest that fits.\n\n"); +#ifdef X86_EMULATOR + /* gdb_debug() will crash in jit code doing backtrace() */ + if (!(IS_EMU() && !CONFIG_CPUSIM && e_in_compiled_code())) +#endif + gdb_debug(); + + if (DPMIValidSelector(_cs)) + print_exception_info(scp); + if (in_vm86) + show_regs(); + fatalerr = 4; + _leavedos_main(0, signum); /* shouldn't return */ + } +} + +/* noinline is to prevent gcc from moving TLS access around init_handler() */ +__attribute__((noinline)) +static void dosemu_fault0(int signum, sigcontext_t *scp) +{ + pthread_t tid; + + if (fault_cnt > 2) { + /* + * At this point we already tried leavedos(). Now try _exit() + * and NOT exit(3), because glibc is probably malfunctions if + * we are here. + */ + _exit(255); + } + + tid = pthread_self(); + if (!pthread_equal(tid, dosemu_pthread_self)) { +#ifdef __GLIBC__ + char name[128]; +#endif + /* disable cancellation to prevent main thread from terminating + * this one due to SIGSEGV elsewhere while we are doing backtrace */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); +#if defined(HAVE_PTHREAD_GETNAME_NP) && defined(__GLIBC__) + pthread_getname_np(tid, name, sizeof(name)); + dosemu_error("thread %s got signal %i, cr2=%llx\n", name, signum, + (unsigned long long)_cr2); +#else + dosemu_error("thread got signal %i, cr2=%llx\n", signum, + (unsigned long long)_cr2); +#endif + signal(signum, SIG_DFL); + pthread_kill(tid, signum); // dump core + _exit(23); + return; + } + +#ifdef __linux__ + if (kernel_version_code < KERNEL_VERSION(2, 6, 14)) { + sigset_t set; + + /* this emulates SA_NODEFER, so that we can double fault. + SA_NODEFER only works as documented in Linux kernels >= 2.6.14. + */ + sigemptyset(&set); + sigaddset(&set, signum); + sigprocmask(SIG_UNBLOCK, &set, NULL); + } +#endif + + if (debug_level('g')>7) + g_printf("Entering fault handler, signal=%i _trapno=0x%X\n", + signum, _trapno); + + dosemu_fault1(signum, scp); + + if (debug_level('g')>8) + g_printf("Returning from the fault handler\n"); +} + +SIG_PROTO_PFX +void dosemu_fault(int signum, siginfo_t *si, void *uc) +{ + ucontext_t *uct = uc; + sigcontext_t *scp = &uct->uc_mcontext; + /* need to call init_handler() before any syscall. + * Additionally, TLS access should be done in a separate no-inline + * function, so that gcc not to move the TLS access around init_handler(). */ + init_handler(scp, uct->uc_flags); +#if defined(__FreeBSD__) + /* freebsd does not provide cr2 */ + _cr2 = (uintptr_t)si->si_addr; +#endif + fault_cnt++; + dosemu_fault0(signum, scp); + fault_cnt--; + deinit_handler(scp, &uct->uc_flags); +} + +/* + * DANG_BEGIN_FUNCTION print_exception_info + * + * Prints information about an exception: exception number, error code, + * address, reason, etc. + * + * DANG_END_FUNCTION + * + */ +void print_exception_info(sigcontext_t *scp) +{ + int i; + + switch(_trapno) + { + case 0: + error("@Division by zero\n"); + break; + + + case 1: + error("@Debug exception\n"); + break; + + + case 3: + error("@Breakpoint exception (caused by INT 3 instruction)\n"); + break; + + + case 4: + error("@Overflow exception (caused by INTO instruction)\n"); + break; + + + case 5: + error("@Bound exception (caused by BOUND instruction)\n"); + break; + + + case 6: { + unsigned char *csp; + int ps = getpagesize(); + unsigned pa = _rip & (ps - 1); + int sub = _min(pa, 10); + int sup = _min(ps - pa, 10); + error("@Invalid opcode\n"); + error("@Opcodes: "); + csp = (unsigned char *) _rip - sub; + for (i = 0; i < 10 - sub; i++) + error("@XX "); + for (i = 0; i < sub; i++) + error("@%02x ", *csp++); + error("@-> "); + for (i = 0; i < sup; i++) + error("@%02x ", *csp++); + for (i = 0; i < 10 - sup; i++) + error("@XX "); + error("@\n"); + break; + } + + case 7: + error("@Coprocessor exception (coprocessor not available)\n"); + /* I'd like to print some info on the EM, MP, and TS flags in CR0, + * but I don't know where I can get that information :-( + * Anyway, this exception should not happen... (Erik Mouw) + */ + break; + + + case 8: + error("@Double fault\n"); + break; + + + case 9: + error("@Coprocessor segment overflow\n"); + break; + + + case 0xa: + error("@Invalid TSS\n"); + if(_err & 0x02) + error("@IDT"); + else if(_err & 0x04) + error("@LDT"); + else + error("@GDT"); + + error("@ selector: 0x%04x\n", ((_err >> 3) & 0x1fff )); + + if(_err & 0x01) + error("@Exception was not caused by DOSEMU\n"); + else + error("@Exception was caused by DOSEMU\n"); + break; + + + case 0xb: + error("@Segment not available\n"); + /* This is the same code as case 0x0a; the compiler merges these + * blocks, so I don't have to edit some dirty constructions to + * generate one block of code. (Erik Mouw) + */ + if(_err & 0x02) + error("@IDT"); + else if(_err & 0x04) + error("@LDT"); + else + error("@GDT"); + + error("@ selector: 0x%04x\n", ((_err >> 3) & 0x1fff )); + + if(_err & 0x01) + error("@Exception was not caused by DOSEMU\n"); + else + error("@Exception was caused by DOSEMU\n"); + break; + + + case 0xc: + error("@Stack exception\n"); + break; + + + case 0xd: + error("@General protection exception\n"); + /* This is the same code as case 0x0a; the compiler merges these + * blocks, so I don't have to edit some dirty constructions to + * generate one block of code. (Erik Mouw) + */ + if(_err & 0x02) + error("@IDT"); + else if(_err & 0x04) + error("@LDT"); + else + error("@GDT"); + + error("@ selector: 0x%04x\n", ((_err >> 3) & 0x1fff )); + + if(_err & 0x01) + error("@Exception was not caused by DOSEMU\n"); + else + error("@Exception was caused by DOSEMU\n"); + break; + + + case 0xe: + error("@Page fault: "); + if(_err & 0x02) + error("@write"); + else + error("@read"); + + error("@ instruction to linear address: 0x%08"PRI_RG"\n", _cr2); + + error("@CPU was in "); + if(_err & 0x04) + error("@user mode\n"); + else + error("@supervisor mode\n"); + + error("@Exception was caused by "); + if(_err & 0x01) + error("@insufficient privilege\n"); + else + error("@non-available page\n"); + break; + + case 0x10: { + int i, n; + unsigned short sw; + fpregset_t p = __fpstate; + error ("@Coprocessor Error:\n"); +#ifdef __x86_64__ + error ("@cwd=%04x swd=%04x ftw=%04x\n", p->cwd, p->swd, p->ftw); + error ("@cs:rip=%04x:%08lx ds:data=%04x:%08lx\n", _cs,p->rip,_ds,p->rdp); + sw = p->swd; +#else + error ("@cw=%04x sw=%04x tag=%04x\n", + ((unsigned short)(p->cw)),((unsigned short)(p->sw)), + ((unsigned short)(p->tag))); + error ("@cs:eip=%04x:%08x ds:data=%04x:%08x\n", + ((unsigned short)(p->cssel)),(unsigned)p->ipoff, + ((unsigned short)(p->datasel)),(unsigned)p->dataoff); + sw = p->sw; +#endif + if ((sw&0x80)==0) error("@No error summary bit,why?\n"); + else { + if (sw&0x20) error("@Precision\n"); + if (sw&0x10) error("@Underflow\n"); + if (sw&0x08) error("@Overflow\n"); + if (sw&0x04) error("@Divide by 0\n"); + if (sw&0x02) error("@Denormalized\n"); + if ((sw&0x41)==0x01) error("@Invalid op\n"); + else if ((sw&0x41)==0x41) error("@Stack fault\n"); + } + n = (sw >> 11) & 7; + for (i=0; i<8; i++) { + unsigned short *r = p->_st[i].significand; + unsigned short e = p->_st[i].exponent; + error ("@fpr[%d] = %04x:%04x%04x%04x%04x\n",n,e,r[3],r[2],r[1],r[0]); + n = (n+1) & 7; + } + } break; + + case 0x13: { +#ifdef __x86_64__ + int i; + unsigned mxcsr; + fpregset_t p = __fpstate; + error ("@SIMD Floating-Point Exception:\n"); + mxcsr = p->mxcsr; + error ("@mxcsr=%08x, mxcr_mask=%08x\n",mxcsr,(unsigned)(p->mxcr_mask)); + if (mxcsr&0x40) error("@Denormals are zero\n"); + if (mxcsr&0x20) error("@Precision\n"); + if (mxcsr&0x10) error("@Underflow\n"); + if (mxcsr&0x08) error("@Overflow\n"); + if (mxcsr&0x04) error("@Divide by 0\n"); + if (mxcsr&0x02) error("@Denormalized\n"); + if (mxcsr&0x01) error("@Invalid op\n"); + for (i=0; i_xmm)/sizeof(p->_xmm[0]); i++) + { + error ("@xmm[%d] = %08x:%08x:%08x:%08x\n",i, + (unsigned)p->_xmm[i].element[0], (unsigned)p->_xmm[i].element[1], + (unsigned)p->_xmm[i].element[2], (unsigned)p->_xmm[i].element[3]); + } +#else + error ("@SIMD Floating-Point Exception\n"); +#endif + break; + } + + default: + error("@Unknown exception\n"); + break; + } +} diff --git a/src/base/lib/mapping/Makefile b/src/arch/linux/mapping/Makefile similarity index 94% rename from src/base/lib/mapping/Makefile rename to src/arch/linux/mapping/Makefile index 6bb2f7d..9ca5ad3 100644 --- a/src/base/lib/mapping/Makefile +++ b/src/arch/linux/mapping/Makefile @@ -12,7 +12,7 @@ include $(top_builddir)/Makefile.conf #The C files, include files and dependancies here. -CFILES = mapping.c mapfile.c mapashm.c +CFILES = mapping.c mapshm.c mapfile.c DEPENDS = $(CFILES:.c=.d) HFILES = diff --git a/src/arch/linux/mapping/mapfile.c b/src/arch/linux/mapping/mapfile.c new file mode 100644 index 0000000..978bb68 --- /dev/null +++ b/src/arch/linux/mapping/mapfile.c @@ -0,0 +1,329 @@ +/* + * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". + * + * for details see file COPYING in the DOSEMU distribution + */ + +/* + * Purpose: memory mapping library, posix SHM and file backends. + * + * Authors: Stas Sergeev, Bart Oldeman. + * Initially started by Hans Lermen, old copyrights below: + */ +/* file mapfile.c + * file mapping driver + * Hans Lermen, lermen@fgan.de + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "emu.h" +#include "mapping.h" +#include "smalloc.h" +#include "utilities.h" + +/* ------------------------------------------------------------ */ + +static smpool pgmpool; +static int mpool_numpages = (32 * 1024) / 4; +static char *mpool = 0; + +static int tmpfile_fd = -1; + +static void *alias_mapping_file(int cap, void *target, size_t mapsize, int protect, void *source) +{ + int fixed = 0; + off_t offs = (char *)source - mpool; + void *addr; + + if (offs < 0 || (offs+mapsize >= (mpool_numpages*PAGE_SIZE))) { + Q_printf("MAPPING: alias_map to address outside of temp file\n"); + errno = EINVAL; + return MAP_FAILED; + } + if (target != (void *)-1) + fixed = MAP_FIXED; + else + target = NULL; + addr = mmap(target, mapsize, protect, MAP_SHARED | fixed, tmpfile_fd, offs); + if (addr == MAP_FAILED) { + addr = mmap(target, mapsize, protect & ~PROT_EXEC, MAP_SHARED | fixed, + tmpfile_fd, offs); + if (addr != MAP_FAILED) { + int ret = mprotect(addr, mapsize, protect); + if (ret == -1) { + perror("mprotect()"); + error("shared memory mprotect failed, exiting\n"); + leavedos(2); + return NULL; + } + } + } +#if 1 + Q_printf("MAPPING: alias_map, fileoffs %llx to %p size %zx, result %p\n", + (long long)offs, target, mapsize, addr); +#endif + return addr; +} + +static void discardtempfile(void) +{ + close(tmpfile_fd); + tmpfile_fd = -1; +} + +static int open_mapping_f(int cap) +{ + int mapsize, estsize, padsize; + + if (cap) Q_printf("MAPPING: open, cap=%s\n", + decode_mapping_cap(cap)); + + padsize = 4*1024; + + /* first estimate the needed size of the mapfile */ + mapsize = HMASIZE >> 10; /* HMA */ + /* VGAEMU */ + mapsize += config.vgaemu_memsize ? config.vgaemu_memsize : 1024; + mapsize += config.ems_size; /* EMS */ + mapsize += LOWMEM_SIZE >> 10; /* Low Mem */ + estsize = mapsize; + /* keep heap fragmentation in mind */ + mapsize += (mapsize/4 < padsize ? padsize : mapsize/4); + mpool_numpages = mapsize / 4; + mapsize = mpool_numpages * PAGE_SIZE; /* make sure we are page aligned */ + + ftruncate(tmpfile_fd, 0); + if (ftruncate(tmpfile_fd, mapsize) == -1) { + if (!cap) + error("MAPPING: cannot size temp file pool, %s\n",strerror(errno)); + discardtempfile(); + if (!cap)return 0; + leavedos(2); + } + /* /dev/shm may be mounted noexec, and then mounting PROT_EXEC fails. + However mprotect may work around this (maybe not in future kernels) + */ + mpool = mmap(0, mapsize, PROT_READ|PROT_WRITE, + MAP_SHARED, tmpfile_fd, 0); + if (mpool == MAP_FAILED || + mprotect(mpool, mapsize, PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { + error("MAPPING: cannot mmap shared memory pool, %s\n", strerror(errno)); + discardtempfile(); + if (!cap) + return 0; + leavedos(2); + } + /* the memory pool itself can just be rw though */ + mprotect(mpool, mapsize, PROT_READ|PROT_WRITE); + Q_printf("MAPPING: open, mpool (min %dK) is %d Kbytes at %p-%p\n", + estsize, mapsize/1024, mpool, mpool+mapsize-1); + sminit(&pgmpool, mpool, mapsize); + + /* + * Now handle individual cases. + * Don't forget that each of the below code pieces should only + * be executed once ! + */ + +#if 0 + if (cap & MAPPING_OTHER) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_EMS) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_DPMI) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_VIDEO) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_VGAEMU) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_HGC) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_HMA) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_SHARED) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_INIT_HWRAM) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_INIT_LOWRAM) { + /* none for now */ + } +#endif + + return 1; +} + +static int open_mapping_file(int cap) +{ + if (tmpfile_fd < 0) { + // Requires a Linux kernel version >= 3.11.0 + tmpfile_fd = open("/tmp", O_TMPFILE | O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR); + open_mapping_f(cap); + } + return 1; +} + +#ifdef HAVE_SHM_OPEN +static int open_mapping_pshm(int cap) +{ + char *name; + int ret; + + if (tmpfile_fd < 0) { + ret = asprintf(&name, "/dosemu_%d", getpid()); + assert(ret != -1); + /* FD_CLOEXEC is set by default */ + tmpfile_fd = shm_open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (tmpfile_fd == -1) { + free(name); + return 0; + } + shm_unlink(name); + free(name); + if (!open_mapping_f(cap)) + return 0; + } + return 1; +} +#endif + +#ifdef HAVE_MEMFD_CREATE +static int open_mapping_mshm(int cap) +{ + char *name; + int ret; + + if (tmpfile_fd < 0) { + ret = asprintf(&name, "dosemu_%d", getpid()); + assert(ret != -1); + + tmpfile_fd = memfd_create(name, MFD_CLOEXEC); + free(name); + if (tmpfile_fd == -1) + return 0; + if (!open_mapping_f(cap)) + return 0; + } + return 1; +} +#endif + +static void close_mapping_file(int cap) +{ + Q_printf("MAPPING: close, cap=%s\n", decode_mapping_cap(cap)); + if (cap == MAPPING_ALL && tmpfile_fd != -1) discardtempfile(); +} + +static void *alloc_mapping_file(int cap, size_t mapsize) +{ + Q__printf("MAPPING: alloc, cap=%s, mapsize=%zx\n", cap, mapsize); + return smalloc(&pgmpool, mapsize); +} + +static void free_mapping_file(int cap, void *addr, size_t mapsize) +/* NOTE: addr needs to be the same as what was supplied by alloc_mapping_file */ +{ + Q__printf("MAPPING: free, cap=%s, addr=%p, mapsize=%zx\n", + cap, addr, mapsize); + smfree(&pgmpool, addr); +} + +/* + * NOTE: DPMI relies on realloc_mapping() _not_ changing the address ('addr'), + * when shrinking the memory region. + */ +static void *realloc_mapping_file(int cap, void *addr, size_t oldsize, size_t newsize) +{ + Q__printf("MAPPING: realloc, cap=%s, addr=%p, oldsize=%zx, newsize=%zx\n", + cap, addr, oldsize, newsize); + if (cap & (MAPPING_EMS | MAPPING_DPMI)) { + int size = smget_area_size(&pgmpool, addr); + void *addr_; + + if (!size || size != oldsize) return (void *)-1; + if (size == newsize) return addr; + /* NOTE: smrealloc() does not change addr, + * when shrinking the memory region. + */ + addr_ = smrealloc(&pgmpool, addr, newsize); + if (!addr_) { + Q_printf("MAPPING: pgrealloc(0x%p,0x%zx,) failed\n", + addr, newsize); + return (void *)-1; + } + return addr_; + } + return (void *)-1; +} + +#ifdef HAVE_SHM_OPEN +struct mappingdrivers mappingdriver_shm = { + "mapshm", + "Posix SHM mapping", + open_mapping_pshm, + close_mapping_file, + alloc_mapping_file, + free_mapping_file, + realloc_mapping_file, + alias_mapping_file +}; +#endif + +#ifdef HAVE_MEMFD_CREATE +struct mappingdrivers mappingdriver_mshm = { + "mapmshm", + "memfd mapping", + open_mapping_mshm, + close_mapping_file, + alloc_mapping_file, + free_mapping_file, + realloc_mapping_file, + alias_mapping_file +}; +#endif + +struct mappingdrivers mappingdriver_file = { + "mapfile", + "temp file mapping", + open_mapping_file, + close_mapping_file, + alloc_mapping_file, + free_mapping_file, + realloc_mapping_file, + alias_mapping_file +}; diff --git a/src/base/lib/mapping/mapping.c b/src/arch/linux/mapping/mapping.c similarity index 59% rename from src/base/lib/mapping/mapping.c rename to src/arch/linux/mapping/mapping.c index de0ba97..aa3339d 100644 --- a/src/base/lib/mapping/mapping.c +++ b/src/arch/linux/mapping/mapping.c @@ -25,12 +25,11 @@ */ #include "emu.h" -#include "xms.h" +#include "hma.h" #include "utilities.h" #include "dos2linux.h" #include "kvm.h" #include "mapping.h" -#include "smalloc.h" #include #include #include @@ -41,10 +40,12 @@ #include #endif -#ifdef __i386__ -enum { MEM_BASE, KVM_BASE, VM86_BASE, MAX_BASES }; +#ifndef __x86_64__ +#undef MAP_32BIT +#define MAP_32BIT 0 +enum { MEM_BASE, VM86_BASE, MAX_BASES }; #else -enum { MEM_BASE, KVM_BASE, MAX_BASES }; +enum { MEM_BASE, MAX_BASES }; #endif struct mem_map_struct { @@ -53,6 +54,7 @@ struct mem_map_struct { void *base[MAX_BASES]; dosaddr_t dst; int len; + int mapped; }; #ifdef __linux__ @@ -63,20 +65,13 @@ static struct mem_map_struct kmem_map[MAX_KMEM_MAPPINGS]; static int init_done = 0; unsigned char *mem_base; -uintptr_t mem_base_mask; -static struct { - unsigned char *base; - size_t size; -} mem_bases[MAX_BASES]; +static unsigned char *mem_bases[MAX_BASES]; uint8_t *lowmem_base; static struct mappingdrivers *mappingdrv[] = { #ifdef HAVE_MEMFD_CREATE &mappingdriver_mshm, /* first try memfd mmap */ #endif -#ifdef __APPLE__ - &mappingdriver_ashm, /* on Mac first try private anon-mmap + mach_vm_remap */ -#endif #ifdef HAVE_SHM_OPEN &mappingdriver_shm, /* then shm_open which is usually broken */ #endif @@ -88,56 +83,43 @@ static struct mappingdrivers *mappingdrv[] = { static struct mappingdrivers *mappingdriver; -#define ALIAS_SIZE (LOWMEM_SIZE + HMASIZE) -static unsigned char *lowmem_aliasmap[ALIAS_SIZE/PAGE_SIZE]; -struct hardware_ram; -static dosaddr_t do_get_hardware_ram(unsigned addr, uint32_t size, - struct hardware_ram **r_hw); -static unsigned do_find_hardware_ram(dosaddr_t va, uint32_t size, - struct hardware_ram **r_hw); -static void hwram_update_aliasmap(struct hardware_ram *hw, unsigned addr, - int size, unsigned char *src); +/* The alias map is used to track alias mappings from the first 1MB + HMA + to the corresponding addresses in Linux address space (either lowmem, + vgaemu, or EMS). The DOS address (&mem_base[address]) may be r/w + protected by cpuemu or vgaemu, but the alias is never protected, + so it can be used to write without needing to unprotect and reprotect + afterwards. + If the alias is not used (hardware RAM from /dev/mem, or DPMI memory + (aliasing using fn 0x509 is safely ignored here)), + the address is identity-mapped to &mem_base[address]. +*/ +static unsigned char *aliasmap[(LOWMEM_SIZE+HMASIZE)/PAGE_SIZE]; static void update_aliasmap(dosaddr_t dosaddr, size_t mapsize, unsigned char *unixaddr) { - unsigned addr2; - struct hardware_ram *hw; + unsigned int dospage, i; - if (dosaddr >= mem_bases[MEM_BASE].size) + if (dosaddr >= LOWMEM_SIZE+HMASIZE) return; - addr2 = do_find_hardware_ram(dosaddr, mapsize, &hw); - if (addr2 == (unsigned)-1) - return; - hwram_update_aliasmap(hw, addr2, mapsize, unixaddr); - invalidate_unprotected_page_cache(dosaddr, mapsize); + dospage = dosaddr >> PAGE_SHIFT; + for (i = 0; i < mapsize >> PAGE_SHIFT; i++) + aliasmap[dospage + i] = unixaddr ? unixaddr + (i << PAGE_SHIFT) : NULL; } -void *dosaddr_to_unixaddr(dosaddr_t addr) +void *dosaddr_to_unixaddr(unsigned int addr) { - if (addr < ALIAS_SIZE) - return lowmem_aliasmap[addr >> PAGE_SHIFT] + (addr & (PAGE_SIZE - 1)); + if (addr < LOWMEM_SIZE + HMASIZE && aliasmap[addr >> PAGE_SHIFT]) + return aliasmap[addr >> PAGE_SHIFT] + (addr & (PAGE_SIZE - 1)); return MEM_BASE32(addr); } void *physaddr_to_unixaddr(unsigned int addr) { - void *hwr = get_hardware_uaddr(addr); - if (hwr != MAP_FAILED) - return hwr; - if (addr < ALIAS_SIZE) + if (addr < LOWMEM_SIZE + HMASIZE) return dosaddr_to_unixaddr(addr); - return MAP_FAILED; -} - -dosaddr_t physaddr_to_dosaddr(unsigned int addr, int len) -{ - dosaddr_t ret = get_hardware_ram(addr, len); - if (ret != (dosaddr_t)-1) - return ret; - if (addr + len <= ALIAS_SIZE) - return addr; - return -1; + /* XXX something other than XMS? */ + return &ext_mem_base[addr - (LOWMEM_SIZE + HMASIZE)]; } #ifdef __linux__ @@ -160,7 +142,7 @@ static int map_find(struct mem_map_struct *map, int max, int idx = -1; dosaddr_t max_addr = addr + size; for (i = 0; i < max; i++) { - if (!map[i].dst || !map[i].len || (map[i].dst != -1) != mapped) + if (!map[i].dst || !map[i].len || map[i].mapped != mapped) continue; dst = map[i].dst; dst1 = dst + map[i].len; @@ -181,20 +163,49 @@ static int map_find(struct mem_map_struct *map, int max, } #endif -static unsigned char *MEM_BASE32x(dosaddr_t a, int base) +static inline unsigned char *MEM_BASE32x(dosaddr_t a, int base) { - if (mem_bases[base].base == MAP_FAILED || a >= mem_bases[base].size) + uint32_t off; + if (mem_bases[base] == MAP_FAILED) return MAP_FAILED; - return &mem_bases[base].base[a]; + assert(a < LOWMEM_SIZE + HMASIZE || base == MEM_BASE); + off = (uint32_t)((uintptr_t)mem_bases[base] + a); + return LINP(off); } #ifdef __linux__ -// counts number of kmem mappings, only used for assert -static int kmem_mapped(dosaddr_t addr, int mapsize) +static dosaddr_t kmem_unmap_single(int cap, int idx) +{ + if (cap & MAPPING_LOWMEM) { + int i; + for(i = 0; i < MAX_BASES; i++) { + void *dst = MEM_BASE32x(kmem_map[idx].dst, i); + if (dst == MAP_FAILED) + continue; + kmem_map[idx].base[i] = mmap(0, kmem_map[idx].len, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + mremap(dst, kmem_map[idx].len, + kmem_map[idx].len, MREMAP_MAYMOVE | MREMAP_FIXED, + kmem_map[idx].base[i]); + } + } else { + kmem_map[idx].base[MEM_BASE] = mmap(0, kmem_map[idx].len, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + mremap(MEM_BASE32(kmem_map[idx].dst), kmem_map[idx].len, + kmem_map[idx].len, MREMAP_MAYMOVE | MREMAP_FIXED, + kmem_map[idx].base[MEM_BASE]); + } + kmem_map[idx].mapped = 0; + update_aliasmap(kmem_map[idx].dst, kmem_map[idx].len, NULL); + return kmem_map[idx].dst; +} + +static int kmem_unmap_mapping(int cap, dosaddr_t addr, int mapsize) { int i, cnt = 0; while ((i = map_find(kmem_map, kmem_mappings, addr, mapsize, 1)) != -1) { + kmem_unmap_single(cap, i); cnt++; } return cnt; @@ -217,6 +228,7 @@ static void kmem_map_single(int cap, int idx, dosaddr_t targ) MREMAP_MAYMOVE | MREMAP_FIXED, MEM_BASE32(targ)); } kmem_map[idx].dst = targ; + kmem_map[idx].mapped = 1; update_aliasmap(targ, kmem_map[idx].len, kmem_map[idx].bkp_base); } #endif @@ -233,37 +245,65 @@ static int is_kvm_map(int cap) return (!(cap & MAPPING_DPMI)); } -void *alias_mapping_ux(int cap, size_t mapsize, int protect, void *source) +void *alias_mapping_high(int cap, size_t mapsize, int protect, void *source) { void *target = (void *)-1; - return mappingdriver->alias(cap, target, mapsize, protect, source); + +#ifdef __x86_64__ + /* use MAP_32BIT also for MAPPING_INIT_LOWRAM until simx86 is 64bit-safe */ + if (cap & (MAPPING_DPMI|MAPPING_VGAEMU|MAPPING_INIT_LOWRAM)) { + target = mmap(NULL, mapsize, protect, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0); + if (target == MAP_FAILED) { + error("mmap MAP_32BIT failed, %s\n", strerror(errno)); + return MAP_FAILED; + } + } +#endif + + target = mappingdriver->alias(cap, target, mapsize, protect, source); + if (target == MAP_FAILED) + return target; + if (is_kvm_map(cap)) + mmap_kvm(cap, target, mapsize, protect); + return target; } int alias_mapping(int cap, dosaddr_t targ, size_t mapsize, int protect, void *source) { + void *target, *addr; int i; +#ifdef __linux__ + int ku; +#endif assert(targ != (dosaddr_t)-1); Q__printf("MAPPING: alias, cap=%s, targ=%#x, size=%zx, protect=%x, source=%p\n", cap, targ, mapsize, protect, source); + /* for non-zero INIT_LOWRAM the target is a hint */ #ifdef __linux__ - assert(kmem_mapped(targ, mapsize) == 0); + ku = kmem_unmap_mapping(cap, targ, mapsize); + if (ku) + dosemu_error("Found %i kmem mappings at %#x\n", ku, targ); #endif - + if (cap & MAPPING_INIT_LOWRAM) { + mem_bases[MEM_BASE] = mem_base; +#ifdef __i386__ + if (config.cpu_vm == CPUVM_VM86) + mem_bases[VM86_BASE] = 0; +#endif + } for (i = 0; i < MAX_BASES; i++) { - void *target, *addr; - int prot; target = MEM_BASE32x(targ, i); if (target == MAP_FAILED) continue; - /* protections on KVM_BASE go via page tables in the VM, not mprotect */ - prot = i == KVM_BASE ? (PROT_READ|PROT_WRITE|PROT_EXEC) : protect; - addr = mappingdriver->alias(cap, target, mapsize, prot, source); + addr = mappingdriver->alias(cap, target, mapsize, protect, source); if (addr == MAP_FAILED) return -1; Q__printf("MAPPING: %s alias created at %p\n", cap, addr); } - update_aliasmap(targ, mapsize, source); + if (targ != (dosaddr_t)-1) + update_aliasmap(targ, mapsize, source); if (is_kvm_map(cap)) mprotect_kvm(cap, targ, mapsize, protect); @@ -292,10 +332,11 @@ static void *mmap_mapping_kmem(int cap, dosaddr_t targ, size_t mapsize, } if (targ == (dosaddr_t)-1) { - target = smalloc_aligned_topdown(&main_pool, NULL, PAGE_SIZE, mapsize); - if (!target) { - error("OOM for mmap_mapping_kmem, %s\n", strerror(errno)); - return MAP_FAILED; + target = mmap(NULL, mapsize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0); + if (target == MAP_FAILED) { + error("mmap MAP_32BIT failed, %s\n", strerror(errno)); + return target; } targ = DOSADDR_REL(target); } else { @@ -305,125 +346,194 @@ static void *mmap_mapping_kmem(int cap, dosaddr_t targ, size_t mapsize, return target; } + +static void munmap_mapping_kmem(int cap, dosaddr_t addr, size_t mapsize) +{ + int i, rc = 0; + + Q__printf("MAPPING: unmap kmem, cap=%s, target=%x, size=%zx\n", + cap, addr, mapsize); + + while ((i = map_find(kmem_map, kmem_mappings, addr, mapsize, 1)) != -1) { + dosaddr_t old_vbase = kmem_unmap_single(cap, i); + if (!(cap & MAPPING_SCRATCH)) + continue; + if (old_vbase < LOWMEM_SIZE) { + rc = alias_mapping(MAPPING_LOWMEM, old_vbase, mapsize, + PROT_READ | PROT_WRITE, LOWMEM(old_vbase)); + } else { + unsigned char *p; + p = mmap_mapping_ux(MAPPING_SCRATCH, MEM_BASE32(old_vbase), mapsize, + PROT_READ | PROT_WRITE); + if (p == MAP_FAILED) + rc = -1; + } + if (rc == -1) { + error("failure unmapping kmem region\n"); + continue; + } + } +} #endif static int mapping_is_hole(void *start, size_t size) { - uintptr_t beg = (uintptr_t)start; - uintptr_t end = beg + size; + unsigned beg = (uintptr_t)start; + unsigned end = beg + size; return (mapping_find_hole(beg, end, size) == start); } -// KVM api documentation recommends that the lower 21 bits of guest_phys_addr and -// userspace_addr be identical, so align to a huge page boundary (2MB). -// This also helps debugging, since subtracting hex numbers is much easier that way -// for a human being. -void *mmap_mapping_huge_page_aligned(int cap, size_t mapsize, int protect) -{ - size_t edge; - int flags = (cap & MAPPING_INIT_LOWRAM) ? _MAP_32BIT : 0; - unsigned char *addr = mmap(NULL, mapsize + HUGE_PAGE_SIZE, protect, - MAP_PRIVATE | flags | MAP_ANONYMOUS, -1, 0); - if (addr == MAP_FAILED) - return addr; - - /* align up to next 2MB */ - edge = (unsigned char *)HUGE_PAGE_ALIGN((uintptr_t)addr + PAGE_SIZE) - addr; - - /* trim front */ - if (edge > PAGE_SIZE) - munmap(addr, edge - PAGE_SIZE); - - /* create guard page to trap bad things */ - mprotect(&addr[edge - PAGE_SIZE], PAGE_SIZE, PROT_NONE); - - addr += edge; - - /* trim back */ - edge = HUGE_PAGE_SIZE - edge; - if (edge > 0) - munmap(&addr[mapsize], edge); - - if (cap & MAPPING_INIT_LOWRAM) { - mem_bases[MEM_BASE].base = addr; - mem_bases[MEM_BASE].size = mapsize; - if (is_kvm_map(cap)) { - cap = MAPPING_LOWMEM; - mapsize = LOWMEM_SIZE + HMASIZE; - protect = PROT_READ|PROT_WRITE|PROT_EXEC; - void *kvm_base = mmap_mapping_huge_page_aligned(cap, mapsize, protect); - if (kvm_base == MAP_FAILED) - return kvm_base; - mem_bases[KVM_BASE].base = kvm_base; - mem_bases[KVM_BASE].size = mapsize; - } -#ifdef __i386__ - if (config.cpu_vm == CPUVM_VM86) { - mem_bases[VM86_BASE].base = 0; - mem_bases[VM86_BASE].size = ALIAS_SIZE; - } -#endif - } - - return addr; -} - -void *mmap_mapping(int cap, void *target, size_t mapsize, int protect) +static void *do_mmap_mapping(int cap, void *target, size_t mapsize, int protect) { void *addr; - int flags; + int flags = (target != (void *)-1) ? MAP_FIXED : 0; - assert(target != (void *)-1); - - /* not removing MAP_FIXED when mapping to 0 */ - if ((cap & MAPPING_NULL) && !mapping_is_hole(target, mapsize)) - return MAP_FAILED; - - flags = (cap & MAPPING_NOOVERLAP) ? + if (cap & MAPPING_NOOVERLAP) { + if (target == (void *)-1) { + dosemu_error("spurious MAPPING_NOOVERLAP flag\n"); + cap &= ~MAPPING_NOOVERLAP; + } else if (target != NULL) { + flags &= ~MAP_FIXED; #ifdef MAP_FIXED_NOREPLACE - MAP_FIXED_NOREPLACE -#else - 0 + flags |= MAP_FIXED_NOREPLACE; +#endif + } + /* not removing MAP_FIXED when mapping to 0 */ + else if (!mapping_is_hole(target, mapsize)) + return MAP_FAILED; + } + if (target == (void *)-1) target = NULL; +#ifdef __x86_64__ + if (flags == 0 && + (cap & (MAPPING_DPMI|MAPPING_VGAEMU|MAPPING_INIT_LOWRAM|MAPPING_KVM))) + flags = MAP_32BIT; #endif - : MAP_FIXED; - addr = mmap(target, mapsize, protect, - MAP_PRIVATE | flags | MAP_ANONYMOUS, -1, 0); - - if (addr != MAP_FAILED && addr != target) { + MAP_PRIVATE | flags | MAP_ANONYMOUS, -1, 0); + if (addr == MAP_FAILED) + return addr; + if (cap & MAPPING_NOOVERLAP) { #ifdef MAP_FIXED_NOREPLACE #ifdef __linux__ /* under valgrind this flag doesn't work */ - if (kernel_version_code >= KERNEL_VERSION(4, 17, 0)) - error_once0("MAP_FIXED_NOREPLACE doesn't work\n"); + if (kernel_version_code >= KERNEL_VERSION(4, 17, 0) && addr != target) + error("MAP_FIXED_NOREPLACE doesn't work\n"); #endif #endif - munmap(addr, mapsize); - return MAP_FAILED; + if (addr != target) { + munmap(addr, mapsize); + return MAP_FAILED; + } } + if (is_kvm_map(cap)) + /* Map guest memory in KVM */ + mmap_kvm(cap, addr, mapsize, protect); + return addr; } -/* Restore mapping previously broken by direct mmap() call. */ -int restore_mapping(int cap, dosaddr_t targ, size_t mapsize) +void *mmap_mapping_ux(int cap, void *target, size_t mapsize, int protect) +{ + return do_mmap_mapping(cap, target, mapsize, protect); +} + +void *mmap_file_ux(int cap, void *target, size_t mapsize, int protect, + int flags, int fd) +{ + void *addr = mmap(target, mapsize, protect, flags, fd, 0); + if (addr == MAP_FAILED) + return MAP_FAILED; + if (is_kvm_map(cap)) + /* Map guest memory in KVM */ + mmap_kvm(cap, addr, mapsize, protect); + return addr; +} + +void *mmap_mapping(int cap, dosaddr_t targ, size_t mapsize, int protect) { void *addr; - void *target; - assert((cap & MAPPING_DPMI) && (targ != (dosaddr_t)-1)); - target = MEM_BASE32(targ); - addr = mmap_mapping(cap, target, mapsize, PROT_READ | PROT_WRITE); + void *target = ((targ == (dosaddr_t)-1) ? (void *)-1 : MEM_BASE32(targ)); + + Q__printf("MAPPING: map, cap=%s, target=%p, size=%zx, protect=%x\n", + cap, target, mapsize, protect); + if (!(cap & MAPPING_INIT_LOWRAM) && targ != (dosaddr_t)-1) { +#ifdef __linux__ + int ku; +#endif + /* for lowram we use alias_mapping() instead */ + assert(targ >= LOWMEM_SIZE); +#ifdef __linux__ + ku = kmem_unmap_mapping(cap, targ, mapsize); + if (ku) + dosemu_error("Found %i kmem mappings at %#x\n", ku, targ); +#endif + } + + addr = do_mmap_mapping(cap, target, mapsize, protect); + if (addr == MAP_FAILED) + return MAP_FAILED; + if (targ != (dosaddr_t)-1) + update_aliasmap(targ, mapsize, addr); + Q__printf("MAPPING: map success, cap=%s, addr=%p\n", cap, addr); + return addr; +} + +static void *do_mremap_grow(int cap, dosaddr_t from, size_t old_size, + size_t new_size) +{ +#ifdef __linux__ + void *old_ptr = MEM_BASE32(from); + void *ptr = mremap(old_ptr, old_size, new_size, MREMAP_MAYMOVE); + Q__printf("MAPPING: remap(grow), cap=%s, from=%x, old=%zx, new=%zx, %p\n", + cap, from, old_size, new_size, ptr); + if (ptr == MAP_FAILED) + return MAP_FAILED; + if (is_kvm_map(cap)) { + munmap_kvm(cap | MAPPING_IMMEDIATE, from, old_size); + mmap_kvm(cap | MAPPING_IMMEDIATE, ptr, new_size, + PROT_READ | PROT_WRITE | PROT_EXEC); + } + return ptr; +#else + return MAP_FAILED; +#endif +} + +void *mremap_mapping(int cap, dosaddr_t from, size_t old_size, size_t new_size) +{ + dosaddr_t unm; + assert(new_size != old_size && !(from & (PAGE_SIZE - 1)) && + !(old_size & (PAGE_SIZE - 1)) && !(new_size & (PAGE_SIZE - 1))); + if (new_size > old_size) + return do_mremap_grow(cap, from, old_size, new_size); + /* shrink is simple */ + Q__printf("MAPPING: remap(shrink), cap=%s, from=%x, old=%zx, new=%zx\n", + cap, from, old_size, new_size); + unm = from + new_size; + munmap(MEM_BASE32(unm), old_size - new_size); if (is_kvm_map(cap)) - mprotect_kvm(cap, targ, mapsize, PROT_READ | PROT_WRITE); - return (addr == target ? 0 : -1); + munmap_kvm(cap | MAPPING_IMMEDIATE, unm, old_size - new_size); + return MEM_BASE32(from); } int mprotect_mapping(int cap, dosaddr_t targ, size_t mapsize, int protect) { int i, ret = -1; + /* it is important to r/o protect the KVM guest page tables BEFORE + calling mprotect as this function is called by parallel threads + (vgaemu.c:_vga_emu_update). + Otherwise the page can be r/w in the guest but r/o on the host which + causes KVM to exit with EFAULT when the guest writes there. + We do not need to worry about caching/TLBs because the kernel will + walk the guest page tables (see kernel: + Documentation/virtual/kvm/mmu.txt: + - if needed, walk the guest page tables to determine the guest translation + (gva->gpa or ngpa->gpa) + - if permissions are insufficient, reflect the fault back to the guest) + */ Q__printf("MAPPING: mprotect, cap=%s, targ=%x, size=%zx, protect=%x\n", cap, targ, mapsize, protect); - invalidate_unprotected_page_cache(targ, mapsize); if (is_kvm_map(cap)) mprotect_kvm(cap, targ, mapsize, protect); if (!(cap & MAPPING_LOWMEM)) { @@ -434,10 +544,8 @@ int mprotect_mapping(int cap, dosaddr_t targ, size_t mapsize, int protect) } for (i = 0; i < MAX_BASES; i++) { void *addr = MEM_BASE32x(targ, i); - /* protections on KVM_BASE go via page tables in the VM, not mprotect */ - if (addr == MAP_FAILED || i == KVM_BASE) + if (addr == MAP_FAILED) continue; - assert(i == MEM_BASE || targ + mapsize <= ALIAS_SIZE); Q__printf("MAPPING: mprotect, cap=%s, addr=%p, size=%zx, protect=%x\n", cap, addr, mapsize, protect); ret = mprotect(addr, mapsize, protect); @@ -477,7 +585,6 @@ void mapping_init(void) leavedos(2); return; } - mappingdriver = mappingdrv[i]; } else { for (i = 0; i < numdrivers; i++) { if (mappingdrv[i] && (*mappingdrv[i]->open)(MAPPING_PROBE)) { @@ -493,10 +600,8 @@ void mapping_init(void) } } - for (i = 0; i < MAX_BASES; i++) { - mem_bases[i].base = MAP_FAILED; - mem_bases[i].size = 0; - } + for (i = 0; i < MAX_BASES; i++) + mem_bases[i] = MAP_FAILED; } /* this gets called on DOSEMU termination cleanup all mapping stuff */ @@ -524,6 +629,7 @@ char *decode_mapping_cap(int cap) if (cap & MAPPING_HGC) p += sprintf(p, " HGC"); if (cap & MAPPING_HMA) p += sprintf(p, " HMA"); if (cap & MAPPING_SHARED) p += sprintf(p, " SHARED"); + if (cap & MAPPING_IMMEDIATE) p += sprintf(p, " IMMEDIATE"); if (cap & MAPPING_INIT_HWRAM) p += sprintf(p, " INIT_HWRAM"); if (cap & MAPPING_INIT_LOWRAM) p += sprintf(p, " INIT_LOWRAM"); if (cap & MAPPING_EXTMEM) p += sprintf(p, " EXTMEM"); @@ -566,7 +672,7 @@ static void *alloc_mapping_kmem(int cap, size_t mapsize, off_t source) if (cap & MAPPING_LOWMEM) { int i; for (i = 0; i < MAX_BASES; i++) { - addr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, + addr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_32BIT, mem_fd, source); if (addr == MAP_FAILED) { close_kmem(); @@ -575,7 +681,7 @@ static void *alloc_mapping_kmem(int cap, size_t mapsize, off_t source) kmem_map[kmem_mappings].base[i] = addr; } } else { - addr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, + addr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_32BIT, mem_fd, source); if (addr == MAP_FAILED) { close_kmem(); @@ -583,7 +689,7 @@ static void *alloc_mapping_kmem(int cap, size_t mapsize, off_t source) } kmem_map[kmem_mappings].base[MEM_BASE] = addr; } - addr2 = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, + addr2 = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_32BIT, mem_fd, source); close_kmem(); if (addr2 == MAP_FAILED) @@ -593,20 +699,19 @@ static void *alloc_mapping_kmem(int cap, size_t mapsize, off_t source) kmem_map[kmem_mappings].bkp_base = addr2; kmem_map[kmem_mappings].dst = -1; kmem_map[kmem_mappings].len = mapsize; + kmem_map[kmem_mappings].mapped = 0; kmem_mappings++; - Q_printf("MAPPING: region allocated at %p\n", addr2); - return addr2; + Q_printf("MAPPING: region allocated at %p\n", addr); + return addr; } #endif -static void *do_alloc_mapping(int cap, size_t mapsize, void *addr) +void *alloc_mapping(int cap, size_t mapsize) { - addr = mappingdriver->alloc(cap, mapsize, addr); - if (addr == MAP_FAILED) { - error("failed to alloc %zx\n", mapsize); - leavedos(2); - return NULL; - } + void *addr; + + Q__printf("MAPPING: alloc, cap=%s size=%#zx\n", cap, mapsize); + addr = mappingdriver->alloc(cap, mapsize); mprotect(addr, mapsize, PROT_READ | PROT_WRITE); if (cap & MAPPING_INIT_LOWRAM) { @@ -617,20 +722,6 @@ static void *do_alloc_mapping(int cap, size_t mapsize, void *addr) return addr; } -void *alloc_mapping(int cap, size_t mapsize) -{ - Q__printf("MAPPING: alloc, cap=%s size=%#zx\n", cap, mapsize); - return do_alloc_mapping(cap, mapsize, (void *)-1); -} - -void *alloc_mapping_huge_page_aligned(int cap, size_t mapsize) -{ - void *addr; - Q__printf("MAPPING: alloc_huge_page_aligned, cap=%s size=%#zx\n", cap, mapsize); - addr = mmap_mapping_huge_page_aligned(cap, mapsize, PROT_NONE); - return addr == MAP_FAILED ? MAP_FAILED : do_alloc_mapping(cap, mapsize, addr); -} - void free_mapping(int cap, void *addr, size_t mapsize) { if (cap & MAPPING_KMEM) { @@ -650,24 +741,22 @@ void *realloc_mapping(int cap, void *addr, size_t oldsize, size_t newsize) } if (!oldsize) dosemu_error("realloc_mapping() addr=%p, oldsize=0\n", addr); - - return mappingdriver->resize(cap, addr, oldsize, newsize); + return mappingdriver->realloc(cap, addr, oldsize, newsize); } -static void populate_aliasmap(unsigned char **map, unsigned char *addr, - int size) +int munmap_mapping(int cap, dosaddr_t targ, size_t mapsize) { - int i; - - for (i = 0; i < size >> PAGE_SHIFT; i++) - map[i] = addr ? addr + (i << PAGE_SHIFT) : NULL; -} - -static unsigned char **alloc_aliasmap(unsigned char *addr, int size) -{ - unsigned char **ret = malloc((size >> PAGE_SHIFT) * sizeof(*ret)); - populate_aliasmap(ret, addr, size); - return ret; +#ifdef __linux__ + int ku; + /* First of all remap the kmem mappings */ + ku = kmem_unmap_mapping(cap, targ, mapsize); + if (ku) + dosemu_error("Found %i kmem mappings at %#x\n", ku, targ); +#endif + munmap(MEM_BASE32(targ), mapsize); + if (is_kvm_map(cap)) + munmap_kvm(cap, targ, mapsize); + return 0; } struct hardware_ram { @@ -676,7 +765,6 @@ struct hardware_ram { dosaddr_t vbase; size_t size; int type; - unsigned char **aliasmap; struct hardware_ram *next; }; @@ -689,8 +777,6 @@ static int do_map_hwram(struct hardware_ram *hw) int cap = MAPPING_KMEM; if (hw->default_vbase != (dosaddr_t)-1) cap |= MAPPING_LOWMEM; - else if (!config.dpmi) - return 0; p = mmap_mapping_kmem(cap, hw->default_vbase, hw->size, hw->base); if (p == MAP_FAILED) { error("mmap error in map_hardware_ram %s\n", strerror (errno)); @@ -718,33 +804,74 @@ void init_hardware_ram(void) struct hardware_ram *hw; for (hw = hardware_ram; hw != NULL; hw = hw->next) { -#ifdef __linux__ - unsigned char *uaddr; int cap = MAPPING_KMEM; -#endif - if (hw->vbase != (dosaddr_t)-1) /* virtual hardware ram mapped later */ - continue; -#ifdef __linux__ if (hw->default_vbase != (dosaddr_t)-1) cap |= MAPPING_LOWMEM; - uaddr = alloc_mapping_kmem(cap, hw->size, hw->base); - if (uaddr == MAP_FAILED) { - error("failed to map KMEM at %lx, size %zx: %s\n", hw->base, hw->size, - strerror(errno)); + if (hw->type == 'e') /* virtual hardware ram mapped later */ continue; - } - populate_aliasmap(hw->aliasmap, uaddr, hw->size); +#ifdef __linux__ + alloc_mapping_kmem(cap, hw->size, hw->base); #endif if (do_map_hwram(hw) == -1) return; } } -static int do_register_hwram(int type, unsigned base, unsigned size, - void *uaddr, dosaddr_t va) +int map_hardware_ram(char type) { struct hardware_ram *hw; + for (hw = hardware_ram; hw != NULL; hw = hw->next) { + if (hw->type != type || hw->vbase != -1) + continue; + if (do_map_hwram(hw) == -1) + return -1; + } + return 0; +} + +int map_hardware_ram_manual(size_t base, dosaddr_t vbase) +{ + struct hardware_ram *hw; + + for (hw = hardware_ram; hw != NULL; hw = hw->next) { + if (hw->base != base) + continue; + hw->vbase = vbase; + return 0; + } + return -1; +} + +int unmap_hardware_ram(char type) +{ + struct hardware_ram *hw; + int rc = 0; + + for (hw = hardware_ram; hw != NULL; hw = hw->next) { + int cap = MAPPING_KMEM; + if (hw->type != type || hw->vbase == -1) + continue; + if (hw->default_vbase != (dosaddr_t)-1) + cap |= MAPPING_LOWMEM; +#ifdef __linux__ + munmap_mapping_kmem(cap, hw->vbase, hw->size); +#endif + g_printf("unmapped hardware ram at 0x%08zx .. 0x%08zx at %#x\n", + hw->base, hw->base+hw->size-1, hw->vbase); + hw->vbase = -1; + } + return rc; +} + +int register_hardware_ram(int type, unsigned int base, unsigned int size) +{ + struct hardware_ram *hw; + + if (!can_do_root_stuff && type != 'e') { + dosemu_error("can't use hardware ram in low feature (non-suid root) DOSEMU\n"); + return 0; + } c_printf("Registering HWRAM, type=%c base=%#x size=%#x\n", type, base, size); hw = malloc(sizeof(*hw)); hw->base = base; @@ -752,138 +879,29 @@ static int do_register_hwram(int type, unsigned base, unsigned size, hw->default_vbase = hw->base; else hw->default_vbase = -1; - hw->vbase = va; + hw->vbase = -1; hw->size = size; hw->type = type; - if (base + size > ALIAS_SIZE) - hw->aliasmap = alloc_aliasmap(uaddr, size); - else { - /* for kmem, uaddr determined later. for !kmem alias on lowmem_base */ - assert(!uaddr); - hw->aliasmap = &lowmem_aliasmap[base >> PAGE_SHIFT]; - } hw->next = hardware_ram; hardware_ram = hw; - if (!uaddr && (base >= LOWMEM_SIZE || type == 'h')) + if (base >= LOWMEM_SIZE || type == 'h') memcheck_reserve(type, base, size); return 1; } -int register_hardware_ram(int type, unsigned base, unsigned int size) -{ - if (!can_do_root_stuff) { - dosemu_error("can't use hardware ram in low feature (non-suid root) DOSEMU\n"); - return 0; - } - return do_register_hwram(type, base, size, NULL, -1); -} - -void register_hardware_ram_virtual2(int type, unsigned base, unsigned int size, - void *uaddr, dosaddr_t va) -{ - void *uaddr2 = base < ALIAS_SIZE ? NULL : MEM_BASE32(va); - do_register_hwram(type, base, size, uaddr2, va); - if (config.cpu_vm_dpmi == CPUVM_KVM || - (config.cpu_vm == CPUVM_KVM && base + size <= LOWMEM_SIZE + HMASIZE)) { - int prot = PROT_READ | PROT_WRITE | PROT_EXEC; - int cap = MAPPING_INIT_LOWRAM; - if (type == 'L') - cap |= MAPPING_LOWMEM; - mmap_kvm(cap, base, size, uaddr, va, prot); - } -} - -void register_hardware_ram_virtual(int type, unsigned base, unsigned int size, - dosaddr_t va) -{ - void *uaddr = base < mem_bases[KVM_BASE].size ? - MEM_BASE32x(base, KVM_BASE) : MEM_BASE32(va); - register_hardware_ram_virtual2(type, base, size, uaddr, va); -} - -int unregister_hardware_ram_virtual(dosaddr_t base) -{ - struct hardware_ram *hw, *phw; - - for (phw = NULL, hw = hardware_ram; hw != NULL; phw = hw, hw = hw->next) { - if (hw->base == base) { - if (phw) - phw->next = hw->next; - else - hardware_ram = hw->next; - if (hw->base + hw->size > ALIAS_SIZE) - free(hw->aliasmap); - free(hw); - return 0; - } - } - return -1; -} - /* given physical address addr, gives the corresponding vbase or -1 */ -static dosaddr_t do_get_hardware_ram(unsigned addr, uint32_t size, - struct hardware_ram **r_hw) +unsigned get_hardware_ram(unsigned addr, uint32_t size) { struct hardware_ram *hw; for (hw = hardware_ram; hw != NULL; hw = hw->next) { if (hw->vbase != -1 && - hw->base <= addr && addr + size <= hw->base + hw->size) { - if (r_hw) - *r_hw = hw; + hw->base <= addr && addr + size <= hw->base + hw->size) return hw->vbase + addr - hw->base; - } } return -1; } -static unsigned do_find_hardware_ram(dosaddr_t va, uint32_t size, - struct hardware_ram **r_hw) -{ - struct hardware_ram *hw; - - for (hw = hardware_ram; hw != NULL; hw = hw->next) { - if (hw->vbase == -1) - continue; - if (hw->vbase <= va && va + size <= hw->vbase + hw->size) { - if (r_hw) - *r_hw = hw; - return hw->base + va - hw->vbase; - } - } - return -1; -} - -dosaddr_t get_hardware_ram(unsigned addr, uint32_t size) -{ - return do_get_hardware_ram(addr, size, NULL); -} - -static void hwram_update_aliasmap(struct hardware_ram *hw, unsigned addr, - int size, unsigned char *src) -{ - int off = addr - hw->base; - assert(!(off & (PAGE_SIZE - 1))); // page-aligned - assert(!(size & (PAGE_SIZE - 1))); // page-aligned - // lowmem needs permanent aliasing - assert(!(src == NULL && (hw->base + hw->size <= ALIAS_SIZE))); - populate_aliasmap(&hw->aliasmap[off >> PAGE_SHIFT], src, size); -} - -void *get_hardware_uaddr(unsigned addr) -{ - struct hardware_ram *hw; - - for (hw = hardware_ram; hw != NULL; hw = hw->next) { - if (hw->vbase != -1 && - hw->base <= addr && addr < hw->base + hw->size) { - int off = addr - hw->base; - return hw->aliasmap[off >> PAGE_SHIFT] + (off & (PAGE_SIZE - 1)); - } - } - return MAP_FAILED; -} - void list_hardware_ram(void (*print)(const char *, ...)) { struct hardware_ram *hw; @@ -979,61 +997,3 @@ void *mapping_find_hole(unsigned long start, unsigned long stop, return MAP_FAILED; return (void *)pend; } - -int mcommit(void *ptr, size_t size) -{ - int err; - dosaddr_t targ = DOSADDR_REL(ptr); - int cap = MAPPING_INIT_LOWRAM; - err = mprotect_mapping(cap, targ, size, PROT_READ | PROT_WRITE); - if (err == -1) - return 0; -#if HAVE_DECL_MADV_POPULATE_WRITE - err = madvise(ptr, size, MADV_POPULATE_WRITE); - if (err) - perror("madvise()"); -#endif - return 1; -} - -int muncommit(void *ptr, size_t size) -{ - dosaddr_t targ = DOSADDR_REL(ptr); - int cap = MAPPING_INIT_LOWRAM; - if (mprotect_mapping(cap, targ, size, PROT_NONE) == -1) - return 0; - return 1; -} - -int alias_mapping_pa(int cap, unsigned addr, size_t mapsize, int protect, - void *source) -{ - void *addr2; - struct hardware_ram *hw; - dosaddr_t va = do_get_hardware_ram(addr, mapsize, &hw); - if (va == (dosaddr_t)-1) - return 0; - assert(addr >= LOWMEM_SIZE + HMASIZE); - addr2 = mappingdriver->alias(cap, MEM_BASE32(va), mapsize, protect, source); - if (addr2 == MAP_FAILED) - return 0; - assert(addr2 == MEM_BASE32(va)); - hwram_update_aliasmap(hw, addr, mapsize, source); - invalidate_unprotected_page_cache(va, mapsize); - if (is_kvm_map(cap)) - mprotect_kvm(cap, va, mapsize, protect); - return 1; -} - -int unalias_mapping_pa(int cap, unsigned addr, size_t mapsize) -{ - struct hardware_ram *hw; - dosaddr_t va = do_get_hardware_ram(addr, mapsize, &hw); - if (va == (dosaddr_t)-1) - return 0; - assert(addr >= LOWMEM_SIZE + HMASIZE); - restore_mapping(cap, va, mapsize); - hwram_update_aliasmap(hw, addr, mapsize, NULL); - invalidate_unprotected_page_cache(va, mapsize); - return 1; -} diff --git a/src/arch/linux/mapping/mapshm.c b/src/arch/linux/mapping/mapshm.c new file mode 100644 index 0000000..45e887f --- /dev/null +++ b/src/arch/linux/mapping/mapshm.c @@ -0,0 +1,184 @@ +/* + * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". + * + * for details see file COPYING in the DOSEMU distribution + */ + +/* + * Purpose: memory mapping library, anon-SHM backend. + * + * Authors: Stas Sergeev, Bart Oldeman. + * + */ + +#ifdef __linux__ +#include "emu.h" +#include +#include +#include + +#include "dosemu_config.h" +#include "mapping.h" + +/* ------------------------------------------------------------ */ + +#define Q__printf(f,cap,a...) ({\ + Q_printf(f,decode_mapping_cap(cap),##a); \ +}) + +static void *alias_mapping_shm(int cap, void *target, size_t mapsize, int protect, void *source) +{ + int flags = MREMAP_MAYMOVE; + /* The trick is to set old_len = 0, + * this won't unmap at the old address, but with + * shared mem the 'nopage' vm_op will map in the right + * pages. We need however to take care not to map + * past the end of the shm area + */ + if (target != (void *)-1) + flags |= MREMAP_FIXED; + else + target = NULL; + target = mremap(source, 0, mapsize, flags, target); + if (target == MAP_FAILED) return MAP_FAILED; + + mprotect(target, mapsize, protect); + return target; +} + +static int open_mapping_shm(int cap) +{ + static int first =1; + + if (cap) Q_printf("MAPPING: open, cap=%s\n", + decode_mapping_cap(cap)); + + if (first) { + void *ptr1, *ptr2 = MAP_FAILED; + first = 0; + + /* do a test alias mapping. kernel 2.6.1 doesn't support our mremap trick */ + ptr1 = mmap(0, PAGE_SIZE, PROT_NONE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (ptr1 != MAP_FAILED) { + ptr2 = mremap(ptr1, 0, PAGE_SIZE, MREMAP_MAYMOVE); + munmap(ptr1, PAGE_SIZE); + if (ptr2 != MAP_FAILED) + munmap(ptr2, PAGE_SIZE); + } + if (ptr2 == MAP_FAILED) { + Q_printf("MAPPING: not using mapshm because alias mapping does not work\n"); + if (!cap)return 0; + leavedos(2); + } + } + + /* + * Now handle individual cases. + * Don't forget that each of the below code pieces should only + * be executed once ! + */ + +#if 0 + if (cap & MAPPING_OTHER) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_EMS) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_DPMI) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_VIDEO) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_VGAEMU) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_HGC) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_HMA) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_SHARED) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_INIT_HWRAM) { + /* none for now */ + } +#endif +#if 0 + if (cap & MAPPING_INIT_LOWRAM) { + /* none for now */ + } +#endif + + return 1; +} + +static void close_mapping_shm(int cap) +{ + Q_printf("MAPPING: close, cap=%s\n", decode_mapping_cap(cap)); +} + +static void *alloc_mapping_shm(int cap, size_t mapsize) +{ + Q__printf("MAPPING: alloc, cap=%s, mapsize=%zx\n", cap, mapsize); + return mmap(0, mapsize, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); +} + +static void free_mapping_shm(int cap, void *addr, size_t mapsize) +/* NOTE: addr needs to be the same as what was supplied by alloc_mapping_shm */ +{ + Q__printf("MAPPING: free, cap=%s, addr=%p, mapsize=%zx\n", + cap, addr, mapsize); + munmap(addr, mapsize); +} + +static void *realloc_mapping_shm(int cap, void *addr, size_t oldsize, size_t newsize) +{ + void *ret; + Q__printf("MAPPING: realloc, cap=%s, addr=%p, oldsize=%zx, newsize=%zx\n", + cap, addr, oldsize, newsize); + + if (newsize <= oldsize) + return mremap(addr, oldsize, newsize, MREMAP_MAYMOVE); + + /* we can't expand shared anonymous memory using mremap + so we must allocate a new region and memcpy to it */ + ret = alloc_mapping_shm(cap, newsize); + if (ret != MAP_FAILED) { + memcpy(ret, addr, oldsize); + free_mapping_shm(cap, addr, oldsize); + } + return ret; +} + +struct mappingdrivers mappingdriver_ashm = { + "mapashm", + "anonymous non-expandable shared memory mapping", + open_mapping_shm, + close_mapping_shm, + alloc_mapping_shm, + free_mapping_shm, + realloc_mapping_shm, + alias_mapping_shm, +}; +#endif diff --git a/src/base/bios/int10.c b/src/base/bios/int10.c index b69cae6..f4ac31c 100644 --- a/src/base/bios/int10.c +++ b/src/base/bios/int10.c @@ -19,7 +19,7 @@ * changed int10() to make graphics work with X. * * 1998/04/05: Put some work into set_video_mode() (made it - * more VGA compatible) and removed new_set_video_mode(). + * more VGA comaptible) and removed new_set_video_mode(). * Removed (useless) global variable "gfx_mode". * -- sw (Steffen Winterfeldt ) * @@ -35,7 +35,7 @@ * cursor shape is now initialized during mode set. * -- sw * - * 2000/05/18: Split int10() into a X and non-X part. Reworked to X part so + * 2000/05/18: Splitted int10() into a X and non-X part. Reworked to X part so * that it supports fonts in gfx modes. * -- sw * @@ -88,7 +88,7 @@ unsigned screen_adr(int page) /* this maps the cursor shape given by int10, fn1 to the actually displayed cursor start&end values in cursor_shape. This seems - to be typical IBM Black Compatibility Magic. + to be typical IBM Black Compatiblity Magic. I modeled it approximately from the behaviour of my own VGA's BIOS. I'm not sure if it is correct for start=end and for font_heights @@ -113,34 +113,17 @@ static void crt_outw(unsigned index, unsigned value) port_outw(port, (index + 1) | ((value & 0xff) << 8)); } -static unsigned do_set_cursor_pos(unsigned page, int x, int y) +static void set_cursor_pos(unsigned page, int x, int y) { - unsigned co, old_y; + unsigned co; - old_y = get_bios_cursor_y_position(page); set_bios_cursor_x_position(page, x); set_bios_cursor_y_position(page, y); co = READ_WORD(BIOS_SCREEN_COLUMNS); crt_outw(0xe, READ_WORD(BIOS_VIDEO_MEMORY_ADDRESS)/2 + y * co + x); - return old_y; } -static void set_cursor_pos(unsigned page, int x, int y) -{ - unsigned old_y = do_set_cursor_pos(page, x, y); - - if (config.dumb_video && y > old_y) { - int i; - - if (no_local_video && !config.tty_stderr) - return; - for (i = 0; i < y - old_y; i++) - fputs("\r\n", config.tty_stderr ? stderr : stdout); - } -} - -static void set_cursor_shape(uint16_t shape) -{ +static inline void set_cursor_shape(ushort shape) { int cs,ce; cshape cursor_shape; cursor_shape.w = shape; @@ -183,8 +166,8 @@ bios_scroll(int x0, int y0, int x1, int y1, int l, int att) int dx = x1 - x0 + 1; int dy = y1 - y0 + 1; int x, y, co, li; - uint16_t blank = ' ' | (att << 8); - uint16_t tbuf[MAX_COLUMNS]; + us blank = ' ' | (att << 8); + us tbuf[MAX_COLUMNS]; unsigned sadr; if (config.dumb_video) @@ -260,6 +243,12 @@ static int using_mono_mode(void) return ((READ_BYTE(BIOS_VDU_CONTROL) & 0xc) == 0xc); } +/* Output a character to the screen. */ +void char_out(unsigned char ch, int page) +{ + tty_char_out(ch, page, -1); +} + /* * Output a character to the screen. * If attr != -1, set the attribute byte, too. @@ -278,7 +267,7 @@ void tty_char_out(unsigned char ch, int s, int attr) unsigned char buff[MB_LEN_MAX + 1]; int num, i; - if (no_local_video && !config.tty_stderr) + if (no_local_video) return; init_charset_state(&term_state, trconfig.output_charset); @@ -287,6 +276,7 @@ void tty_char_out(unsigned char ch, int s, int attr) return; for (i = 0; i < num; i++) fputc(buff[i], config.tty_stderr ? stderr : stdout); + return; } li= READ_BYTE(BIOS_ROWS_ON_SCREEN_MINUS_1) + 1; @@ -314,8 +304,8 @@ void tty_char_out(unsigned char ch, int s, int attr) case '\t': /* Tab */ i10_deb("char_out: tab\n"); do { - tty_char_out(' ', s, -1); - xpos = get_bios_cursor_x_position(s); + char_out(' ', s); + xpos = get_bios_cursor_x_position(s); } while (xpos % 8 != 0); break; @@ -330,8 +320,8 @@ void tty_char_out(unsigned char ch, int s, int attr) else { dst = screen_adr(s) + 2 * (ypos*co + xpos); - WRITE_BYTE(dst, ch); - if(attr != -1) WRITE_BYTE(dst + 1, attr); + vga_write(dst, ch); + if(attr != -1) vga_write(dst + 1, attr); } xpos++; } @@ -350,7 +340,7 @@ void tty_char_out(unsigned char ch, int s, int attr) vga_read(screen_adr(s) + 2*(ypos*co + xpos) + 1)); } } - do_set_cursor_pos(s, xpos, ypos); + set_cursor_pos(s, xpos, ypos); } /* The following clears the screen buffer. It does it only to the screen @@ -369,42 +359,45 @@ static void clear_screen(void) v_printf("INT10: cleared screen: screen_adr %x\n", screen_adr(0)); for (schar = screen_adr(0), lx = 0; lx < 16*1024; - WRITE_WORD(schar, blank), lx++, schar+=2); + vga_write_word(schar, blank), lx++, schar+=2); for (s = 0; s < 8; s++) - do_set_cursor_pos(s, 0, 0); + set_cursor_pos(s, 0, 0); } +#if 0 /* return number of vertical scanlines based on the bytes at 40:88 and 40:89 */ static int get_text_scanlines(void) { - int info = READ_BYTE(BIOS_VIDEO_INFO_2); + int info = READ_WORD(BIOS_VIDEO_INFO_1); v_printf("scanlines=%x\n", info); - if ((info & 0x80) && !(info & 0x10)) + if ((info & 1) == 0) return 200; - if (!(info & 0x80) && !(info & 0x10)) + if ((info & 0x1000) == 0) return 350; - if (!(info & 0x80)) + if ((info & 0x8000) == 0) return 400; return 480; } +#endif /* set number of vertical scanlines at the bytes at 40:88 and 40:89 */ static void set_text_scanlines(int lines) { - int info = READ_BYTE(BIOS_VIDEO_INFO_2) & ~0x90; + int info = READ_WORD(BIOS_VIDEO_INFO_1) & ~0x9001; if (lines == 200) - info |= 0x80; + info |= 0x8000; else { + info |= 1; if (lines == 400) - info |= 0x10; + info |= 0x1000; else if (lines == 480) - info |= 0x90; + info |= 0x9000; } v_printf("scanlines=%x %d\n", info, lines); - WRITE_BYTE(BIOS_VIDEO_INFO_2, info); + WRITE_WORD(BIOS_VIDEO_INFO_1, info); } static int adjust_font_size(int vga_font_height) @@ -464,7 +457,7 @@ static int adjust_font_size(int vga_font_height) * -- 1998/04/04 sw */ -bool set_video_mode(int mode) +boolean set_video_mode(int mode) { vga_mode_info *vmi; int clear_mem = 1; @@ -483,29 +476,6 @@ bool set_video_mode(int mode) i10_msg("set_video_mode: undefined video mode\n"); return 0; } - if (vmi->mode_class == TEXT) { - vga_mode_info *vmi2 = vmi; - vga_mode_info *vmi_best = vmi; - int ts = get_text_scanlines(); - int delta = ts - vmi2->height; - - i10_msg("look for mode with scan=%i font_height=%i\n", - ts, READ_BYTE(BIOS_FONT_HEIGHT)); - while ((vmi2 = vga_emu_find_mode(mode, vmi2))) { - if (vmi2->height > ts || - vmi2->char_height != READ_BYTE(BIOS_FONT_HEIGHT)) - continue; - if (delta < 0 || ts - vmi2->height < delta) { - i10_msg("better mode found: %ix%i %ix%i scan=%i\n", - vmi2->text_width, vmi2->text_height, - vmi2->char_width, vmi2->char_height, - vmi2->height); - vmi_best = vmi2; - delta = ts - vmi2->height; - } - vmi = vmi_best; - } - } if (vmi->mode_class == GRAPH && config.term) { error("Cannot set graphics mode under terminal!\n"); return 0; @@ -627,9 +597,11 @@ bool set_video_mode(int mode) page_size = vga.mem.bank_pages * 4096; WRITE_WORD(BIOS_VIDEO_MEMORY_USED, page_size); } + WRITE_WORD(BIOS_FONT_HEIGHT, vga_font_height); WRITE_BYTE(BIOS_ROWS_ON_SCREEN_MINUS_1, li - 1); WRITE_WORD(BIOS_SCREEN_COLUMNS, co); } + set_cursor_shape(vmi->type == TEXT_MONO ? 0x0b0d : 0x0607); switch(vga_font_height) { case 14: @@ -641,9 +613,6 @@ bool set_video_mode(int mode) default: u = vgaemu_bios.font_8; } - SETIVEC(0x43, 0xc000, u); - WRITE_WORD(BIOS_FONT_HEIGHT, vga_font_height); // before set_cursor_shape() - set_cursor_shape(vmi->type == TEXT_MONO ? 0x0b0d : 0x0607); if (using_text_mode()) { v_printf("INT10: X_set_video_mode: 8x%d ROM font -> bank 0\n", @@ -652,6 +621,9 @@ bool set_video_mode(int mode) i10_msg("activated font bank 0\n"); } + SETIVEC(0x43, 0xc000, u); + + set_text_scanlines(vmi->height); return 1; } @@ -754,7 +726,6 @@ static void vga_ROM_to_RAM(unsigned height, int bank) ofs = vgaemu_bios.font_16; } vga_RAM_to_RAM(height,0,256,seg,ofs,bank); - memcpy(vga.backup_font, vga.mem.base + 0x20000, 256 * 32); } /******************************************************************/ @@ -944,19 +915,7 @@ int int10(void) /* with dualmon */ "rep char: page %u, char 0x%02x '%c', attr 0x%02x\n", HI(bx), LO(ax), LO(ax) > ' ' && LO(ax) < 0x7f ? LO(ax) : ' ', LO(bx) ); - if (config.dumb_video) { - FILE *f = config.tty_stderr ? stderr : stdout; - int i; - - if (no_local_video && !config.tty_stderr) - break; - for (i = 0; i < LWORD(ecx); i++) - fputc(LO(ax), f); - /* cursor must not move when printing */ - fputc('\r', f); - } else { - vgaemu_repeat_char_attr(LO(ax), HI(bx), LO(bx), LWORD(ecx)); - } + vgaemu_repeat_char_attr(LO(ax), HI(bx), LO(bx), LWORD(ecx)); break; case 0x0a: /* write char */ @@ -1011,7 +970,7 @@ int int10(void) /* with dualmon */ "tty put char: page %u, char 0x%02x '%c'\n", HI(bx), LO(ax), LO(ax) > ' ' && LO(ax) < 0x7f ? LO(ax) : ' ' ); - tty_char_out(LO(ax), READ_BYTE(BIOS_CURRENT_SCREEN_PAGE), -1); + char_out(LO(ax), READ_BYTE(BIOS_CURRENT_SCREEN_PAGE)); } else { i10_deb( @@ -1033,7 +992,7 @@ int int10(void) /* with dualmon */ HI(ax) = co & 0xff; HI(bx) = READ_BYTE(BIOS_CURRENT_SCREEN_PAGE); i10_deb( - "get video mode: mode 0x%02x, page %u, %u columns\n", + "get video mode: mode 0x%02x, page %u, %u colums\n", LO(ax), HI(bx), HI(ax) ); break; @@ -1518,7 +1477,7 @@ int int10(void) /* with dualmon */ unsigned crtc, ind; /* select crtc base address */ - crtc = (port_inb(MISC_OUTPUT_R) & 1) ? 0x3d4 : 0x3b4; + crtc = (inb(MISC_OUTPUT_R) & 1) ? 0x3d4 : 0x3b4; buf[0x0] = port_inb(SEQUENCER_INDEX); buf[0x1] = port_inb(crtc); @@ -1596,7 +1555,7 @@ int int10(void) /* with dualmon */ for (ind = 0; ind < 25; ind++) port_outw(crtc, ind | (buf[0x0a+ind] << 8)); /* select crtc base address */ - port_outb(MISC_OUTPUT_W, (port_inb(MISC_OUTPUT_R) & ~0x01) | (crtc == 0x3d4)); + outb(MISC_OUTPUT_W, (inb(MISC_OUTPUT_R) & ~0x01) | (crtc == 0x3d4)); /* reset flipflop ! */ port_inb(crtc + 0x6); for (ind = 0; ind < 20; ind++) { diff --git a/src/base/bios/int16.c b/src/base/bios/int16.c index ed4fd88..729c1e3 100644 --- a/src/base/bios/int16.c +++ b/src/base/bios/int16.c @@ -122,7 +122,7 @@ static unsigned check_key_available(int extended) trigger_idle(); else reset_idle(0); - idle_enable2(500, 20, 2, "int16"); + idle_enable(500, 20, 2, "int16"); } else { reset_idle(1); } @@ -193,12 +193,7 @@ static void store_key_in_buffer(void) LO(ax) = (store_key(LWORD(ecx)) ? 0 : 1); } -static void get_kbd_features(void) -{ - _AX = 0x20; /* enh kbd functionality, nothing else */ -} - -int ___int16(void) +int int16(void) { switch(HI(ax)) { @@ -224,9 +219,6 @@ int ___int16(void) case 5: store_key_in_buffer(); break; - case 0x9: - get_kbd_features(); - break; case 0x10: int_yield(); read_key(EXTENDED); diff --git a/src/base/bios/pci_bios.c b/src/base/bios/pci_bios.c index 2253471..957de9e 100644 --- a/src/base/bios/pci_bios.c +++ b/src/base/bios/pci_bios.c @@ -259,17 +259,6 @@ pciRec *pcibios_find_class(unsigned long cls, int num) return NULL; } -pciRec *pcibios_find_primary_vga(void) -{ - int i = 0; - pciRec *ret; - - do { - ret = pcibios_find_class(PCI_CLASS_DISPLAY_VGA << 8, i++); - } while (ret && !ret->enabled); - return ret; -} - pciRec *pcibios_find_bdf(unsigned short bdf) { pciPtr pci = pciList; @@ -442,17 +431,15 @@ interpretCfgSpace(unsigned int *pciheader,unsigned int *pcibuses,int busidx, { static const char *typestr[] = { "MEM", "IO", "ROM" }; int tmp, i; - uint16_t command; pciPtr pciTmp = (pciPtr)malloc(sizeof(pciRec)); pciTmp->next = pciList; pciList = pciTmp; + pciTmp->enabled = config.pci; pciTmp->bdf = pcibuses[busidx] << 8 | dev << 3 | func; pciTmp->vendor = pciheader[0] & 0xffff; pciTmp->device = pciheader[0] >> 16; - command = pciheader[1] & 0xffff; pciTmp->cls = pciheader[0x02] >> 8; - pciTmp->enabled = ((command & 3) == 3); if (PCI_BRIDGE_CLASS(pciTmp->cls)) { if (PCI_BRIDGE_PCI_CLASS(pciTmp->cls)) { /*PCI-PCI*/ Z_printf("PCI-PCI bridge:\n"); diff --git a/src/base/bios/setup.c b/src/base/bios/setup.c index d1ed2b1..ab133ee 100644 --- a/src/base/bios/setup.c +++ b/src/base/bios/setup.c @@ -15,8 +15,6 @@ #include "lowmem.h" #include "int.h" #include "iodev.h" -#include "virq.h" -#include "vint.h" #include "emm.h" #include "xms.h" #include "hma.h" @@ -104,9 +102,6 @@ static void late_init_thr(void *arg) return; /* if something else is to be added here, * add the "late_init" member into dev_list instead */ - virq_setup(); - vint_setup(); - pit_late_init(); video_late_init(); mouse_late_init(); mouse_client_post_init(); @@ -133,7 +128,7 @@ static void bios_setup(void) /* init trapped interrupts called via jump */ for (i = 0; i < 256; i++) { - if (config.vga) { + if (config.vga && !config.vbios_post) { uint16_t seg, off; unsigned int addr; @@ -142,47 +137,31 @@ static void bios_setup(void) v_printf("int0x%x was 0x%04x:0x%04x\n", i, seg, off); addr = SEGOFF2LINEAR(seg, off); if (addr >= VBIOS_START && addr < VBIOS_START + VBIOS_SIZE) { - v_printf("Setting int0x%x to 0x%04x:0x%04x\n", i, seg, off); + g_printf("Setting int0x%x to 0x%04x:0x%04x\n", i, seg, off); SETIVEC(i, seg, off); continue; } } - switch (i) { - case 0x60 ... 0x67: - case 0x79 ... 0xff: - /* interrupts >= 0xc0 are NULL unless defined by DOSEMU */ - SETIVEC(i, 0, 0); - break; - case 0x68 ... 0x6f: - /* 0x68-0x6f are usually set to iret */ - SETIVEC(i, IRET_SEG, IRET_OFF); - break; - case 0x70 ... 0x78: - SETIVEC(i, BIOSSEG, EOI2_OFF); - break; - case 0 ... 7: - case 0x10 ... 0x5f: - SETIVEC(i, BIOSSEG, INT_OFF(i)); - break; - case 8: // timer - case 9: // kbd - case 11: // com2,4 - case 12: // com1,3 - case 14: // floppy - case 15: // spurious - SETIVEC(i, BIOSSEG, EOI_OFF); - break; - case 10: // re-routed from irq9/int71h (mt32) - case 13: // exception D (GPF) or SB16 IRQ - SETIVEC(i, IRET_SEG, IRET_OFF); - break; + /* interrupts >= 0xc0 are scratch (BIOS stack), + unless defined by DOSEMU */ + if ((i & 0xf8) == 0x60 || (i >= 0x78 && i < 0xc0)) { /* user interrupts */ + /* show also EMS (int0x67) as disabled */ + SETIVEC(i, 0, 0); + } else if ((i & 0xf8) == 0x68) { + SETIVEC(i, IRET_SEG, IRET_OFF); + } else if (i < 0x78 || i == DOS_HELPER_INT || i == 0xe7) { + SETIVEC(i, BIOSSEG, INT_OFF(i)); } } - SETIVEC(DOS_HELPER_INT, BIOSSEG, INT_OFF(DOS_HELPER_INT)); - SETIVEC(0xe7, BIOSSEG, INT_OFF(0xe7)); + /* Let kernel handle this, no need to return to DOSEMU */ + #if 0 + SETIVEC(0x1c, BIOSSEG + 0x10, INT_OFF(0x1c) +2 - 0x100); + #endif + SETIVEC(0x09, INT09_SEG, INT09_OFF); + SETIVEC(0x0a, BIOSSEG, EOI_OFF); SETIVEC(0x08, INT08_SEG, INT08_OFF); /* 0x30 and 0x31 are not vectors, they are the 5-byte long jump. * While 0x30 is overwritten entirely, only one byte is overwritten @@ -200,21 +179,11 @@ static void bios_setup(void) SETIVEC(0x67, BIOSSEG, INT_OFF(0x67)); if (config.pktdrv) SETIVEC(0x60, PKTDRV_SEG, PKTDRV_OFF); - if (config.ipxsup) - SETIVEC(0x7a, BIOSSEG, INT_OFF(0x7a)); if (config.mouse.intdrv) SETIVEC(0x74, BIOSSEG, Mouse_ROUTINE_OFF); - - /* set up PIC */ - port_outb(0x20, 0x10); // ICW1 - port_outb(0x21, 8); // ICW2, set irq to 8 - port_outb(0x21, 1 << 2); // ICW3m, slave on irq2 - port_outb(0xa0, 0x10); // ICW1 - port_outb(0xa1, 0x70); // ICW2, set irq to 0x70 - port_outb(0xa1, 2); // ICW3s, master uses irq2 - /* mask out SB irqs or Blood game crashes */ - if (config.sound) - port_outb(0x21, (1 << config.sb_irq) | port_inb(0x21)); + /* IPX. Dummy but should not crash */ + if (config.ipxsup) + SETIVEC(0x7a, BIOSSEG, INT_OFF(0x7a)); /* Install new handler for video-interrupt into bios_f000_int10ptr, * for video initialization at f800:4200 @@ -223,6 +192,14 @@ static void bios_setup(void) */ install_int_10_handler(); + { + /* update boot drive in Banner-code */ + unsigned ptr; + + ptr = SEGOFF2LINEAR(BIOSSEG, bios_f000_bootdrive); + WRITE_BYTE(ptr, (config.hdiskboot >= 2 || config.hdiskboot == -1) ? 0x80 : 0); + } + bios_mem_setup(); /* setup values in BIOS area */ } @@ -230,6 +207,7 @@ static void dosemu_reset(void) { initialized = 0; dos_post_boot_reset(); + mfs_reset(); iodev_reset(); /* reset all i/o devices */ commands_plugin_inte6_reset(); lowmem_reset(); /* release memory used by helper utilities */ diff --git a/src/base/bios/vgabios.c b/src/base/bios/vgabios.c index aaeed3c..6c717a1 100644 --- a/src/base/bios/vgabios.c +++ b/src/base/bios/vgabios.c @@ -31,7 +31,7 @@ // - rombios.c of plex86 // // This VGA Bios contains fonts from : -// - fntcol16.zip (c) by Joseph Gil available at : +// - fntcol16.zip (c) by Joseph Gil avalable at : // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip // These fonts are public domain // @@ -97,12 +97,12 @@ Bit8u xstart,Bit8u ysrc,Bit8u ydest,Bit8u cols,Bit8u nbcols,Bit8u cheight) src=ysrc*cheight*nbcols+xstart+vstart; dest=ydest*cheight*nbcols+xstart+vstart; - port_outw(VGAREG_GRDC_ADDRESS, 0x0105); + outw(VGAREG_GRDC_ADDRESS, 0x0105); for(i=0;ibuffer_start,address,attr,nbrows*nbcols*cheight); - port_outw(VGAREG_GRDC_ADDRESS, 0x0005); + outw(VGAREG_GRDC_ADDRESS, 0x0005); } else {// if Scroll up @@ -346,15 +346,15 @@ static void write_gfx_char_pl4(Bit16u vstart,Bit8u car,Bit8u attr, fdata = MEM_BASE32(IVEC(0x43)); addr=xcurs+ycurs*cheight*nbcols+vstart; src = car * cheight; - port_outw(VGAREG_SEQU_ADDRESS, 0x0f02); - port_outw(VGAREG_GRDC_ADDRESS, 0x0205); + outw(VGAREG_SEQU_ADDRESS, 0x0f02); + outw(VGAREG_GRDC_ADDRESS, 0x0205); if(attr&0x80) { - port_outw(VGAREG_GRDC_ADDRESS, 0x1803); + outw(VGAREG_GRDC_ADDRESS, 0x1803); } else { - port_outw(VGAREG_GRDC_ADDRESS, 0x0003); + outw(VGAREG_GRDC_ADDRESS, 0x0003); } for(i=0;i>j; - port_outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); + outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); read_byte(0xa000,dest); if(fdata[src+i]&mask) { @@ -385,9 +385,9 @@ ASM_START out dx, ax ASM_END #else - port_outw(VGAREG_GRDC_ADDRESS, 0xff08); - port_outw(VGAREG_GRDC_ADDRESS, 0x0005); - port_outw(VGAREG_GRDC_ADDRESS, 0x0003); + outw(VGAREG_GRDC_ADDRESS, 0xff08); + outw(VGAREG_GRDC_ADDRESS, 0x0005); + outw(VGAREG_GRDC_ADDRESS, 0x0003); #endif } @@ -531,10 +531,10 @@ static void biosfn_set_cursor_pos(Bit8u page,Bit16u cursor) // CRTC regs 0x0e and 0x0f crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); - port_outb(crtc_addr,0x0e); - port_outb(crtc_addr+1,(address&0xff00)>>8); - port_outb(crtc_addr,0x0f); - port_outb(crtc_addr+1,address&0x00ff); + outb(crtc_addr,0x0e); + outb(crtc_addr+1,(address&0xff00)>>8); + outb(crtc_addr,0x0f); + outb(crtc_addr+1,address&0x00ff); } } @@ -851,12 +851,12 @@ static void biosfn_write_pixel(Bit8u BH,Bit8u AL,Bit16u CX,Bit16u DX) addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)+ READ_WORD(BIOS_VIDEO_MEMORY_USED)*BH; mask = 0x80 >> (CX & 0x07); - port_outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); - port_outw(VGAREG_GRDC_ADDRESS, 0x0205); + outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); + outw(VGAREG_GRDC_ADDRESS, 0x0205); data = read_byte(0xa000,addr); if (AL & 0x80) { - port_outw(VGAREG_GRDC_ADDRESS, 0x1803); + outw(VGAREG_GRDC_ADDRESS, 0x1803); } write_byte(0xa000,addr,AL); #if 0 @@ -870,9 +870,9 @@ ASM_START out dx, ax ASM_END #else - port_outw(VGAREG_GRDC_ADDRESS, 0xff08); - port_outw(VGAREG_GRDC_ADDRESS, 0x0005); - port_outw(VGAREG_GRDC_ADDRESS, 0x0003); + outw(VGAREG_GRDC_ADDRESS, 0xff08); + outw(VGAREG_GRDC_ADDRESS, 0x0005); + outw(VGAREG_GRDC_ADDRESS, 0x0003); #endif break; case CGA: @@ -947,7 +947,7 @@ static unsigned char biosfn_read_pixel(Bit8u BH,Bit16u CX,Bit16u DX) attr = 0x00; for(i=0;i<4;i++) { - port_outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04); + outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04); data = read_byte(0xa000,addr) & mask; if (data > 0) attr |= (0x01 << i); } diff --git a/src/base/bios/x86/Makefile b/src/base/bios/x86/Makefile index d6a5a72..b11b045 100644 --- a/src/base/bios/x86/Makefile +++ b/src/base/bios/x86/Makefile @@ -2,21 +2,37 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.conf GENSRC = bios_symbols.c -SFILES = bios.S -bios_S_START = 0xe000 -ALL_CPPFLAGS += -DBIOS_START=$(bios_S_START) +XSFILES = bios.s +BIOS_START = 0xe000 +ALL_CPPFLAGS += -DBIOS_START=$(BIOS_START) all: lib +# unused target, for testing +everyth: lib bios_offsets.hh bios_data.xxd include $(REALTOPDIR)/src/Makefile.common # to support parallel build, we need a separate .o and .elf for every gen target -bios1.o: $(srcdir)/bios.S $(srcdir)/Makefile $(top_builddir)/src/include/version.hh - $(CPP) $(ALL_CPPFLAGS) -x assembler-with-cpp $< | $(XAS) $(XASFLAGS) -o $@ +bios0.o bios1.o bios2.o: $(srcdir)/bios.s $(srcdir)/Makefile $(top_builddir)/src/include/version.hh + $(CPP) $(ALL_CPPFLAGS) -x assembler-with-cpp $< | $(AS) --32 -o $@ -.INTERMEDIATE: bios1.o +.INTERMEDIATE: bios_data bios0.elf bios1.elf bios2.elf bios0.o bios1.o bios2.o -bios_symbols.c: bios1.o +bios_data: bios0.elf + $(OBJCOPY) -j .text -O binary $< $@ + +# Makefile defines BIOS_START so add to deps +bios%.elf: bios%.o $(srcdir)/Makefile + # formal intermediate filename is necessary for xxd to name structure + $(AS_LD) $(AS_LDFLAGS) -static --section-start .text=$(BIOS_START) -e bios_data_start -Map bios.map -o $@ $< + chmod -x $@ + +bios_data.xxd: bios_data + echo "const char *bios_data = \"\\" >$@ + hexdump -v -e '"\\" "x" 1/1 "%02X"' $< >>$@ + echo "\";" >>$@ + +bios_symbols.c: bios1.elf nm -g -n $< | gawk '\ BEGIN {\ COUNT=0;\ @@ -28,7 +44,7 @@ bios_symbols.c: bios1.o }\ {\ HEXSTR = sprintf("0x%s", $$1);\ - ADDR = strtonum(HEXSTR) + $(bios_S_START);\ + ADDR = strtonum(HEXSTR);\ if (ADDR <= 0xffff) {\ COUNT++;\ printf " { 0x%04x, \"%s\" },\n", ADDR, $$3;\ @@ -41,5 +57,23 @@ bios_symbols.c: bios1.o }\ ' > $@ || (rm -f $@ ; false) +bios_offsets.hh: bios2.elf + nm -g -n $< | gawk '\ + BEGIN {\ + print "// Warning: autogenerated";\ + print "";\ + }\ + {\ + HEXSTR = sprintf("0x%s", $$1);\ + ADDR = strtonum(HEXSTR);\ + if (ADDR <= 0xffff) {\ + printf "#define %s 0x%04x\n", $$3, ADDR;\ + }\ + }\ + END {\ + print "";\ + }\ + ' > $@ || (rm -f $@ ; false) + clean:: - rm -f *.o *.d bios_symbols.c *.map + rm -f *.o *.d bios_symbols.c bios_offsets.hh bios_data.xxd bios_data bios*.elf bios.map diff --git a/src/base/bios/x86/bios.S b/src/base/bios/x86/bios.s similarity index 94% rename from src/base/bios/x86/bios.S rename to src/base/bios/x86/bios.s index d8778c9..31a6c1e 100644 --- a/src/base/bios/x86/bios.S +++ b/src/base/bios/x86/bios.s @@ -16,7 +16,6 @@ /* some other useful definitions */ #define BIOSSEG 0xf000 -/* below block is used in int 9 with DS=BIOS_DATA */ #define BIOS_DATA 0x40 #define KEYBUF_READ_PTR 0x1a #define KEYBUF_WRITE_PTR 0x1c @@ -25,10 +24,6 @@ #define KEYSHIFT_FLAGS 0x17 #define KEYBOARD_FLAGS_2 0x18 #define KEYBOARD_STATUS_3 0x96 -#define BIOS_FLAGS_1 0x71 -#define BIOS_FLAGS_2 0x72 -/* end int 9 defines */ - #define BIOS_TIMER 0x46c #define BIOS_TIMER_OVERFLOW 0x470 #define HOUR24_ADJUST 0x1800B0 @@ -54,8 +49,6 @@ _ORG(0xe000) _ORG(ROM_BIOS_SELFTEST) /* COMPAS FE05B jmp to POST */ /* COMPAS FE05E-FE2C2 reserved */ - .global _start -_start: hlt sti @@ -75,6 +68,7 @@ _start: lcall *%cs:bios_f000_int10ptr popw %ds sti + jmp video_init_done /* ----------------------------------------------------------------- */ /* Post-less video init @@ -85,6 +79,8 @@ no_vbios_post: video_init_done: movb $DOS_HELPER_SHOW_BANNER,%al int $DOS_HELPER_INT + movb %cs:bios_f000_bootdrive,%dl + movb $DOS_HELPER_READ_MBR,%al int $DOS_HELPER_INT ljmp $0x0, $0x7c00 /* Some boot sectors require cs=0 */ @@ -106,9 +102,16 @@ GET_RETCODE_HELPER: int $DOS_HELPER_INT lret - /* This is the int74 handler */ - .globl Mouse_ROUTINE_OFF +/* ----------------------------------------------------------------- */ + /* this is IRET */ + .globl IRET_OFF +IRET_OFF: + iret + + .globl Mouse_ROUTINE_OFF Mouse_ROUTINE_OFF: + + /* This is the int74 handler */ pushw %ax /* save everything */ pushw %bx movw $DOS_HELPER_MOUSE_HELPER,%ax /* mouse helper */ @@ -119,10 +122,11 @@ Mouse_ROUTINE_OFF: ljmp $BIOSSEG, $EOI2_OFF /* ----------------------------------------------------------------- */ - /* this is IRET */ - .globl IRET_OFF -IRET_OFF: - iret + .globl IPX_OFF +IPX_OFF: +ipx_handler: + int $0x7a + lret /* ----------------------------------------------------------------- */ /* This is an int e7 used for FCB opens */ @@ -351,8 +355,6 @@ int09_cont: check_special: cmpw $SP_BREAK, %ax je kbd_do_break - cmpw $SP_CC, %ax - je kbd_do_cc cmpw $SP_PRTSCR, %ax je kbd_do_prtscr cmpw $SP_SYSRQ_MAKE, %ax @@ -383,12 +385,6 @@ no_wrap: buffer_full: ret -clear_kbd_buffer: - movw KEYBUFFER_START,%bx - movw %bx,KEYBUF_WRITE_PTR - movw %bx,KEYBUF_READ_PTR - ret - kbd_do_pause: testb $PAUSE_MASK,KEYBOARD_FLAGS_2 /* already paused? */ jnz kbd_done /* do nothing */ @@ -404,37 +400,24 @@ kbd_do_pause: jmp kbd_done2 kbd_do_break: /* CTRL-BREAK pressed */ - movw $0,%ax -kbd_do_cc: /* CTRL-c pressed */ - call clear_kbd_buffer + movw $0x100,%ax call store_key - orb $0x80,BIOS_FLAGS_1 - call kbd_EOI - sti int $0x1b /* call BREAK interrupt */ - jmp kbd_done2 + jmp kbd_done kbd_do_prtscr: /* PRINT SCREEN pressed */ - call kbd_EOI - sti int $0x05 - jmp kbd_done2 + jmp kbd_done kbd_do_sysrq_make: /* Alt-SYSRQ pressed */ - orb $4,KEYBOARD_FLAGS_2 /* set sysrq bit */ - call kbd_EOI - sti movw $0x8500,%ax int $0x15 - jmp kbd_done2 + jmp kbd_done kbd_do_sysrq_break: /* ALT-SYSRQ released */ - andb $~4,KEYBOARD_FLAGS_2 /* clear sysrq bit */ - call kbd_EOI - sti movw $0x8501,%ax int $0x15 - jmp kbd_done2 + jmp kbd_done kbd_do_CAD: call kbd_EOI @@ -467,6 +450,10 @@ bios_f000_int10_old: bios_in_int10_callback: .byte 0 + .globl bios_f000_bootdrive +bios_f000_bootdrive: + .byte 0 + /* this is the paramblock, we told DOS to use for INT21 AX=4B01 */ .align 16,0 .globl DBGload_parblock @@ -579,22 +566,12 @@ DPMI_return_from_realmode: .globl DPMI_return_from_dos_memory DPMI_return_from_dos_memory: hlt - -.macro ihdr n - .globl \n -\n: -.rept DPMI_MAX_CLIENTS + .globl DPMI_int1c +DPMI_int1c: hlt - jmp \n\()_end -.endr - .globl \n\()_end -\n\()_end: -.endm - -ihdr DPMI_int1c iret - -ihdr DPMI_int23 + .globl DPMI_int23 +DPMI_int23: pushw %ax pushw %bx movw $0x6200, %ax /* get PSP */ @@ -611,10 +588,10 @@ DPMI_int23_2: iret 1: /* leave flags on stack */ lret - -ihdr DPMI_int24 + .globl DPMI_int24 +DPMI_int24: + hlt iret - .globl DPMI_raw_mode_switch_rm DPMI_raw_mode_switch_rm: hlt @@ -622,13 +599,6 @@ DPMI_raw_mode_switch_rm: DPMI_save_restore_rm: hlt lret - .globl DPMI_exit -DPMI_exit: - jnz 1f - /* last client terminated, reinit FPU */ - fninit -1: - int $0x21 .globl DPMI_end DPMI_end: @@ -643,16 +613,14 @@ XMSControl_OFF: .globl EOI_OFF EOI_OFF: - cli pushw %ax - movb $0x20,%al - outb %al,$0x20 /* flag interrupt complete */ + movb $0x20,%al + outb %al,$0x20 /* flag interrupt complete */ popw %ax iret .globl EOI2_OFF EOI2_OFF: - cli pushw %ax movb $0x20,%al outb %al,$0xa0 @@ -755,9 +723,8 @@ LFN_42_A6_HELPER_COMMON: movw $0x1216, %ax int $0x2f jc 1f - popw %ax /* restore function number */ - orb $0x80, %al /* add extension bit */ stc + popw %ax /* restore function number */ int $0x2f jmp 3f 1: @@ -934,18 +901,13 @@ bios_text_font: _ORG(0xfea6) .globl INT75_OFF INT75_OFF: - int $2 /* Bochs does this; RBIL says: redirected to INT 02 */ - /* by the BIOS, for compatibility with the PC */ - fnclex /* Clear FP exceptions just in case a hooked - handler hasn't already done so, so we won't - get stuck (in real mode IGNNE would prevent - further exceptions but we don't emulate that) */ xorb %al, %al outb %al, $0xf0 movb $0x20, %al outb %al, $0xa0 outb %al, $0x20 - iret + int $2 /* Bochs does this; RBIL says: redirected to INT 02 */ + iret /* by the BIOS, for compatibility with the PC */ /* ----------------------------------------------------------------- */ .globl INT08_OFF @@ -1000,15 +962,12 @@ INT08_L2: .globl INT71_OFF INT71_OFF: push %ax - /* EOI to PIC1 */ + /* EOI to PIC2 */ movb $0x20, %al outb %al, $0xa0 + pop %ax /* Then invoke IRQ2 */ int $0x0a - /* Specific EOI */ - movb $0x62, %al - outb %al, $0x20 - pop %ax iret /* return to interrupted code */ /* COMPAS FFEF3 vector table for INT08-INT1F */ diff --git a/src/base/bios/x86/bios_offsets.h b/src/base/bios/x86/bios_offsets.h deleted file mode 100644 index 6641037..0000000 --- a/src/base/bios/x86/bios_offsets.h +++ /dev/null @@ -1,88 +0,0 @@ -extern const unsigned bios_data_start; -extern const unsigned ROM_BIOS_EXIT; -extern const unsigned GET_RETCODE_HELPER; -extern const unsigned Mouse_ROUTINE_OFF; -extern const unsigned IRET_OFF; -extern const unsigned FCB_HLP_OFF; -extern const unsigned INT10_WATCHER_OFF; -extern const unsigned MOUSE_INT33_OFF; -extern const unsigned INT70_OFF; -extern const unsigned INT70_end; -extern const unsigned HD_parameter_table0; -extern const unsigned HD_parameter_table1; -extern const unsigned bios_f000_int10ptr; -extern const unsigned bios_f000_int10_old; -extern const unsigned bios_in_int10_callback; -extern const unsigned DBGload_parblock; -extern const unsigned DBGload_CSIP; -extern const unsigned PKTDRV_param; -extern const unsigned PKTDRV_stats; -extern const unsigned LFN_short_name; -extern const unsigned bios_hlt_blk; -extern const unsigned DPMI_OFF; -extern const unsigned DPMI_dpmi_init; -extern const unsigned DPMI_return_from_dos; -extern const unsigned DPMI_return_from_rmint; -extern const unsigned DPMI_return_from_realmode; -extern const unsigned DPMI_return_from_dos_memory; -extern const unsigned DPMI_int1c; -extern const unsigned DPMI_int1c_end; -extern const unsigned DPMI_int23; -extern const unsigned DPMI_int23_end; -extern const unsigned DPMI_int23_1; -extern const unsigned DPMI_int23_2; -extern const unsigned DPMI_int24; -extern const unsigned DPMI_int24_end; -extern const unsigned DPMI_raw_mode_switch_rm; -extern const unsigned DPMI_save_restore_rm; -extern const unsigned DPMI_exit; -extern const unsigned DPMI_end; -extern const unsigned XMSControl_OFF; -extern const unsigned EOI_OFF; -extern const unsigned EOI2_OFF; -extern const unsigned PKTDRV_OFF; -extern const unsigned PKTDRV_driver_name; -extern const unsigned PKTDRV_driver_entry_ip; -extern const unsigned PKTDRV_driver_entry_cs; -extern const unsigned FOSSIL_isr; -extern const unsigned FOSSIL_oldisr; -extern const unsigned FOSSIL_magic; -extern const unsigned FOSSIL_maxfun; -extern const unsigned FOSSIL_idstring; -extern const unsigned LFN_HELPER_OFF; -extern const unsigned LFN_42_HELPER_OFF; -extern const unsigned LFN_A6_HELPER_OFF; -extern const unsigned DBGload_OFF; -extern const unsigned INT_RVC_21_OFF; -extern const unsigned int_rvc_ip_21; -extern const unsigned int_rvc_cs_21; -extern const unsigned int_rvc_ret_ip_21; -extern const unsigned int_rvc_ret_cs_21; -extern const unsigned int_rvc_disp_ip_21; -extern const unsigned int_rvc_disp_cs_21; -extern const unsigned INT_RVC_28_OFF; -extern const unsigned int_rvc_ip_28; -extern const unsigned int_rvc_cs_28; -extern const unsigned int_rvc_ret_ip_28; -extern const unsigned int_rvc_ret_cs_28; -extern const unsigned int_rvc_disp_ip_28; -extern const unsigned int_rvc_disp_cs_28; -extern const unsigned INT_RVC_2f_OFF; -extern const unsigned int_rvc_ip_2f; -extern const unsigned int_rvc_cs_2f; -extern const unsigned int_rvc_ret_ip_2f; -extern const unsigned int_rvc_ret_cs_2f; -extern const unsigned int_rvc_disp_ip_2f; -extern const unsigned int_rvc_disp_cs_2f; -extern const unsigned INT_RVC_33_OFF; -extern const unsigned int_rvc_ip_33; -extern const unsigned int_rvc_cs_33; -extern const unsigned int_rvc_ret_ip_33; -extern const unsigned int_rvc_ret_cs_33; -extern const unsigned int_rvc_disp_ip_33; -extern const unsigned int_rvc_disp_cs_33; -extern const unsigned bios_text_font; -extern const unsigned INT75_OFF; -extern const unsigned INT08_OFF; -extern const unsigned INT71_OFF; -extern const unsigned bios_f000_end; diff --git a/src/base/core/Makefile b/src/base/core/Makefile index 6d455c3..a17b298 100644 --- a/src/base/core/Makefile +++ b/src/base/core/Makefile @@ -1,7 +1,15 @@ + top_builddir=../../.. include $(top_builddir)/Makefile.conf -CFILES = dyndeb.c int.c hlt.c emu.c ports.c coopth.c dump.c lowmem.c priv.c \ - vint.c + +# src/base/misc/dyndeb.c -> ../async/dyndeb.c +# src/base/misc/int.c -> ../async/int.c + +CFILES = dyndeb.c int.c hlt.c emu.c ports.c coopth.c dump.c lowmem.c priv.c include $(REALTOPDIR)/src/Makefile.common + +all: lib + +install: all diff --git a/src/base/core/coopth.c b/src/base/core/coopth.c index 6d04a17..4e4b437 100644 --- a/src/base/core/coopth.c +++ b/src/base/core/coopth.c @@ -30,11 +30,9 @@ #include #include #include -#include #ifdef HAVE_EXECINFO #include #endif -#include "emu.h" #include "utilities.h" #include "libpcl/pcl.h" #include "coopth.h" @@ -70,11 +68,11 @@ struct coopth_thrdata_t { struct coopth_thrfunc_t clnup; struct coopth_thrfunc_t uhook; jmp_buf exit_jmp; - unsigned int canc_disabled:1; - unsigned int attached:1; - unsigned int cancelled:1; - unsigned int left:1; - unsigned int atomic_switch:1; + int canc_disabled:1; + int attached:1; + int cancelled:1; + int left:1; + int atomic_switch:1; }; struct coopth_ctx_handlers_t { @@ -108,7 +106,7 @@ struct coopth_per_thread_t { struct coopth_starter_args_t args; void *stack; size_t stk_size; - unsigned int quick_sched:1; + int quick_sched:1; void (*retf)(int tid, int idx); }; @@ -119,8 +117,8 @@ struct coopth_t { int len; int cur_thr; int max_thr; - unsigned int detached:1; - unsigned int custom:1; + int detached:1; + int custom:1; coopth_func_t func; struct coopth_ctx_handlers_t ctxh; struct coopth_sleep_handlers_t sleeph; @@ -128,23 +126,22 @@ struct coopth_t { struct coopth_per_thread_t pth[MAX_COOP_RECUR_DEPTH]; struct coopth_per_thread_t *post_pth; const struct coopth_be_ops *ops; - pthread_t pthread; }; -static __TLS cohandle_t co_handle; +static cohandle_t co_handle; static struct coopth_t coopthreads[MAX_COOPTHREADS]; static int coopth_num; -static __TLS int thread_running; -static __TLS int joinable_running; -static __TLS int left_running; +static int thread_running; +static int joinable_running; +static int left_running; #define DETACHED_RUNNING (thread_running - joinable_running - left_running) -static __TLS int threads_joinable; -static __TLS int threads_left; -static __TLS int threads_total; +static int threads_joinable; +static int threads_left; +static int threads_total; #define MAX_ACT_THRS 10 -static __TLS int threads_active; -static __TLS int active_tids[MAX_ACT_THRS]; -static __TLS void (*nothread_notifier)(int); +static int threads_active; +static int active_tids[MAX_ACT_THRS]; +static void (*nothread_notifier)(void); static void coopth_callf_chk(struct coopth_t *thr, struct coopth_per_thread_t *pth); @@ -320,8 +317,8 @@ static void do_del_thread(struct coopth_t *thr, thr->post_pth = pth; } } - if (nothread_notifier) - nothread_notifier(threads_joinable + threads_left); + if (threads_joinable + threads_left == 0 && nothread_notifier) + nothread_notifier(); } static void coopth_retf(struct coopth_t *thr, struct coopth_per_thread_t *pth, @@ -366,7 +363,7 @@ static struct coopth_per_thread_t *current_thr(struct coopth_t *thr) struct coopth_per_thread_t *pth; assert(thr - coopthreads < MAX_COOPTHREADS); if (!thr->cur_thr) { - error("coopth: schedule to inactive thread %i\n", thr->tid); + error("coopth: schedule to inactive thread\n"); exit(2); return NULL; } @@ -570,7 +567,7 @@ int coopth_create_internal(const char *name, coopth_func_t func, struct coopth_t *thr; assert(coopth_num < MAX_COOPTHREADS); - num = __sync_fetch_and_add(&coopth_num, 1); + num = coopth_num++; thr = &coopthreads[num]; thr->name = name; thr->cur_thr = 0; @@ -579,7 +576,6 @@ int coopth_create_internal(const char *name, coopth_func_t func, thr->len = 1; thr->func = func; thr->ops = ops; - thr->pthread = pthread_self(); call_prep(thr); return num; } @@ -592,7 +588,7 @@ int coopth_create_multi_internal(const char *name, int len, assert(len && coopth_num + len <= MAX_COOPTHREADS); num = coopth_num; - __sync_fetch_and_add(&coopth_num, len); + coopth_num += len; for (i = 0; i < len; i++) { struct coopth_t *thr = &coopthreads[num + i]; thr->name = name; @@ -602,7 +598,6 @@ int coopth_create_multi_internal(const char *name, int len, thr->len = (i == 0 ? len : 1); thr->func = func; thr->ops = ops; - thr->pthread = pthread_self(); call_prep(thr); } return num; @@ -649,8 +644,11 @@ static int do_start(struct coopth_t *thr, struct coopth_state_t st, void *arg) if (thr->cur_thr > thr->max_thr) { size_t stk_size = COOP_STK_SIZE(); thr->max_thr = thr->cur_thr; +#ifndef MAP_STACK +#define MAP_STACK 0 +#endif pth->stack = mmap(NULL, stk_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); if (pth->stack == MAP_FAILED) { error("Unable to allocate stack\n"); exit(21); @@ -821,7 +819,12 @@ static int detach_sw(struct coopth_t *thr, struct coopth_per_thread_t *pth) /* this is special: thread already finished, can't be ran */ do_del_thread(thr, pth); return 1; - default: + case idx_LEAVE: + case idx_SCHED: + case idx_ATTACH: + case idx_AWAKEN: + case idx_YIELD: + case idx_WAIT: sw_list[pth->st.sw_idx](thr, pth); break; } @@ -938,8 +941,7 @@ static int __coopth_is_in_thread(int warn, const char *f) int coopth_get_tid(void) { struct coopth_thrdata_t *thdata; - if (!_coopth_is_in_thread_nowarn()) - return -1; + assert(_coopth_is_in_thread()); thdata = co_get_data(co_current(co_handle)); return *thdata->tid; } @@ -1069,6 +1071,13 @@ static int check_cancel(void) return -1; /* never reached */ } +static void check_cancel_chk(void) +{ + /* normal (non-disabled) cancellation case */ + int can = check_cancel(); + assert(!can); +} + static struct coopth_t *on_thread(unsigned id) { int i; @@ -1092,13 +1101,11 @@ static int current_active(void) return thr->ops->is_active(CIDX2(tid, thr->cur_thr - 1)); } -int coopth_yield(void) +void coopth_yield(void) { assert(_coopth_is_in_thread()); switch_state(COOPTH_YIELD); - if (check_cancel()) - return -1; - return 1; + check_cancel_chk(); } int coopth_sched(void) @@ -1125,27 +1132,23 @@ int coopth_sched_cond(void) return 1; } -int coopth_wait(void) +void coopth_wait(void) { assert(_coopth_is_in_thread()); ensure_attached(); switch_state(COOPTH_WAIT); - if (check_cancel()) - return -1; - return 1; + check_cancel_chk(); } -int coopth_sleep(void) +void coopth_sleep(void) { int tid = coopth_get_tid(); assert(_coopth_is_in_thread()); if (!is_detached()) - coopthreads[tid].ops->to_sleep(tid); + coopthreads[tid].ops->to_sleep(); switch_state(COOPTH_SLEEP); - if (check_cancel()) - return -1; - return 1; + check_cancel_chk(); } static void ensure_single(struct coopth_thrdata_t *thdata) @@ -1235,17 +1238,6 @@ void coopth_abandon(void) * has a separate entry point (via coopth_run()), the left thread must * not have a separate entry point. So it appeared better to return the * special type "left" threads. */ -static void do_leave(struct coopth_thrdata_t *thdata) -{ - if (thdata->posth_num) - dosemu_error("coopth: leaving thread with active post handlers\n"); - if (!current_active()) - dosemu_error("coopth: leaving descheduled thread\n"); - if (!thdata->attached) - dosemu_error("coopth: leaving detached thread\n"); - switch_state(COOPTH_LEAVE); -} - void coopth_leave(void) { struct coopth_thrdata_t *thdata; @@ -1254,19 +1246,13 @@ void coopth_leave(void) thdata = co_get_data(co_current(co_handle)); if (thdata->left) return; - do_leave(thdata); -} - -void coopth_leave_internal(void) -{ - struct coopth_thrdata_t *thdata; - if (!_coopth_is_in_thread_nowarn()) - return; - thdata = co_get_data(co_current(co_handle)); - if (thdata->left) - return; - assert(coopthreads[*thdata->tid].custom); - do_leave(thdata); + if (thdata->posth_num) + dosemu_error("coopth: leaving thread with active post handlers\n"); + if (!current_active()) + dosemu_error("coopth: leaving descheduled thread\n"); + if (!thdata->attached) + dosemu_error("coopth: leaving detached thread\n"); + switch_state(COOPTH_LEAVE); } static void do_awake(struct coopth_per_thread_t *pth) @@ -1320,7 +1306,7 @@ again: struct coopth_per_thread_t *pth = current_thr(thr); if (!pth->data.attached) continue; - /* don't cancel own thread */ + /* dont cancel own thread */ assert(!thdata || *thdata->tid != tid); do_cancel(thr, pth); do_detach(thr, pth); @@ -1414,7 +1400,7 @@ again: int tid = active_tids[i]; struct coopth_t *thr = &coopthreads[tid]; struct coopth_per_thread_t *pth = current_thr(thr); - /* don't cancel own thread */ + /* dont cancel own thread */ if (thdata && *thdata->tid == tid) continue; if (!pth->data.attached) { @@ -1436,10 +1422,7 @@ again: for (i = 0; i < coopth_num; i++) { struct coopth_t *thr = &coopthreads[i]; int j; - - if (!pthread_equal(thr->pthread, pthread_self())) - continue; - /* don't free own thread */ + /* dont free own thread */ if (thdata && *thdata->tid == i) continue; for (j = thr->cur_thr; j < thr->max_thr; j++) { @@ -1464,12 +1447,12 @@ int coopth_wants_sleep_internal(unsigned id) pth->st.state == COOPTHS_SWITCH); } -void coopth_set_nothread_notifier(void (*notifier)(int)) +void coopth_set_nothread_notifier(void (*notifier)(void)) { nothread_notifier = notifier; } -void coopth_cancel_disable_cur(void) +void coopth_cancel_disable(void) { struct coopth_thrdata_t *thdata; assert(_coopth_is_in_thread()); @@ -1477,7 +1460,7 @@ void coopth_cancel_disable_cur(void) thdata->canc_disabled = 1; } -void coopth_cancel_enable_cur(void) +void coopth_cancel_enable(void) { struct coopth_thrdata_t *thdata; assert(_coopth_is_in_thread()); diff --git a/src/base/core/dump.c b/src/base/core/dump.c index c2e398c..af4b6ca 100644 --- a/src/base/core/dump.c +++ b/src/base/core/dump.c @@ -19,9 +19,9 @@ char *emu_disasm(unsigned int ip) { - static char buf[2048]; + static char buf[512]; #ifdef USE_MHPDBG - char frmtbuf[1024]; + char frmtbuf[256]; int rc, i; unsigned int cp; char *p; @@ -154,7 +154,7 @@ show_ints(int min, int max) void dump_state(void) { - cpuctx_t *scp = dpmi_get_scp(); + sigcontext_t *scp = dpmi_get_scp(); show_regs(); if (scp) dbug_printf("\nProtected-mode state dump:\n%s\n", DPMI_show_state(scp)); diff --git a/src/base/core/emu.c b/src/base/core/emu.c index bad94fb..02f217d 100644 --- a/src/base/core/emu.c +++ b/src/base/core/emu.c @@ -57,10 +57,11 @@ #include "version.h" #include "memory.h" +#include "mhpdbg.h" +#include "debug.h" #include "emu.h" -#include "mhpdbg.h" #include "bios.h" #include "video.h" #include "timers.h" @@ -83,7 +84,7 @@ #include "iodev.h" #include "mapping.h" #include "dosemu_config.h" -#include "libpacket.h" +#include "pktdrvr.h" #include "ne2000.h" #include "dma.h" #include "hlt.h" @@ -91,7 +92,6 @@ #include "keyboard/keyb_server.h" #include "sig.h" #include "sound.h" -#include "ioselect.h" #ifdef X86_EMULATOR #include "cpu-emu.h" #endif @@ -102,7 +102,7 @@ static int can_leavedos; static int leavedos_code; static int leavedos_called; static pthread_mutex_t ld_mtx = PTHREAD_MUTEX_INITIALIZER; -__TLS union vm86_union vm86u; +union vm86_union vm86u; volatile __thread int fault_cnt; volatile int in_vm86; @@ -144,7 +144,7 @@ static int find_boot_drive(void) void boot(void) { unsigned buffer; - struct disk *dp = NULL; + struct disk *dp = NULL; if (config.try_freedos && config.hdiskboot == -1 && config.hdisks > 0 && !disk_is_bootable(&hdisktab[0])) { @@ -246,9 +246,6 @@ mbr: } } disk_close(); - - /* put boot drive to dl */ - _DX = dp->drive_num; } static int c_chk(void) @@ -257,6 +254,14 @@ static int c_chk(void) return !in_dpmi_pm(); } +static void c_nothr(void) +{ + /* here we can start snapshotting. + * See https://github.com/dosemu2/dosemu2/issues/1005 + */ +// error("No threads\n"); +} + /* * DANG_BEGIN_FUNCTION emulate * @@ -309,6 +314,7 @@ int main(int argc, char **argv, char * const *envp) get_time_init(); print_version(); /* log version information */ memcheck_init(); + time_setting_init(); /* get the startup time */ /* threads can be created only after signal_pre_init() so * it should be above device_init(), iodev_init(), cpu_setup() etc */ signal_pre_init(); /* initialize sig's & sig handlers */ @@ -317,9 +323,11 @@ int main(int argc, char **argv, char * const *envp) device_init(); /* priv initialization of video etc. */ extra_port_init(); /* setup ports dependent on config */ SIG_init(); /* Silly Interrupt Generator */ - LibpacketInit(); /* initialize network packet interfaces */ + pkt_priv_init(); /* initialize the packet driver interface */ + ne2000_priv_init(); mapping_init(); /* initialize mapping drivers */ + low_mem_init(); /* initialize the lower 1Meg */ if (can_do_root_stuff && !under_root_login) { g_printf("dropping root privileges\n"); @@ -327,8 +335,7 @@ int main(int argc, char **argv, char * const *envp) } priv_drop(); - map_memory_space(); /* maps all DOS memory (low, dpmi, xms...) */ - init_hardware_ram(); /* map the direct hardware ram */ + init_hardware_ram(); /* map the direct hardware ram */ map_video_bios(); /* map (really: copy) the video bios */ close_kmem(); @@ -336,6 +343,7 @@ int main(int argc, char **argv, char * const *envp) vm86_hlt_state = hlt_init(BIOS_HLT_BLK_SIZE); coopth_init(); coopth_set_ctx_checker_vm86(c_chk); + coopth_set_nothread_notifier(c_nothr); ld_tid = coopth_create("leavedos", leavedos_thr); coopth_set_ctx_handlers(ld_tid, sig_ctx_prepare, sig_ctx_restore, NULL); @@ -344,13 +352,13 @@ int main(int argc, char **argv, char * const *envp) HMA_init(); /* HMA can only be done now after mapping is initialized*/ memory_init(); /* initialize the memory contents */ - ioselect_init(); /* iodev_init() can load plugins, like SDL, that can spawn a thread. * This must be done before initializing signals, or problems ensue. * This also must be done when the signals are blocked, so after * the signal_pre_init(), which right now blocks the signals. */ iodev_init(); /* initialize devices */ init_all_DOS_tables(); /* longest init function! needs to be optimized */ + dos2tty_init(); signal_init(); /* initialize sig's & sig handlers */ if (config.exitearly) { dbug_printf("Leaving DOS before booting\n"); @@ -370,8 +378,7 @@ int main(int argc, char **argv, char * const *envp) set_kvm_memory_regions(); cpu_reset(); - if (config.cpu_vm == CPUVM_KVM) - kvm_enter(0); + can_leavedos = 1; while (!fatalerr && !config.exitearly) { @@ -444,8 +451,9 @@ void __leavedos(int code, int sig, const char *s, int num) keyb_close(); /* abandon current thread if any */ coopth_abandon(); - /* switch to RM before closing coopthreads-related stuff */ - dpmi_done0(); + /* close coopthreads-related stuff first */ + dpmi_done(); + dos2tty_done(); if (!config.exitearly) { // in exitearly case nothing to join /* try to clean up threads */ tmp = coopth_flush_vm86(); @@ -462,18 +470,13 @@ static void __leavedos_main(int code, int sig) { int i; - /* async signals must be disabled first or pthread_cancel() hangs on arm */ - signal_done(); - dpmi_done(); - /* now safe to stop io thread */ - ioselect_done(); - /* then stop device threads, which also stops any remaining vm86() uses */ - iodev_term(); #ifdef USE_MHPDBG g_printf("closing debugger pipes\n"); - /* after vm86() is no longer used, we can do this */ mhp_close(); #endif + /* async signals must be disabled after coopthreads are joined, but + * before coopth_done(). */ + signal_done(); /* now it is safe to shut down coopth. Can be done any later, if need be */ coopth_done(); dbug_printf("coopthreads stopped\n"); @@ -493,13 +496,16 @@ static void __leavedos_main(int code, int sig) * My port logic is actually stolen from kd_nosound in the kernel. * --EB 21 September 1997 */ - port_outb(0x61, port_inb(0x61)&0xFC); /* turn off any sound */ + port_safe_outb(0x61, port_safe_inb(0x61)&0xFC); /* turn off any sound */ } free(vm86_hlt_state); SIG_close(); + g_printf("calling keyboard_close\n"); + iodev_term(); + #if defined(X86_EMULATOR) /* if we are here with config.cpuemu>1 something went wrong... */ if (IS_EMU()) { @@ -531,20 +537,15 @@ static void __leavedos_main(int code, int sig) g_printf("calling close_all_printers\n"); close_all_printers(); + ioselect_done(); for (i = 0; i < exit_hndl_num; i++) exit_hndl[i].handler(); flush_log(); - if (sig < 0) - code = -sig; - else if (sig > 0) - code = sig + 128; - else - code &= 0x7f; /* We don't need to use _exit() here; this is the graceful exit path. */ - exit(code); + exit(sig ? sig + 128 : code); } void __leavedos_main_wrp(int code, int sig, const char *s, int num) diff --git a/src/base/core/int.c b/src/base/core/int.c index 212df1f..64c2cc1 100644 --- a/src/base/core/int.c +++ b/src/base/core/int.c @@ -12,14 +12,9 @@ #include #include #include -#ifdef __linux__ #include -#else -#include -#include -#endif #include -#include "Linux/magic.h" +#include #include #include #include @@ -41,10 +36,8 @@ #include "hma.h" #include "xms.h" #include "int.h" -#include "vint.h" #include "dos2linux.h" #include "video.h" -#include "clipboard.h" #include "priv.h" #include "doshelpers.h" #include "lowmem.h" @@ -187,8 +180,13 @@ static void process_master_boot_record(void) * SS:BP,DS:SI pointing to the boot partition entry within 0:600 MBR * DI = 0x7dfe */ - struct on_disk_mbr *mbr = LOWMEM(0x600); - struct on_disk_mbr *bootrec = LOWMEM(0x7c00); + struct mbr { + char code[PART_INFO_START]; + struct on_disk_partition partition[4]; + unsigned short bootmagic; + } __attribute__ ((packed)); + struct mbr *mbr = LOWMEM(0x600); + struct mbr *bootrec = LOWMEM(0x7c00); int i; unsigned offs; @@ -200,7 +198,7 @@ static void process_master_boot_record(void) } if (i >= 4) { /* aiee... no bootflags sets */ - error("no bootflag set, Leaving DOS...\n"); + p_dos_str("\n\rno bootflag set, Leaving DOS...\n\r"); leavedos(99); } LO(dx) = 0x80; /* drive C:, DOS boots only from C: */ @@ -212,13 +210,13 @@ static void process_master_boot_record(void) LWORD(eax) = 0x0201; /* read one sector */ LWORD(ebx) = 0x7c00; /* target offset, ES is 0 */ do_int_call_back(0x13); - if ((REG(eflags) & CF) || (bootrec->signature != MBR_SIG)) { + if ((REG(eflags) & CF) || (bootrec->bootmagic != 0xaa55)) { /* error while booting */ error("error on reading bootsector, Leaving DOS...\n"); leavedos(99); } - offs = 0x600 + offsetof(struct on_disk_mbr, partition) + sizeof(mbr->partition[0]) * i; + offs = 0x600 + offsetof(struct mbr, partition) + sizeof(mbr->partition[0]) * i; coopth_add_post_handler(mbr_jmp, (void *) (long) offs); } @@ -374,7 +372,7 @@ static int dos_helper(int stk_offs, int revect) LWORD(eax) = DOS_HELPER_MAGIC; LWORD(ebx) = VERSION_NUM * 0x100 + SUBLEVEL; /* major version 0.49 -> 0049 */ /* The patch level in the form n.n is a float... - * ...we let GCC at compile time translate it to 0xHHLL, HH=major, LL=minor. + * ...we let GCC at compiletime translate it to 0xHHLL, HH=major, LL=minor. * This way we avoid usage of float instructions. */ LWORD(ecx) = REVISION; @@ -393,7 +391,8 @@ static int dos_helper(int stk_offs, int revect) break; case DOS_HELPER_PRINT_STRING: /* PRINT STRING ES:DX */ - dbug_printf("DOS to EMU: \"%s\"\n", SEG_ADR((char *), es, dx)); + g_printf("DOS likes us to print a string\n"); + ds_printf("DOS to EMU: \"%s\"\n", SEG_ADR((char *), es, dx)); break; case DOS_HELPER_ADJUST_IOPERMS: /* SET IOPERMS: bx=start, cx=range, @@ -473,10 +472,6 @@ static int dos_helper(int stk_offs, int revect) p_dos_str("\n"); break; - case DOS_HELPER_PRESTROKES_START: - start_pre_strokes(); - break; - case DOS_HELPER_INSERT_INTO_KEYBUFFER: k_printf ("KBD: WARNING: outdated keyboard helper fn 6 was called!\n"); @@ -511,10 +506,6 @@ static int dos_helper(int stk_offs, int revect) config.hogthreshold = LWORD(ebx); break; - case DOS_HELPER_TEST_MODE: - config.test_mode = LO(bx); - return 1; - case DOS_HELPER_MFS_HELPER: mfs_inte6(); return 1; @@ -564,7 +555,7 @@ static int dos_helper(int stk_offs, int revect) case DOS_HELPER_GARROT_HELPER: /* Mouse garrot helper */ if (!LWORD(ebx)) /* Wait sub-function requested */ - idle_enable(50, 0, "mouse_garrot"); + idle_enable(0, 50, 0, "mouse_garrot"); else { /* Get Hogthreshold value sub-function */ LWORD(ebx) = config.hogthreshold; LWORD(eax) = config.hogthreshold; @@ -673,7 +664,10 @@ static int dos_helper(int stk_offs, int revect) case DOS_HELPER_GET_CPU_SPEED: { - REG(eax) = 0; + if (config.rdtsc) + REG(eax) = (LLF_US << 16) / config.cpu_spd; + else + REG(eax) = 0; break; } @@ -715,12 +709,10 @@ static int dos_helper(int stk_offs, int revect) buf == NULL ? 0 : (SEGOFF2LINEAR(_ES, _DX) & 0xffff); break; } - case DOS_HELPER_GETPID: { - pid_t pid = getpid(); - LWORD(eax) = pid; - LWORD(ebx) = pid >> 16; + case DOS_HELPER_GETPID: + LWORD(eax) = getpid(); + LWORD(ebx) = getppid(); break; - } case DOS_HELPER_CHDIR: LWORD(eax) = chdir(SEG_ADR((char *), es, dx)); @@ -800,7 +792,7 @@ static int int15(void) case 0x10: /* TopView/DESQview */ switch (LO(ax)) { case 0x00:{ /* giveup timeslice */ - idle_enable(100, 0, "topview"); + idle_enable(0, 100, 0, "topview"); break; } } @@ -895,9 +887,6 @@ static int int15(void) unsigned src_addr, dst_addr; unsigned src_limit, dst_limit; unsigned int length; - void *s, *d; - unsigned int old_a20 = a20; - lp = SEG_ADR((unsigned int *), es, si); lp += 4; src_addr = (*lp >> 16) & 0x0000FFFF; @@ -918,52 +907,19 @@ static int int15(void) src_addr, dst_addr, length); if (src_limit < length - 1 || dst_limit < length - 1 || - src_addr + length > LOWMEM_SIZE + EXTMEM_SIZE || - dst_addr + length > LOWMEM_SIZE + EXTMEM_SIZE) { + src_addr + length > LOWMEM_SIZE + HMASIZE + EXTMEM_SIZE || + dst_addr + length > LOWMEM_SIZE + HMASIZE + EXTMEM_SIZE) { x_printf("block move failed\n"); LWORD(eax) = 0x0200; CARRY; - break; - } - /* Have to enable a20 before translating addresses */ - if (!a20) - set_a20(1); - while (length) { - /* avoid crossing page boundaries */ - int s_al = PAGE_ALIGN(src_addr) - src_addr; - int d_al = PAGE_ALIGN(dst_addr) - dst_addr; - int todo; - - if (!s_al) - s_al += PAGE_SIZE; - if (!d_al) - d_al += PAGE_SIZE; - todo = _min(s_al, d_al); - todo = _min(todo, length); - x_printf("int 15: copy subblock: src=%#x dst=%#x len=%#x\n", - src_addr, dst_addr, todo); - s = physaddr_to_unixaddr(src_addr); - if (s == MAP_FAILED) { - error("error mapping %x to addr\n", src_addr); - break; - } - d = physaddr_to_unixaddr(dst_addr); - if (d == MAP_FAILED) { - error("error mapping %x to addr\n", dst_addr); - break; - } - e_invalidate_pa(dst_addr, todo); - memcpy(d, s, todo); - src_addr += todo; - dst_addr += todo; - length -= todo; - } - if (old_a20 != a20) - set_a20(old_a20); - if (length) { - LWORD(eax) = 0x0200; - CARRY; } else { + unsigned int old_a20 = a20; + /* Have to enable a20 before moving */ + if (!a20) + set_a20(1); + extmem_copy(dst_addr, src_addr, length); + if (old_a20 != a20) + set_a20(old_a20); LWORD(eax) = 0; NOCARRY; } @@ -971,7 +927,10 @@ static int int15(void) } case 0x88: - LWORD(eax) = EXTMEM_SIZE >> 10; + if (xms_intdrv()) + LWORD(eax) = 0; + else + LWORD(eax) = (EXTMEM_SIZE + HMASIZE) >> 10; NOCARRY; break; @@ -1053,7 +1012,7 @@ static int int15(void) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - #endif if (LO(ax) == 1) { - Bit32u mem = EXTMEM_SIZE >> 10; + Bit32u mem = (EXTMEM_SIZE + HMASIZE) >> 10; if (mem < 0x3c00) { LWORD(eax) = mem; LWORD(ebx) = 0; @@ -1124,8 +1083,6 @@ static void set_ticks(unsigned long new_ticks) static int int1a(void) { - int_yield(); - switch (HI(ax)) { /* @@ -1149,7 +1106,7 @@ increments AL so we *don't* lose a day if two consecutive midnights pass. case 0: /* read time counter */ { int day_rollover; - idle_enable2(50, 50, 0, "int1a:0"); + idle(50, 50, 0, "int1a:0"); if (config.timemode == TM_LINUX) { /* Set BIOS area flags to LINUX time computed values always */ last_ticks = get_linux_ticks(0, &day_rollover); @@ -1461,7 +1418,7 @@ static int msdos(void) #endif case 0x2C:{ /* get time & date */ - idle_enable(100, 0, "dos_time"); + idle(2, 100, 0, "dos_time"); return 0; } @@ -1607,10 +1564,10 @@ static void do_ret_from_int(int inum, const char *pfx) ssp = SEGOFF2LINEAR(SREG(ss), 0); sp = LWORD(esp); + _SP += 6; _IP = popw(ssp, sp); _CS = popw(ssp, sp); flgs = popw(ssp, sp); - _SP += 6; if (flgs & IF) set_IF(); else @@ -1721,11 +1678,9 @@ static far_t int##x##_unrevect(uint16_t seg, uint16_t offs) \ return ret; \ int##x##_hooked = 1; \ di_printf("int_rvc: unrevect 0x%s\n", #x); \ - if (test_bit(0x##x, &vm86s.int_revectored)) { \ - if (!mhp_revectored(0x##x)) \ - clear_bit(0x##x, &vm86s.int_revectored); \ - else \ - mhp_adjust_revectored(0x##x); \ + if (is_revectored(0x##x, &vm86s.int_revectored)) { \ + assert(!mhp_revectored(0x##x)); \ + reset_revectored(0x##x, &vm86s.int_revectored); \ } else { \ di_printf("int_rvc: revectoring of 0x%s was not enabled\n", #x); \ } \ @@ -1740,7 +1695,7 @@ static int int##x##_unrevect_simple(void) \ return 0; \ int##x##_hooked = 1; \ di_printf("int_rvc: unrevect 0x%s\n", #x); \ - clear_bit(0x##x, &vm86s.int_revectored); \ + reset_revectored(0x##x, &vm86s.int_revectored); \ int##x##_rvc_setup(); \ SETIVEC(0x##x, INT_RVC_SEG, INT_RVC_##x##_OFF); \ return 1; \ @@ -1809,7 +1764,7 @@ static void msdos_xtra(uint16_t old_ax, uint16_t old_flags) di_printf("int_rvc 0x21 call for ax=0x%04x %x\n", LWORD(eax), old_ax); CARRY; - switch (HI_BYTE(old_ax)) { + switch (HI_BYTE_d(old_ax)) { case 0x71: if (LWORD(eax) != 0x7100) break; @@ -1963,10 +1918,8 @@ static int int19(void) { int stal; coopth_leave(); - dpmi_done0(); if (clnup_handler) clnup_handler(); - clnup_handler = NULL; stal = coopth_flush_vm86(); if (stal) { error("stalled %i threads on reboot\n", stal); @@ -2070,10 +2023,8 @@ static int redir_printers(void) /* drive for -K (aka system.com) */ struct drive_syscom { char *path; + int drv_num; int mfs_idx; -#define SCUSERS 5 - uint8_t *drv_num[SCUSERS]; - int num_scusers; }; static struct drive_syscom syscomdrv; /* drive for -d */ @@ -2095,18 +2046,14 @@ static int num_x_drives; #define REDIR_F_GRP 1 -void add_syscom_drive(char *path, uint8_t *user) +int *add_syscom_drive(char *path) { - assert(syscomdrv.num_scusers == 0); - syscomdrv.path = expand_path(path); - syscomdrv.mfs_idx = mfs_define_drive(syscomdrv.path); - syscomdrv.drv_num[0] = user; -} - -void add_syscom_user(uint8_t *user) -{ - assert(1 + syscomdrv.num_scusers < SCUSERS); - syscomdrv.drv_num[1 + syscomdrv.num_scusers++] = user; + struct drive_syscom *drv = &syscomdrv; + assert(drv->drv_num == 0); + drv->path = expand_path(path); + drv->drv_num = -1; + drv->mfs_idx = mfs_define_drive(drv->path); + return &drv->drv_num; } int add_extra_drive(char *path, int ro, int cd, int grp) @@ -2463,9 +2410,7 @@ static int redir_one_drive(const char *path, int ro, int cdrom, int prm, int drv = find_free_drive(); if (drv < 0) { error("no free drives\n"); - if (get_lastdrive() < 7) - error("@Set LASTDRIVE=Z in your fdconfig.sys\n"); - else if (config.boot_dos == FATFS_FD_D) { + if (config.boot_dos == FATFS_FD_D) { error("@-d/-K is not supported with this freedos version\n"); leavedos(26); } @@ -2475,9 +2420,7 @@ static int redir_one_drive(const char *path, int ro, int cdrom, int prm, grp ? REDIR_F_GRP : 0); if (ret != CC_SUCCESS) { error("INT21: redirecting %s failed (err = %d)\n", path, ret); - if (get_lastdrive() < 7) - error("@Set LASTDRIVE=Z in your fdconfig.sys\n"); - else if (config.boot_dos == FATFS_FD_D && (ret == 0x55 /* duplicate redirect */ + if (config.boot_dos == FATFS_FD_D && (ret == 0x55 /* duplicate redirect */ || ret == 0xf /* invalid drive */)) { error("-d/-K is not supported with this freedos version\n"); leavedos(26); @@ -2652,15 +2595,13 @@ static void redir_extra_drives(void) { int i, ret, drv; - if (syscomdrv.path) { + if (syscomdrv.drv_num != 0) { drv = redir_one_drive(syscomdrv.path, 0, 0, 1, 0, syscomdrv.mfs_idx); if (drv < 0) { leavedos(26); return; } - /* notify all users about this drive */ - for (i = 0; i < 1 + syscomdrv.num_scusers; i++) - *syscomdrv.drv_num[i] = drv; + syscomdrv.drv_num = drv; } for (i = 0; i < num_x_drives; i++) { @@ -2841,10 +2782,6 @@ void dos_post_boot_reset(void) if (clnup_handler) clnup_handler(); clnup_handler = NULL; - syscomdrv.num_scusers = 0; -#ifdef USE_MHPDBG - mhp_reset_hma(); -#endif } static void dos_post_boot(void) @@ -2852,9 +2789,6 @@ static void dos_post_boot(void) if (!post_boot) { post_boot = 1; post_boot_unrevect(); - /* call vint_setup() again to avoid DOS STACKS hooks, see - * https://github.com/dosemu2/dosemu2/issues/1607 */ - vint_setup(); if (config.force_redir) { if (!redir_state) { redir_it(); @@ -2863,22 +2797,13 @@ static void dos_post_boot(void) enable_redirect(); } } -#ifdef USE_MHPDBG - /* - * Let's set up the hma start address for dosdebug use. There's no - * specific reason it should be here other than it needs to be done - * sometime after DOS has started. - */ - mhp_init_hma(); -#endif - start_pre_strokes(); } } /* KEYBOARD BUSY LOOP */ static int int28(void) { - idle_enable(50, 0, "int28"); + idle_enable(0, 50, 0, "int28"); return 1; } @@ -2938,7 +2863,7 @@ done: static unsigned short do_get_psp(int parent) { - /* don't care about parent, as command.com is primary */ + /* dont care about parent, as command.com is primary */ return sda_cur_psp(sda); } @@ -2957,9 +2882,6 @@ static void do_run_cmd(struct lowstring *str, struct ae00_tab *cmd) _AL = 0xff; } -/* size not propagated through DOS API, so we cache it */ -static int clipb_size; - static int int2f(int stk_offs, int revect) { reset_idle(0); @@ -3021,16 +2943,14 @@ hint_done: memcpy(cmdname, str->s, len); cmdname[len] = 0; ptr = cmdname + strspn(cmdname, " \t"); + if (!ptr[0]) + return 0; tmp_ptr = ptr; while (*tmp_ptr) { /* Check whether the name is valid */ if (iscntrlDOS(*tmp_ptr++)) return 0; } strcpy(title_current, title_hint); - if (!ptr[0]) { - change_window_title(title_current); - return 0; - } snprintf(appname, sizeof(appname), "%s ( %s )", title_current, strlowerDOS(ptr)); change_window_title(appname); @@ -3092,7 +3012,7 @@ hint_done: break; case 0x80: /* give up time slice */ - idle_enable(100, 0, "int2f_idle_magic"); + idle_enable(0, 100, 0, "int2f_idle_magic"); if (config.hogthreshold) { LO(ax) = 0; return 1; @@ -3101,11 +3021,8 @@ hint_done: case 0x83: - if (dpmi_active() && win3x_mode != INACTIVE) { - LWORD(ebx) = 1; /* W95: number of virtual machine */ - return 1; - } - break; + if (dpmi_active() && win3x_mode != INACTIVE) + LWORD(ebx) = 0; /* W95: number of virtual machine */ case 0x81: /* W95: enter critical section */ if (dpmi_active() && win3x_mode != INACTIVE) { D_printf("WIN: enter critical section\n"); @@ -3141,81 +3058,13 @@ hint_done: } break; - case 0x17: /* MS Windows WINOLDAP functions */ - switch (LO(ax)) { - case 0x00: /* IDENTIFY WinOldAp VERSION */ - LO(ax) = 0x01; // major version - HI(ax) = 0x00; // minor version - v_printf("Check for WinOldAp\n"); // Installed == (AX != 1700) - return 1; - case 0x01: /* OPEN CLIPBOARD */ - LWORD(eax) = 1; // success (AX != 0) - v_printf("Open clipboard\n"); - return 1; - case 0x02: /* EMPTY CLIPBOARD */ - v_printf("Clear clipboard\n"); - if (Clipboard && Clipboard->clear) - LWORD(eax) = Clipboard->clear(); - else - LWORD(eax) = 0; - return 1; - case 0x03: /* WRITE CLIPBOARD */ - v_printf("Write clipboard\n"); - if (Clipboard && Clipboard->write) { - char *pbuf = MK_FP32(SREG(es), LWORD(ebx)); - unsigned int bsize = LWORD(esi) << 16 | LWORD(ecx); - LWORD(eax) = Clipboard->write(LWORD(edx), pbuf, bsize); - } else - LWORD(eax) = 0; - return 1; - case 0x04: /* GET CLIPBOARD DATA SIZE */ - v_printf("Get clipboard size\n"); - if (Clipboard && Clipboard->getsize) { - clipb_size = Clipboard->getsize(LWORD(edx)); - LWORD(edx) = (clipb_size >> 16); - LWORD(eax) = (clipb_size & 0xffff); - } else { - LWORD(edx) = LWORD(eax) = 0; - } - return 1; - case 0x05: /* GET CLIPBOARD DATA */ - v_printf("Get clipboard data\n"); - if (Clipboard && Clipboard->getdata) { - char *pbuf = MK_FP32(SREG(es), LWORD(ebx)); - LWORD(eax) = Clipboard->getdata(LWORD(edx), pbuf, - clipb_size); - } else - LWORD(eax) = 0; - return 1; - case 0x08: /* CLOSE CLIPBOARD */ - LWORD(eax) = 1; // success (AX != 0) - v_printf("Close clipboard\n"); - return 1; - case 0x09: /* COMPACT CLIPBOARD */ - // SI:CX = desired size in bytes - // DX:AX = number of bytes in largest block of free memory - LWORD(edx) = 0; - LWORD(eax) = 0x1000; // 4K should indicate enough room - v_printf("Compact clipboard\n"); - return 1; - case 0x0a: /* GET DEVICE CAPABILITIES */ - LWORD(eax) = 0; // Not sure if we should "support" this - // function, but doesn't seem possible to - // indicate otherwise. - v_printf("Get device capabilities (0x%02x)\n", LWORD(edx)); - return 1; - default: - v_printf("BAD WinOldAp func int 2f/ax=0x%04x\n", LWORD(eax)); - } - break; - case INT2F_XMS_MAGIC: if (!xms_intdrv()) break; switch (LO(ax)) { case 0: /* check for XMS */ x_printf("Check for XMS\n"); - LWORD(eax) = xms_install_check(); + LO(ax) = 0x80; break; case 0x10: x_printf("Get XMSControl address\n"); @@ -3413,7 +3262,7 @@ void do_int(int i) } #endif - if (test_bit(i, &vm86s.int_revectored) && !mhp_revectored(i)) { + if (is_revectored(i, &vm86s.int_revectored) && !mhp_revectored(i)) { assert(int_handlers[i].interrupt_function[REVECT]); if (debug_level('#') > 2) debug_int("Do rvc", i); @@ -3526,10 +3375,10 @@ void fake_iret(void) ssp = SEGOFF2LINEAR(SREG(ss), 0); sp = LWORD(esp); + _SP += 6; _IP = popw(ssp, sp); _CS = popw(ssp, sp); set_FLAGS(popw(ssp, sp)); - _SP += 6; #ifdef USE_MHPDBG if (mhpdbg.active && old_tf) set_TF(); @@ -3548,12 +3397,6 @@ void do_eoi2_iret(void) _IP = EOI2_OFF; } -void do_iret(void) -{ - _CS = BIOSSEG; - _IP = IRET_OFF; -} - static void rvc_int_pre(int tid, void *arg, void *arg2) { coopth_push_user_data(tid, (void *) (long) get_FLAGS(REG(eflags))); @@ -3592,14 +3435,6 @@ static int _int##n##_(int stk_offs, int revect) \ return int##n(); \ } -/* Needed for int16, which can clash with type name. - * Under clang, both _int16 and __int16 are also occupied. */ -#define INT_WRP2(n) \ -static int _int##n##_(int stk_offs, int revect) \ -{ \ - return ___int##n(); \ -} - INT_WRP(05) INT_WRP(10) INT_WRP(11) @@ -3607,7 +3442,7 @@ INT_WRP(12) INT_WRP(13) INT_WRP(14) INT_WRP(15) -INT_WRP2(16) +INT_WRP(16) INT_WRP(17) INT_WRP(18) INT_WRP(19) @@ -3635,7 +3470,7 @@ static void revect_setup(void) if (config.force_revect != 0) { for (i = 0; i < 0x100; i++) { if (int_handlers[i].interrupt_function[REVECT]) - set_bit(i, &vm86s.int_revectored); + set_revectored(i, &vm86s.int_revectored); } } @@ -3736,15 +3571,10 @@ void setup_interrupts(void) void int_try_disable_revect(void) { - int i; - if (config.force_revect != -1) return; config.force_revect = 0; - for (i = 0; i < 256; i++) { - if (test_bit(i, &vm86s.int_revectored) && !mhp_revectored(i)) - clear_bit(i, &vm86s.int_revectored); - } + memset(&vm86s.int_revectored, 0x00, sizeof(vm86s.int_revectored)); } void update_xtitle(void) @@ -3893,7 +3723,7 @@ far_t get_int_vector(int vec) { far_t addr; - if (test_bit(vec, &vm86s.int_revectored)) { + if (is_revectored(vec, &vm86s.int_revectored)) { addr.segment = INT_RVC_SEG; switch (vec) { case 0x21: diff --git a/src/base/core/lowmem.c b/src/base/core/lowmem.c index 73d031f..6baa8fb 100644 --- a/src/base/core/lowmem.c +++ b/src/base/core/lowmem.c @@ -33,7 +33,7 @@ static smpool mp; unsigned char *dosemu_lmheap_base; static void *rm_stack; -#define RM_STACK_SIZE 0x200 +#define RM_STACK_SIZE 0x400 static void do_sm_error(int prio, const char *fmt, ...) { @@ -49,11 +49,11 @@ static void do_sm_error(int prio, const char *fmt, ...) dbug_printf("%s\n", buf); } -int lowmem_init(void) +int lowmem_init() { dosemu_lmheap_base = MK_FP32(DOSEMU_LMHEAP_SEG, DOSEMU_LMHEAP_OFF); + smregister_default_error_notifier(do_sm_error); sminit(&mp, dosemu_lmheap_base, DOSEMU_LMHEAP_SIZE); - smregister_error_notifier(&mp, do_sm_error); return 1; } @@ -152,27 +152,6 @@ void rm_stack_enter(void) void rm_stack_leave(void) { - int old_tf = isset_TF(); put_rm_stack(NULL); REGS = rm_regs_stack[in_rm_stack]; - if (old_tf) - set_TF(); -} - -#define LMHEAP_OFF 0xa000 -#define LMHEAP_SIZE 0x4000 - -static uint16_t lmheap_add(void) -{ - return (config.dos_up == 2 ? FDPP_LMHEAP_ADD : 0); -} - -uint16_t lmheap_off(void) -{ - return LMHEAP_OFF + lmheap_add(); -} - -uint16_t lmheap_size(void) -{ - return LMHEAP_SIZE - lmheap_add(); } diff --git a/src/base/core/ports.c b/src/base/core/ports.c index f7054c2..cd50966 100644 --- a/src/base/core/ports.c +++ b/src/base/core/ports.c @@ -29,7 +29,7 @@ #include #include #include -#ifdef HAVE_SYS_IO_H +#ifdef __linux__ #include #endif #include @@ -61,6 +61,8 @@ static pid_t portserver_pid = 0; static unsigned char port_handles; /* number of io_handler's */ +static const char *irq_handler_name[EMU_MAX_IRQS]; + int in_crit_section = 0; static const char *crit_sect_caller; @@ -189,7 +191,7 @@ static void log_port_write_d(ioport_t port, Bit32u w) Bit8u port_inb(ioport_t port) { Bit8u res; - res = EMU_HANDLER(port).read_portb(port, EMU_HANDLER(port).arg); + res = EMU_HANDLER(port).read_portb(port); return LOG_PORT_READ(port, res); } @@ -203,7 +205,7 @@ Bit8u port_inb(ioport_t port) void port_outb(ioport_t port, Bit8u byte) { LOG_PORT_WRITE(port, byte); - EMU_HANDLER(port).write_portb(port, byte, EMU_HANDLER(port).arg); + EMU_HANDLER(port).write_portb(port,byte); } /* @@ -219,10 +221,8 @@ Bit16u port_inw(ioport_t port) { Bit16u res; - if (EMU_HANDLER(port).read_portw != NULL && - EMU_HANDLER(port).read_portb == EMU_HANDLER(port + 1).read_portb - ) { - res = EMU_HANDLER(port).read_portw(port, EMU_HANDLER(port).arg); + if (EMU_HANDLER(port).read_portw != NULL) { + res = EMU_HANDLER(port).read_portw(port); return LOG_PORT_READ_W(port, res); } else { @@ -240,11 +240,9 @@ Bit16u port_inw(ioport_t port) */ void port_outw(ioport_t port, Bit16u word) { - if (EMU_HANDLER(port).write_portw != NULL && - EMU_HANDLER(port).write_portb == EMU_HANDLER(port + 1).write_portb - ) { + if (EMU_HANDLER(port).write_portw != NULL) { LOG_PORT_WRITE_W(port, word); - EMU_HANDLER(port).write_portw(port, word, EMU_HANDLER(port).arg); + EMU_HANDLER(port).write_portw(port, word); } else { port_outb(port, word & 0xff); @@ -264,12 +262,8 @@ Bit32u port_ind(ioport_t port) { Bit32u res; - if (EMU_HANDLER(port).read_portd != NULL && - EMU_HANDLER(port).read_portb == EMU_HANDLER(port + 1).read_portb && - EMU_HANDLER(port).read_portb == EMU_HANDLER(port + 2).read_portb && - EMU_HANDLER(port).read_portb == EMU_HANDLER(port + 3).read_portb - ) { - res = EMU_HANDLER(port).read_portd(port, EMU_HANDLER(port).arg); + if (EMU_HANDLER(port).read_portd != NULL) { + res = EMU_HANDLER(port).read_portd(port); } else { res = (Bit32u) port_inw(port) | (((Bit32u) port_inw(port + 2)) << 16); @@ -280,12 +274,8 @@ Bit32u port_ind(ioport_t port) void port_outd(ioport_t port, Bit32u dword) { LOG_PORT_WRITE_D(port, dword); - if (EMU_HANDLER(port).write_portd != NULL && - EMU_HANDLER(port).write_portb == EMU_HANDLER(port + 1).write_portb && - EMU_HANDLER(port).write_portb == EMU_HANDLER(port + 2).write_portb && - EMU_HANDLER(port).write_portb == EMU_HANDLER(port + 3).write_portb - ) { - EMU_HANDLER(port).write_portd(port, dword, EMU_HANDLER(port).arg); + if (EMU_HANDLER(port).write_portd != NULL) { + EMU_HANDLER(port).write_portd(port, dword); } else { port_outw(port, dword & 0xffff); @@ -313,7 +303,7 @@ static void check_crit_section(ioport_t port, const char *function) } } -static Bit8u port_not_avail_inb(ioport_t port, void *arg) +static Bit8u port_not_avail_inb(ioport_t port) { /* it is a fact of (hardware) life that unused locations return all (or almost all) the bits at 1; some software can try to detect a @@ -330,33 +320,33 @@ static Bit8u port_not_avail_inb(ioport_t port, void *arg) return 0xff; } -static void port_not_avail_outb(ioport_t port, Bit8u byte, void *arg) +static void port_not_avail_outb(ioport_t port, Bit8u byte) { check_crit_section(port, "outb"); if (debug_level('i')) pna_emsg(port,'b',"write"); } -static Bit16u port_not_avail_inw(ioport_t port, void *arg) +static Bit16u port_not_avail_inw(ioport_t port) { if (debug_level('i')) pna_emsg(port,'w',"read"); // idle(0, 50, 0, "inw"); return 0xffff; } -static void port_not_avail_outw(ioport_t port, Bit16u value, void *arg) +static void port_not_avail_outw(ioport_t port, Bit16u value) { check_crit_section(port, "outw"); if (debug_level('i')) pna_emsg(port,'w',"write"); } -static Bit32u port_not_avail_ind(ioport_t port, void *arg) +static Bit32u port_not_avail_ind(ioport_t port) { if (debug_level('i')) pna_emsg(port,'d',"read"); // idle(0, 50, 0, "ind"); return 0xffffffff; } -static void port_not_avail_outd(ioport_t port, Bit32u value, void *arg) +static void port_not_avail_outd(ioport_t port, Bit32u value) { check_crit_section(port, "outd"); if (debug_level('i')) pna_emsg(port,'d',"write"); @@ -386,7 +376,7 @@ Bit8u std_port_inb(ioport_t port) } if (!portserver_pid) { error ("std_port_inb(0x%X): port server unavailable\n", port); - return port_not_avail_inb (port, NULL); + return port_not_avail_inb (port); } pr.port = port; pr.type = TYPE_INB; @@ -395,11 +385,6 @@ Bit8u std_port_inb(ioport_t port) return pr.word; } -static Bit8u std_port_inb_h(ioport_t port, void *arg) -{ - return std_port_inb(port); -} - void std_port_outb(ioport_t port, Bit8u byte) { struct portreq pr; @@ -411,7 +396,7 @@ void std_port_outb(ioport_t port, Bit8u byte) if (!portserver_pid) { error ("std_port_outb(0x%X,0x%X): port server unavailable\n", port, byte); - port_not_avail_outb (port, byte, NULL); + port_not_avail_outb (port, byte); return; } pr.word = byte; @@ -421,23 +406,16 @@ void std_port_outb(ioport_t port, Bit8u byte) read(port_fd_in[0], &pr, sizeof(pr)); } -static void std_port_outb_h(ioport_t port, Bit8u byte, void *arg) -{ - std_port_outb(port, byte); -} - Bit16u std_port_inw(ioport_t port) { struct portreq pr; - if (current_iopl == 3 || (test_bit(port, emu_io_bitmap) + - test_bit(port + 1, emu_io_bitmap) - == 2)) { + if (current_iopl == 3 || test_bit(port, emu_io_bitmap)) { return port_real_inw(port); } if (!portserver_pid) { error ("std_port_inw(0x%X): port server unavailable\n", port); - return port_not_avail_inw (port, NULL); + return port_not_avail_inw (port); } pr.port = port; pr.type = TYPE_INW; @@ -446,25 +424,18 @@ Bit16u std_port_inw(ioport_t port) return pr.word; } -static Bit16u std_port_inw_h(ioport_t port, void *arg) -{ - return std_port_inw(port); -} - void std_port_outw(ioport_t port, Bit16u word) { struct portreq pr; - if (current_iopl == 3 || (test_bit(port, emu_io_bitmap) + - test_bit(port + 1, emu_io_bitmap) - == 2)) { + if (current_iopl == 3 || test_bit(port, emu_io_bitmap)) { port_real_outw(port, word); return; } if (!portserver_pid) { error ("std_port_outw(0x%X,0x%X): port server unavailable\n", port, word); - port_not_avail_outw (port, word, NULL); + port_not_avail_outw (port, word); return; } pr.word = word; @@ -474,25 +445,16 @@ void std_port_outw(ioport_t port, Bit16u word) read(port_fd_in[0], &pr, sizeof(pr)); } -static void std_port_outw_h(ioport_t port, Bit16u word, void *arg) -{ - std_port_outw(port, word); -} - Bit32u std_port_ind(ioport_t port) { struct portreq pr; - if (current_iopl == 3 || (test_bit(port, emu_io_bitmap) + - test_bit(port + 1, emu_io_bitmap) + - test_bit(port + 2, emu_io_bitmap) + - test_bit(port + 3, emu_io_bitmap) - == 4)) { + if (current_iopl == 3 || test_bit(port, emu_io_bitmap)) { return port_real_ind(port); } if (!portserver_pid) { error ("std_port_ind(0x%X): port server unavailable\n", port); - return port_not_avail_ind (port, NULL); + return port_not_avail_ind (port); } pr.port = port; pr.type = TYPE_IND; @@ -501,27 +463,18 @@ Bit32u std_port_ind(ioport_t port) return pr.word; } -static Bit32u std_port_ind_h(ioport_t port, void *arg) -{ - return std_port_ind(port); -} - static int do_port_outd(ioport_t port, Bit32u dword, int pci) { struct portreq pr; - if (current_iopl == 3 || (test_bit(port, emu_io_bitmap) + - test_bit(port + 1, emu_io_bitmap) + - test_bit(port + 2, emu_io_bitmap) + - test_bit(port + 3, emu_io_bitmap) - == 4)) { + if (current_iopl == 3 || test_bit(port, emu_io_bitmap)) { port_real_outd(port, dword); return 0; } if (!portserver_pid) { error ("std_port_outd(0x%X,0x%X): port server unavailable\n", port, dword); - port_not_avail_outd (port, dword, NULL); + port_not_avail_outd (port, dword); return 0; } pr.word = dword; @@ -538,11 +491,6 @@ void std_port_outd(ioport_t port, Bit32u dword) read(port_fd_in[0], &pr, sizeof(pr)); } -static void std_port_outd_h(ioport_t port, Bit32u dword, void *arg) -{ - std_port_outd(port, dword); -} - void pci_port_outd(ioport_t port, Bit32u dword) { do_port_outd(port, dword, 1); @@ -568,9 +516,17 @@ int port_rep_inb(ioport_t port, Bit8u *base, int df, Bit32u count) if (count==0) return 0; i_printf("Doing REP insb(%#x) %d bytes at %p, DF %d\n", port, count, base, df); - while (count--) { - *dest = port_inb(port); + if (EMU_HANDLER(port).read_portb == std_port_inb) { + while (count--) { + *dest = std_port_inb(port); + dest += incr; + } + } + else { + while (count--) { + *dest = EMU_HANDLER(port).read_portb(port); dest += incr; + } } if (debug_level('T')) { dest = base; @@ -591,9 +547,17 @@ int port_rep_outb(ioport_t port, Bit8u *base, int df, Bit32u count) if (count==0) return 0; i_printf("Doing REP outsb(%#x) %d bytes at %p, DF %d\n", port, count, base, df); - while (count--) { - port_outb(port, *dest); + if (EMU_HANDLER(port).write_portb == std_port_outb) { + while (count--) { + std_port_outb(port, *dest); + dest += incr; + } + } + else { + while (count--) { + EMU_HANDLER(port).write_portb(port, *dest); dest += incr; + } } if (debug_level('T')) { dest = base; @@ -614,17 +578,23 @@ int port_rep_inw(ioport_t port, Bit16u *base, int df, Bit32u count) if (count==0) return 0; i_printf("Doing REP insw(%#x) %d words at %p, DF %d\n", port, count, base, df); - if (EMU_HANDLER(port).read_portw == NULL) { + if (EMU_HANDLER(port).read_portw == std_port_inw) { + while (count--) { + *dest = std_port_inw(port); + dest += incr; + } + } + else if (EMU_HANDLER(port).read_portw == NULL) { Bit16u res; while (count--) { - res = port_inb(port); - *dest = ((Bit16u)port_inb(port+1) <<8) | res; + res = EMU_HANDLER(port).read_portb(port); + *dest = ((Bit16u)EMU_HANDLER(port).read_portb(port+1) <<8) | res; dest += incr; } } else { while (count--) { - *dest = port_inw(port); + *dest = EMU_HANDLER(port).read_portw(port); dest += incr; } } @@ -647,17 +617,23 @@ int port_rep_outw(ioport_t port, Bit16u *base, int df, Bit32u count) if (count==0) return 0; i_printf("Doing REP outsw(%#x) %d words at %p, DF %d\n", port, count, base, df); - if (EMU_HANDLER(port).write_portw == NULL) { + if (EMU_HANDLER(port).write_portw == std_port_outw) { + while (count--) { + std_port_outw(port, *dest); + dest += incr; + } + } + else if (EMU_HANDLER(port).write_portw == NULL) { Bit16u res; while (count--) { res = *dest, dest += incr; - port_outb(port, res); - port_outb(port+1, res>>8); + EMU_HANDLER(port).write_portb(port, res); + EMU_HANDLER(port).write_portb(port+1, res>>8); } } else { while (count--) { - port_outw(port, *dest); + EMU_HANDLER(port).write_portw(port, *dest); dest += incr; } } @@ -721,7 +697,7 @@ void do_r3da_pending (void) } } -static Bit8u special_port_inb(ioport_t port, void *arg) +static Bit8u special_port_inb(ioport_t port) { Bit8u res = 0xff; @@ -740,7 +716,7 @@ static Bit8u special_port_inb(ioport_t port, void *arg) return res; } -static void special_port_outb(ioport_t port, Bit8u byte, void *arg) +static void special_port_outb(ioport_t port, Bit8u byte) { if (current_iopl == 3 || test_bit(port, emu_io_bitmap)) { port_real_outb(port, byte); @@ -762,16 +738,16 @@ static void special_port_outb(ioport_t port, Bit8u byte, void *arg) * This way we avoid extra port accesses when the program * is only looking for the sync bits, and we don't miss * the case where the read to 0x3da is used to reset the - * index/data flipflop for port 0x3c0. Further accesses to + * index/data flipflop for port 0x3c0. Futher accesses to * port 0x3c0 are handled at full speed. * * SIDOC_END_REMARK */ if (config.vga && (config.emuretrace>1)) { if (r3da_pending) { - (void)std_port_inb_h(r3da_pending, arg); + (void)std_port_inb(r3da_pending); r3da_pending = 0; - std_port_outb_h(0x3c0, byte, arg); + std_port_outb(0x3c0, byte); return; } goto defout; @@ -788,7 +764,7 @@ static void special_port_outb(ioport_t port, Bit8u byte, void *arg) } defout: - std_port_outb_h (port, byte, arg); + std_port_outb (port, byte); } /* ---------------------------------------------------------------------- */ @@ -814,6 +790,8 @@ int port_init(void) port_handler[i].write_portw = NULL; port_handler[i].read_portd = NULL; port_handler[i].write_portd = NULL; + port_handler[i].irq = EMU_NO_IRQ; + port_handler[i].fd = -1; } /* handle 0 maps to the unmapped IO device handler. Basically any @@ -831,28 +809,28 @@ int port_init(void) /* the STD handles will be in use by many devices, and their fd will always be -1 */ - port_handler[HANDLE_STD_IO].read_portb = std_port_inb_h; - port_handler[HANDLE_STD_IO].write_portb = std_port_outb_h; - port_handler[HANDLE_STD_IO].read_portw = std_port_inw_h; - port_handler[HANDLE_STD_IO].write_portw = std_port_outw_h; - port_handler[HANDLE_STD_IO].read_portd = std_port_ind_h; - port_handler[HANDLE_STD_IO].write_portd = std_port_outd_h; + port_handler[HANDLE_STD_IO].read_portb = std_port_inb; + port_handler[HANDLE_STD_IO].write_portb = std_port_outb; + port_handler[HANDLE_STD_IO].read_portw = std_port_inw; + port_handler[HANDLE_STD_IO].write_portw = std_port_outw; + port_handler[HANDLE_STD_IO].read_portd = std_port_ind; + port_handler[HANDLE_STD_IO].write_portd = std_port_outd; port_handler[HANDLE_STD_IO].handler_name = "std port io"; - port_handler[HANDLE_STD_RD].read_portb = std_port_inb_h; + port_handler[HANDLE_STD_RD].read_portb = std_port_inb; port_handler[HANDLE_STD_RD].write_portb = port_not_avail_outb; - port_handler[HANDLE_STD_RD].read_portw = std_port_inw_h; + port_handler[HANDLE_STD_RD].read_portw = std_port_inw; port_handler[HANDLE_STD_RD].write_portw = port_not_avail_outw; - port_handler[HANDLE_STD_RD].read_portd = std_port_ind_h; + port_handler[HANDLE_STD_RD].read_portd = std_port_ind; port_handler[HANDLE_STD_RD].write_portd = port_not_avail_outd; port_handler[HANDLE_STD_RD].handler_name = "std port read"; port_handler[HANDLE_STD_WR].read_portb = port_not_avail_inb; - port_handler[HANDLE_STD_WR].write_portb = std_port_outb_h; + port_handler[HANDLE_STD_WR].write_portb = std_port_outb; port_handler[HANDLE_STD_WR].read_portw = port_not_avail_inw; - port_handler[HANDLE_STD_WR].write_portw = std_port_outw_h; + port_handler[HANDLE_STD_WR].write_portw = std_port_outw; port_handler[HANDLE_STD_WR].read_portd = port_not_avail_ind; - port_handler[HANDLE_STD_WR].write_portd = std_port_outd_h; + port_handler[HANDLE_STD_WR].write_portd = std_port_outd; port_handler[HANDLE_STD_WR].handler_name = "std port write"; #if 0 port_handler[HANDLE_VID_IO].read_portb = video_port_in; @@ -863,12 +841,12 @@ int port_init(void) port_handler[HANDLE_VID_IO].write_portd = NULL; port_handler[HANDLE_VID_IO].handler_name = "video port io"; #else - port_handler[HANDLE_VID_IO].read_portb = std_port_inb_h; - port_handler[HANDLE_VID_IO].write_portb = std_port_outb_h; - port_handler[HANDLE_VID_IO].read_portw = std_port_inw_h; - port_handler[HANDLE_VID_IO].write_portw = std_port_outw_h; - port_handler[HANDLE_VID_IO].read_portd = std_port_ind_h; - port_handler[HANDLE_VID_IO].write_portd = std_port_outd_h; + port_handler[HANDLE_VID_IO].read_portb = std_port_inb; + port_handler[HANDLE_VID_IO].write_portb = std_port_outb; + port_handler[HANDLE_VID_IO].read_portw = std_port_inw; + port_handler[HANDLE_VID_IO].write_portw = std_port_outw; + port_handler[HANDLE_VID_IO].read_portd = std_port_ind; + port_handler[HANDLE_VID_IO].write_portd = std_port_outd; port_handler[HANDLE_VID_IO].handler_name = "std port io"; #endif @@ -889,13 +867,13 @@ int port_init(void) return port_handles; /* unused but useful */ } -static void portserver_exit(void *arg) +static void portserver_exit(void) { error("port server terminated, exiting\n"); leavedos(1); } -/* port server: this function runs in a separate process from the main +/* port server: this function runs in a seperate process from the main DOSEMU. This enables the main DOSEMU to drop root privileges. The server can do that as well: by setting iopl(3). Maybe this server should wrap DOSEMU rather than be forked from @@ -905,7 +883,7 @@ static void port_server(void) { sigset_t set; struct portreq pr; - _port_handler *ph, *ph1, *ph2, *ph3; + _port_handler *ph; signal(SIGINT, SIG_DFL); signal(SIGPIPE, SIG_DFL); signal(SIGHUP, SIG_DFL); @@ -926,70 +904,33 @@ static void port_server(void) if (pr.type >= TYPE_EXIT) _exit(0); ph = &EMU_HANDLER(pr.port); - ph1 = &EMU_HANDLER(pr.port + 1); - ph2 = &EMU_HANDLER(pr.port + 2); - ph3 = &EMU_HANDLER(pr.port + 3); if (pr.type == TYPE_PCI) { /* get addr and data i/o access as close to each other as possible, both to minimize possible races, and for speed */ struct portreq pr2; read(port_fd_out[0], &pr2, sizeof(pr2)); - ph->write_portd(pr.port, pr.word, ph->arg); + ph->write_portd(pr.port, pr.word); pr = pr2; } switch (pr.type) { case TYPE_INB: - pr.word = ph->read_portb(pr.port, ph->arg); + pr.word = ph->read_portb(pr.port); break; case TYPE_OUTB: - ph->write_portb(pr.port, pr.word, ph->arg); + ph->write_portb(pr.port, pr.word); break; case TYPE_INW: - if (ph->read_portb == ph1->read_portb) { - pr.word = ph->read_portw(pr.port, ph->arg); - } else { - i_printf("PORT: splitting inw(0x%x)\n", pr.port); - pr.word = ph->read_portb(pr.port, ph->arg) | - (ph1->read_portb(pr.port + 1, ph->arg) << 8); - } + pr.word = ph->read_portw(pr.port); break; case TYPE_OUTW: - if (ph->write_portb == ph1->write_portb) { - ph->write_portw(pr.port, pr.word, ph->arg); - } else { - i_printf("PORT: splitting outw(0x%x)\n", pr.port); - ph->write_portb(pr.port, pr.word, ph->arg); - ph1->write_portb(pr.port + 1, pr.word >> 8, ph->arg); - } + ph->write_portw(pr.port, pr.word); break; case TYPE_IND: - if (ph->read_portb == ph1->read_portb && - ph->read_portb == ph2->read_portb && - ph->read_portb == ph3->read_portb - ) { - pr.word = ph->read_portd(pr.port, ph->arg); - } else { - i_printf("PORT: splitting ind(0x%x)\n", pr.port); - pr.word = ph->read_portb(pr.port, ph->arg) | - (ph1->read_portb(pr.port + 1, ph->arg) << 8) | - (ph2->read_portb(pr.port + 2, ph->arg) << 16) | - (ph3->read_portb(pr.port + 3, ph->arg) << 24); - } + pr.word = ph->read_portd(pr.port); break; case TYPE_OUTD: - if (ph->write_portb == ph1->write_portb && - ph->write_portb == ph2->write_portb && - ph->write_portb == ph3->write_portb - ) { - ph->write_portd(pr.port, pr.word, ph->arg); - } else { - i_printf("PORT: splitting outd(0x%x)\n", pr.port); - ph->write_portb(pr.port, pr.word, ph->arg); - ph1->write_portb(pr.port + 1, pr.word >> 8, ph->arg); - ph2->write_portb(pr.port + 2, pr.word >> 16, ph->arg); - ph3->write_portb(pr.port + 3, pr.word >> 24, ph->arg); - } + ph->write_portd(pr.port, pr.word); break; } write(port_fd_in[1], &pr, sizeof(pr)); @@ -1047,7 +988,7 @@ int extra_port_init(void) close(port_fd_in[1]); close(port_fd_out[0]); sigchld_register_handler(portserver_pid, - portserver_exit, NULL); + portserver_exit); break; } } @@ -1070,11 +1011,21 @@ void port_exit(void) void release_ports (void) { + int i; + + for (i=0; i < port_handles; i++) { + if (port_handler[i].fd >= 2) { + close(port_handler[i].fd); +/* DANG_FIXTHIS we should free the name but we are going to exit anyway + */ +/* free(port_handler[i].handler_name); */ + } + } memset (port_handle_table, NO_HANDLE, sizeof(port_handle_table)); memset (port_andmask, 0xff, sizeof(port_andmask)); memset (port_ormask, 0, sizeof(port_ormask)); -} + } /* ---------------------------------------------------------------------- */ /* @@ -1089,6 +1040,12 @@ int port_register_handler(emu_iodev_t device, int flags) { int handle, i; + if (device.irq != EMU_NO_IRQ && device.irq >= EMU_MAX_IRQS) { + dbug_printf("PORT: IO device %s registered with IRQ=%d above %u\n", + device.handler_name, device.irq, EMU_MAX_IRQS - 1); + return 1; + } + /* first find existing handle for function or create new one */ for (handle=0; handle < port_handles; handle++) { if (!strcmp(port_handler[handle].handler_name, device.handler_name)) @@ -1102,17 +1059,34 @@ int port_register_handler(emu_iodev_t device, int flags) leavedos(77); } + if (device.irq != EMU_NO_IRQ && irq_handler_name[device.irq]) { + error("PORT: IRQ %d conflict. IO devices %s & %s\n", + device.irq, irq_handler_name[device.irq], device.handler_name); + if (device.fd) close(device.fd); + return 2; + } + if (device.irq != EMU_NO_IRQ && device.irq < EMU_MAX_IRQS) + irq_handler_name[device.irq] = device.handler_name; port_handles++; - port_handler[handle] = device; + /* * for byte and double, a NULL function means that the port * access is not available, while for word means that it will * be translated into 2 byte accesses */ - if (!device.read_portb) - port_handler[handle].read_portb = port_not_avail_inb; - if (!device.write_portb) - port_handler[handle].write_portb = port_not_avail_outb; + port_handler[handle].read_portb = + (device.read_portb? : port_not_avail_inb); + port_handler[handle].write_portb = + (device.write_portb? : port_not_avail_outb); + port_handler[handle].read_portw = device.read_portw; + port_handler[handle].write_portw = device.write_portw; + port_handler[handle].read_portd = + (device.read_portd? : port_not_avail_ind); + port_handler[handle].write_portd = + (device.write_portd? : port_not_avail_outd); + port_handler[handle].handler_name = device.handler_name; + port_handler[handle].irq = device.irq; + port_handler[handle].fd = -1; } /* change table to reflect new handler id for that address */ @@ -1121,7 +1095,7 @@ int port_register_handler(emu_iodev_t device, int flags) error("PORT: conflicting devices: %s & %s for port %#x\n", port_handler[handle].handler_name, EMU_HANDLER(i).handler_name, i); - config.exitearly = 1; + if (device.fd) close(device.fd); return 4; } port_handle_table[i] = handle; @@ -1129,9 +1103,9 @@ int port_register_handler(emu_iodev_t device, int flags) set_bit(i, portfast_map); } - i_printf("PORT: registered \"%s\" handle 0x%02x [0x%04x-0x%04x]\n", + i_printf("PORT: registered \"%s\" handle 0x%02x [0x%04x-0x%04x] fd=%d\n", port_handler[handle].handler_name, handle, device.start_addr, - device.end_addr); + device.end_addr, device.fd); if (flags & PORT_FAST) { i_printf("PORT: trying to give fast access to ports [0x%04x-0x%04x]\n", @@ -1152,10 +1126,17 @@ int port_register_handler(emu_iodev_t device, int flags) * SIDOC_END_FUNCTION */ Boolean port_allow_io(ioport_t start, Bit16u size, int permission, Bit8u ormask, - Bit8u andmask, int portspeed) + Bit8u andmask, int portspeed, char *device) { static emu_iodev_t io_device; - int usemasks = 0; + FILE *fp; + unsigned int beg, end, newbeg, newend; + size_t len; + ssize_t bytes; + char *line, *portname, lock_file[64]; + unsigned char mapped; + char *devrname; + int fd, usemasks = 0; unsigned int flags = 0; if (!can_do_root_stuff) { @@ -1173,6 +1154,117 @@ Boolean port_allow_io(ioport_t start, Bit16u size, int permission, Bit8u ormask, usemasks = 1; } + /* SIDOC_BEGIN_REMARK + * find out whether the port address request is available; + * this way, try to deny uncoordinated access + * + * If it is not listed in /proc/ioports, register them + * (we need some syscall to do so bo 960609)... + * (we have a module to do so AV 970813) + * if it is registered, we need the name of a device to open + * if we can't open it, we disallow access to that port + * SIDOC_END_REMARK + */ + if ((fp = fopen("/proc/ioports", "r")) == NULL) { + i_printf("PORT: can't open /proc/ioports\n"); + return FALSE; + } + mapped = beg = end = len = 0; + portname = line = NULL; + while ((bytes = getline(&line, &len, fp)) != -1) { + int i; + if (bytes > 0 && line[bytes-1] == '\n') + line[bytes-1] = '\0'; + if (sscanf(line, "%x-%x : %n", &newbeg, &newend, &i) < 2) + break; + if (mapped) { + /* only break if no overlap with previous line */ + if (newend > end) break; + free(portname); + mapped = 0; + } + beg = newbeg; + end = newend; + if ((start <= end) && ((start+size) > beg)) { + /* ports are besetzt, try to open the according device */ + portname = strdup(&line[i]); + mapped = 1; + } + } + fclose (fp); + + if (mapped) { + const char *name = portname ? portname : ""; + i_printf("PORT: range 0x%04x-0x%04x already registered as %s\n", + beg, end, name); + if (!strncasecmp(name,"dosemu",6)) return FALSE; + if (device==NULL || *device==0) { + i_printf ("PORT: no device specified for %s\n", name); + return FALSE; + } + free (portname); + } + + io_device.fd = -1; + if (device && *device) { + /* SIDOC_BEGIN_REMARK + * We need to check if our required port range is in use + * by some device. So we look into proc/ioports to check + * the addresses. Fine, but at this point we must supply + * a device name ourselves, and we can't check from here + * if it's the right one. The device is then open and left + * open until dosemu ends; for the rest, in the original + * code the device wasn't used, just locked, and only then + * port access was granted. + * SIDOC_END_REMARK + */ + int devperm; + + devrname=strrchr(device,'/'); + if (devrname==NULL) devrname=device; else devrname++; + sprintf(lock_file, "%s/%s%s", PATH_LOCKD, NAME_LOCKF, devrname); + + switch (permission) { + case IO_READ: devperm = O_RDONLY; + flags |= PORT_DEV_RD; + break; + case IO_WRITE: devperm = O_WRONLY; + flags |= PORT_DEV_WR; + break; + default: devperm = O_RDWR; + flags |= (PORT_DEV_RD|PORT_DEV_WR); + } + io_device.fd = open(device, devperm); + if (io_device.fd == -1) { + switch (errno) { + case EBUSY: + i_printf("PORT: Device %s busy\n", device); + return FALSE; + case EACCES: + i_printf("PORT: Device %s, access not allowed\n", device); + return FALSE; + case ENOENT: + case ENXIO: + i_printf("PORT: No such Device '%s'\n", device); + return FALSE; + default: + i_printf("PORT: Device %s error %d\n", device, errno); + return FALSE; + } + } + + fd = open(lock_file, O_RDONLY); + if (fd >= 0) { + close(fd); + i_printf("PORT: Device %s is locked\n", device); + return FALSE; + } + + i_printf("PORT: Device %s opened successfully = %d\n", device, + io_device.fd); + + } + if (permission == IO_RDWR) io_device.handler_name = "std port io"; else if (permission == IO_READ) @@ -1182,6 +1274,7 @@ Boolean port_allow_io(ioport_t start, Bit16u size, int permission, Bit8u ormask, io_device.start_addr = start; io_device.end_addr = start + size - 1; + io_device.irq = EMU_NO_IRQ; if (usemasks) { port_andmask[start] = andmask; @@ -1206,7 +1299,7 @@ Boolean port_allow_io(ioport_t start, Bit16u size, int permission, Bit8u ormask, int set_ioperm(int start, int size, int flag) { -#ifdef HAVE_SYS_IO_H +#ifdef __linux__ PRIV_SAVE_AREA int tmp; diff --git a/src/base/core/priv.c b/src/base/core/priv.c index 9888871..89cc2e7 100644 --- a/src/base/core/priv.c +++ b/src/base/core/priv.c @@ -4,7 +4,7 @@ #include #include #include -#ifdef HAVE_SYS_IO_H +#ifdef __linux__ #include #endif #include "emu.h" @@ -58,7 +58,7 @@ static int pop_priv(saved_priv_status *privs) leavedos(99); } #ifdef PRIV_TESTING - c_printf("PRIV: popping %d privs_ptr=%p\n", *privs, privs); + c_printf("PRIV: poping %d privs_ptr=%p\n", *privs, privs); #endif ret = (int)*privs; *privs = PRIV_MAGIC; @@ -138,7 +138,7 @@ int real_leave_priv_setting(saved_priv_status *privs) int priv_iopl(int pl) { -#ifdef HAVE_SYS_IO_H +#ifdef __linux__ int ret; if (PRIVS_ARE_OFF) { _priv_on(); @@ -201,16 +201,28 @@ int priv_drop(void) return 1; } +#define MAXGROUPS 20 +static gid_t *groups; +static int num_groups = 0; + + +int is_in_groups(gid_t gid) +{ + int i; + for (i=0; i5 && memcmp(line, "HOME=", 5) == 0) { + setenv("HOME", line+5, 1); + } + } + free(line); + fclose(fp); + } + free(path); + } } } } @@ -253,5 +284,28 @@ void priv_init(void) skip_priv_setting = 1; } + if ((num_groups = getgroups(0, NULL)) <= 0) { + error("priv_init(): getgroups() size returned %d!\n", num_groups); + goto error_exit; + } + + if ((groups = malloc(num_groups * sizeof(gid_t))) == NULL) { + error("priv_init(): malloc() failed!\n"); + goto error_exit; + } + + if (getgroups(num_groups, groups) == -1) { + error("priv_init(): getgroups() failed '%s'!\n", strerror(errno)); + free(groups); + goto error_exit; + } + + goto done; + +error_exit: + num_groups = 0; + groups = NULL; + +done: if (!skip_priv_setting) _priv_off(); } diff --git a/src/base/core/vint.c b/src/base/core/vint.c deleted file mode 100644 index 7bca4db..0000000 --- a/src/base/core/vint.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: virtual interrupt router (another one) - * - * Author: Stas Sergeev. - * - */ -#include -#include -#include "cpu.h" -#include "int.h" -#include "hlt.h" -#include "memory.h" -#include "port.h" -#include "chipset.h" -#include "emu.h" -#include "vint.h" - -#define VINT_MAX 2 -static int vi_used; -static uint16_t vint_hlt; - -#define ON_PIC1(n) (vih[n].orig_irq >= 8) - -struct vihandler { - void (*handler)(int, int); - void (*mask)(int, int); - uint8_t irq; - uint8_t orig_irq; - uint8_t interrupt; - int tweaked; - unsigned tw_flags; -}; -struct vihandler vih[VINT_MAX]; - -static void poll_pic0(uint8_t irq) -{ - port_outb(0x20, 0x0c); // OCW3, enter poll mode - port_outb(0x20, irq); // extension, may not work on real PIC - /* see if it worked */ - assert(pic_get_isr() & (1 << irq)); -} - -static void poll_pic1(uint8_t irq) -{ - port_outb(0x20, 0x0c); // OCW3, enter poll mode - port_outb(0x20, 2); // extension, may not work on real PIC - port_outb(0xa0, 0x0c); - port_outb(0xa0, irq - 8); - /* see if it worked */ - assert((pic_get_isr() & ((1 << irq) | 4)) == ((1 << irq) | 4)); -} - -static void full_eoi(void) -{ - port_outb(0xa0, 0x20); - port_outb(0x20, 0x20); -} - -static void do_ret(int vi_num) -{ - clear_IF(); - vih[vi_num].mask(vi_num, 0); - do_iret(); -} - -int vint_is_masked(int vi_num, uint8_t *imr) -{ - uint16_t real_imr = (imr[1] << 8) | imr[0]; - return !!(real_imr & (1 << vih[vi_num].orig_irq)); -} - -static void vint_handler(uint16_t idx, HLT_ARG(arg)) -{ - uint8_t imr[2]; - int masked; - int vi_num = idx >> 1; - - if (idx & 1) { - do_ret(vi_num); - return; - } - - imr[0] = port_inb(0x21); - imr[1] = port_inb(0xa1); - masked = vint_is_masked(vi_num, imr); - if (masked) { - h_printf("vint: masked, iret\n"); - do_eoi2_iret(); - } else { - uint8_t irq = vih[vi_num].orig_irq; - uint16_t port = (irq >= 8 ? PIC1_VECBASE_PORT : PIC0_VECBASE_PORT); - uint8_t inum = port_inb(port) + (irq & 7); - full_eoi(); - if (ON_PIC1(vi_num)) - poll_pic1(irq); - else - poll_pic0(irq); - if (vih[vi_num].tweaked) { - _IP++; // skip hlt - h_printf("vint: call to inum %x\n", inum); - real_run_int(inum); - vih[vi_num].mask(vi_num, 1); - } else { - h_printf("vint: jump to inum %x\n", inum); - jmp_to(ISEG(inum), IOFF(inum)); - } - } - - if (vih[vi_num].handler) - vih[vi_num].handler(vi_num, masked); -} - -void vint_post_irq_dpmi(int vi_num, int masked) -{ - full_eoi(); - if (!masked) { - uint8_t irq = vih[vi_num].orig_irq; - if (ON_PIC1(vi_num)) - poll_pic1(irq); - else - poll_pic0(irq); - } -} - -void vint_init(void) -{ - emu_hlt_t hlt_hdlr = HLT_INITIALIZER; - - hlt_hdlr.name = "vint"; - hlt_hdlr.func = vint_handler; - hlt_hdlr.len = VINT_MAX * 2; - vint_hlt = hlt_register_handler_vm86(hlt_hdlr); -} - -void vint_setup(void) -{ - int i; - - for (i = 0; i < VINT_MAX; i++) { - if (vih[i].interrupt) - SETIVEC(vih[i].interrupt, BIOS_HLT_BLK_SEG, vint_hlt + 2 * i); - } -} - -int vint_register(void (*ack_handler)(int, int), - void (*mask_handler)(int, int), - int irq, int orig_irq, int inum) -{ - struct vihandler *vi = &vih[vi_used]; - assert(vi_used < VINT_MAX); - vi->handler = ack_handler; - vi->mask = mask_handler; - vi->irq = irq; - vi->orig_irq = orig_irq; - vi->interrupt = inum; - return vi_used++; -} - -void vint_set_tweaked(int vi_num, int on, unsigned flags) -{ - struct vihandler *vi = &vih[vi_num]; - assert(vi_num < VINT_MAX); - vi->tweaked = on; - vi->tw_flags = flags; -} diff --git a/src/base/dev/dma/dma.c b/src/base/dev/dma/dma.c index 752f767..28c1d63 100644 --- a/src/base/dev/dma/dma.c +++ b/src/base/dev/dma/dma.c @@ -32,7 +32,6 @@ #include "utilities.h" #include "port.h" #include "timers.h" -#include "cpu-emu.h" #include "dma.h" #include "dmaregs.h" #include @@ -127,8 +126,8 @@ static void dma_update_DRQ(int dma_idx, int chan_idx) static void dma_process_channel(int dma_idx, int chan_idx) { struct dma_channel *chan = &dma[dma_idx].chans[chan_idx]; - unsigned pa = (chan->page << 16) | (chan->cur_addr.value << dma_idx); - void *addr = physaddr_to_unixaddr(pa); + void *addr = physaddr_to_unixaddr( + (chan->page << 16) | (chan->cur_addr.value << dma_idx)); /* first, do the transfer */ switch (DMA_TRANSFER_OP(chan->mode)) { @@ -136,22 +135,10 @@ static void dma_process_channel(int dma_idx, int chan_idx) q_printf("DMA: verify mode does nothing\n"); break; case WRITE: - if (addr != MAP_FAILED) { - e_invalidate_pa(pa, 1 << dma_idx); - memcpy(addr, dma_data_bus, 1 << dma_idx); - } else { - error_once0("DMA: write to unmapped address\n"); - q_printf("DMA: write to unmapped address %#x\n", pa); - } + memcpy(addr, dma_data_bus, 1 << dma_idx); break; case READ: - if (addr != MAP_FAILED) - memcpy(dma_data_bus, addr, 1 << dma_idx); - else { - error_once0("DMA: read from unmapped address\n"); - q_printf("DMA: read from unmapped address %#x\n", pa); - memset(dma_data_bus, 0xff, sizeof(dma_data_bus)); - } + memcpy(dma_data_bus, addr, 1 << dma_idx); break; case INVALID: q_printf("DMA: invalid mode does nothing\n"); @@ -257,7 +244,7 @@ int dma_pulse_DRQ(int ch, Bit8u * buf) HANDLE_##n(2, 2); \ HANDLE_##n(2, 3); \ HANDLE_##n(2, 4) -static Bit8u dma_io_read(ioport_t port, void *arg) +static Bit8u dma_io_read(ioport_t port) { Bit8u r = 0xff; switch (port) { @@ -319,7 +306,7 @@ static Bit8u dma_io_read(ioport_t port, void *arg) return r; } -static void dma_io_write(ioport_t port, Bit8u value, void *arg) +static void dma_io_write(ioport_t port, Bit8u value) { switch (port) { @@ -475,6 +462,8 @@ void dma_init(void) io_device.write_portw = NULL; io_device.read_portd = NULL; io_device.write_portd = NULL; + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; /* * XT Controller diff --git a/src/base/dev/dma/dmaregs.h b/src/base/dev/dma/dmaregs.h index cf63334..4fbd563 100644 --- a/src/base/dev/dma/dmaregs.h +++ b/src/base/dev/dma/dmaregs.h @@ -1,17 +1,7 @@ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * for details see file COPYING in the DOSEMU distribution */ #ifndef __DMAREGS_H__ diff --git a/src/base/dev/misc/8042.c b/src/base/dev/misc/8042.c index 14f82f3..c800c95 100644 --- a/src/base/dev/misc/8042.c +++ b/src/base/dev/misc/8042.c @@ -76,7 +76,7 @@ void output_byte_8042(Bit8u value) port60_ready=1; if (keyb_ctrl_command & 0x01) { /* if interrupt enabled */ k_printf("8042: scheduling IRQ1\n"); - pic_request(1); + pic_request(PIC_IRQ1); } else k_printf("8042: interrupt flag OFF!\n"); @@ -303,7 +303,7 @@ static Bit8u read_port60(void) if (kbd_disabled && last_read_valid) { r = last_read_data; if (port60_ready && (keyb_ctrl_command & 0x01)) /* if interrupt enabled */ - pic_request(1); + pic_request(PIC_IRQ1); } else { r = port60_buffer; port60_ready = 0; @@ -343,7 +343,7 @@ static Bit8u read_port60(void) } -Bit8u keyb_io_read(ioport_t port, void *arg) +Bit8u keyb_io_read(ioport_t port) { Bit8u r = 0; @@ -351,7 +351,7 @@ Bit8u keyb_io_read(ioport_t port, void *arg) case 0x60: r = read_port60(); if (!port60_ready) - pic_untrigger(1); + pic_untrigger(PIC_IRQ1); k_printf("8042: read port 0x60 read=0x%02x\n",r); break; @@ -368,7 +368,7 @@ Bit8u keyb_io_read(ioport_t port, void *arg) return r; } -void keyb_io_write(ioport_t port, Bit8u value, void *arg) +void keyb_io_write(ioport_t port, Bit8u value) { switch (port) { case 0x60: @@ -407,11 +407,14 @@ void keyb_8042_init(void) io_device.handler_name = "8042 Keyboard data"; io_device.start_addr = 0x0060; io_device.end_addr = 0x0060; + io_device.irq = 1; + io_device.fd = -1; port_register_handler(io_device, 0); io_device.handler_name = "8042 Keyboard command"; io_device.start_addr = 0x0064; io_device.end_addr = 0x0064; + io_device.irq = EMU_NO_IRQ; port_register_handler(io_device, 0); io_device.handler_name = "Keyboard controller port B"; diff --git a/src/base/dev/misc/Makefile b/src/base/dev/misc/Makefile index 4f94e40..0084e44 100644 --- a/src/base/dev/misc/Makefile +++ b/src/base/dev/misc/Makefile @@ -6,11 +6,7 @@ include $(top_builddir)/Makefile.conf # src/base/misc/timers.c -> ../dev/misc/timers.c -CFILES = cmos.c timers.c lpt.c rtc.c pci.c chipset.c 8042.c kbd.c \ - virq.c vtmr.c -ifeq ($(OS),Linux) -CFILES += joystick.c -endif +CFILES=cmos.c timers.c lpt.c rtc.c pci.c joystick.c chipset.c 8042.c kbd.c include $(REALTOPDIR)/src/Makefile.common diff --git a/src/base/dev/misc/chipset.c b/src/base/dev/misc/chipset.c index c5ff54f..a2f1ccd 100644 --- a/src/base/dev/misc/chipset.c +++ b/src/base/dev/misc/chipset.c @@ -13,7 +13,7 @@ #define CONTROL_A20GATE_MASK 2 -static Bit8u port92h_io_read(ioport_t port, void *arg) +static Bit8u port92h_io_read(ioport_t port) { Bit8u ret = 0; if (a20) @@ -21,50 +21,27 @@ static Bit8u port92h_io_read(ioport_t port, void *arg) return ret; } -static void port92h_io_write(ioport_t port, Bit8u val, void *arg) +static void port92h_io_write(ioport_t port, Bit8u val) { int enA20 = (val & CONTROL_A20GATE_MASK) ? 1 : 0; if (val & CONTROL_RESET_MASK) cpu_reset(); set_a20(enA20); } -static Bit8u picext_io_read(ioport_t port, void *arg) -{ - Bit8u val = 0xff; - - switch (port) { - case PIC0_VECBASE_PORT: - val = pic0_get_base(); - break; - case PIC1_VECBASE_PORT: - val = pic1_get_base(); - break; - } - return val; -} - void chipset_init(void) { - emu_iodev_t io_dev = {}; + emu_iodev_t io_dev; io_dev.read_portb = port92h_io_read; io_dev.write_portb = port92h_io_write; + io_dev.read_portw = NULL; + io_dev.write_portw = NULL; + io_dev.read_portd = NULL; + io_dev.write_portd = NULL; + io_dev.irq = EMU_NO_IRQ; + io_dev.fd = -1; io_dev.start_addr = 0x92; io_dev.end_addr = 0x92; io_dev.handler_name = "Chipset Control Port A"; port_register_handler(io_dev, 0); - - memset(&io_dev, 0, sizeof(io_dev)); - io_dev.read_portb = picext_io_read; - io_dev.start_addr = PIC0_EXTPORT_START; - io_dev.end_addr = PIC0_EXTPORT_START + PICx_EXT_PORTS - 1; - io_dev.handler_name = "PIC0 extensions"; - port_register_handler(io_dev, 0); - - memset(&io_dev, 0, sizeof(io_dev)); - io_dev.read_portb = picext_io_read; - io_dev.start_addr = PIC1_EXTPORT_START; - io_dev.end_addr = PIC1_EXTPORT_START + PICx_EXT_PORTS - 1; - io_dev.handler_name = "PIC1 extensions"; - port_register_handler(io_dev, 0); } diff --git a/src/base/dev/misc/cmos.c b/src/base/dev/misc/cmos.c index d0b0202..a10a3d5 100644 --- a/src/base/dev/misc/cmos.c +++ b/src/base/dev/misc/cmos.c @@ -19,7 +19,7 @@ #include "disks.h" -#define PEXTMEM_SIZE EXTMEM_SIZE +#define PEXTMEM_SIZE (EXTMEM_SIZE + HMASIZE) struct CMOS cmos; @@ -37,7 +37,7 @@ cmos_chksum(void) return sum; } -Bit8u cmos_read(ioport_t port, void *arg) +Bit8u cmos_read(ioport_t port) { unsigned char holder = 0; @@ -67,7 +67,7 @@ Bit8u cmos_read(ioport_t port, void *arg) return holder; } -void cmos_write(ioport_t port, Bit8u byte, void *arg) +void cmos_write(ioport_t port, Bit8u byte) { if (port == 0x70) cmos.address = byte & ~0xc0;/* get true address */ @@ -99,12 +99,14 @@ void cmos_init(void) io_device.handler_name = "CMOS RAM"; io_device.start_addr = 0x0070; io_device.end_addr = 0x0071; + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; port_register_handler(io_device, 0); for (i = 0; i < 64; i++) cmos.subst[i] = cmos.flag[i] = 0; - rtc_setup(); + rtc_init(); /* CMOS floppies...is this correct? */ SET_CMOS(CMOS_DISKTYPE, @@ -145,8 +147,8 @@ void cmos_init(void) SET_CMOS(CMOS_BASEMEML, config.mem_size & 0xff); /* base mem LSB */ SET_CMOS(CMOS_BASEMEMM, config.mem_size >> 8); /* base mem MSB */ - SET_CMOS(CMOS_EXTMEML, EXTMEM_SIZE & 0xff); - SET_CMOS(CMOS_EXTMEMM, EXTMEM_SIZE >> 8); + SET_CMOS(CMOS_EXTMEML, (EXTMEM_SIZE + HMASIZE) & 0xff); + SET_CMOS(CMOS_EXTMEMM, (EXTMEM_SIZE + HMASIZE) >> 8); SET_CMOS(CMOS_PEXTMEML, PEXTMEM_SIZE & 0xff); SET_CMOS(CMOS_PEXTMEMM, PEXTMEM_SIZE >> 8); diff --git a/src/base/dev/misc/joystick.c b/src/base/dev/misc/joystick.c index f04c3a8..9d83079 100644 --- a/src/base/dev/misc/joystick.c +++ b/src/base/dev/misc/joystick.c @@ -68,6 +68,7 @@ * Includes */ +#ifdef __linux__ #include "joystick.h" #include @@ -151,8 +152,8 @@ static void joy_emu_axis_set (const int joynum, const int axis, const int value) static int joy_emu_axis_conv (const int linux_val, const int invalid_val); /* port emulation */ -Bit8u joy_port_inb (ioport_t port, void *arg); -void joy_port_outb (ioport_t port, Bit8u value, void *arg); +Bit8u joy_port_inb (ioport_t port); +void joy_port_outb (ioport_t port, Bit8u value); /* @@ -537,9 +538,6 @@ void joy_init (void) else /* successfully switched device to NONBLOCKing mode... */ joy_driver_set (&joy_driver_new); } -#if defined(HAVE_PTHREAD_SETNAME_NP) && defined(__GLIBC__) - pthread_setname_np(thread [joynum], "dosemu: joy"); -#endif } #endif /* USE_PTHREADS */ } @@ -575,6 +573,8 @@ void joy_init (void) io_device.handler_name = "Joystick Port Emulation"; io_device.start_addr = 0x200; io_device.end_addr = 0x20F; + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; if (port_register_handler (io_device, 0) != 0) { @@ -597,10 +597,8 @@ void joy_uninit (void) for (joynum = 0; joynum < 2; joynum++) { #ifdef USE_PTHREADS - if (joy_driver == &joy_driver_new_threaded && thread [joynum]) { + if (joy_driver == &joy_driver_new_threaded) pthread_cancel (thread [joynum]); - pthread_join (thread [joynum], NULL); - } #endif if (joy_fd [joynum] >= 0) @@ -1178,7 +1176,7 @@ static int joy_linux_read_axis_new_threaded (const int joynum, const int axis, * whether or not you have a joystick? * * I have never seen a real BIOS set the Carry Flag on this call, even - * on a computer without a joystick -- so to mimic what happens in the + * on a computer without a joystick -- so to mimick what happens in the * real world, I just clear the Carry Flag regardless of whether the user * has a joystick or not. This could be incorrect behaviour so it may * have to be changed in the future. @@ -1205,7 +1203,7 @@ static int joy_linux_read_axis_new_threaded (const int joynum, const int axis, * * Because of this, it returns the joystick axis values with the same * range as port 0x201 BUT the range for a real BIOS varies between - * computers as it is dependent on how it reads from the port + * computers as it is dependant on how it reads from the port * (hopefully this won't cause any problems). * * DANG_END_FUNCTION @@ -1286,7 +1284,7 @@ int joy_bios_read (void) * * DANG_END_FUNCTION */ -Bit8u joy_port_inb (ioport_t port, void *arg) +Bit8u joy_port_inb (ioport_t port) { Bit8u ret = 0; int joynum; @@ -1352,7 +1350,7 @@ Bit8u joy_port_inb (ioport_t port, void *arg) return ret; } -void joy_port_outb (ioport_t port, Bit8u value, void *arg) +void joy_port_outb (ioport_t port, Bit8u value) { #ifdef JOY_PORT_DEBUG joy_port_printf ("port 0x%X: outb()\n", port); @@ -1399,3 +1397,4 @@ void joy_port_outb (ioport_t port, Bit8u value, void *arg) } /* end of joystick.c */ +#endif diff --git a/src/base/dev/misc/kbd.c b/src/base/dev/misc/kbd.c index 763f386..6f74e84 100644 --- a/src/base/dev/misc/kbd.c +++ b/src/base/dev/misc/kbd.c @@ -64,7 +64,7 @@ * one keypress or release event. [The exception are the braindead * 0xe02a / 0xe0aa shift key emulation codes the keyboard processor * 'decorates' some kinds of keyboard events, which for convenience - * are treated as separate events.] + * are treated as seperate events.] * Each queue entry holds a up to 4 bytes of raw keycodes for the * port 60h emulation, along with a 2-byte translated int16h keycode * and the shift state after this event was processed. @@ -98,7 +98,7 @@ static inline Boolean queue_full(struct keyboard_queue *q) } /* - * this has to work even if the variables are uninitialized! + * this has to work even if the variables are uninitailized! */ void clear_queue(struct keyboard_queue *q) { @@ -223,7 +223,7 @@ void int_check_queue(void) #if KBD_PIC_HACK /* HACK - extra sentinel needed, timing is not * a reliable measure under heavy loads */ - if (pic_irq_active(1)) + if (pic_irq_active(PIC_IRQ1)) return; #endif diff --git a/src/base/dev/misc/lpt.c b/src/base/dev/misc/lpt.c index 98933b0..654e924 100644 --- a/src/base/dev/misc/lpt.c +++ b/src/base/dev/misc/lpt.c @@ -20,7 +20,6 @@ #include "lpt.h" #include "utilities.h" #include "dos2linux.h" -#include "ioselect.h" /* status bits, Centronics */ #define CTS_STAT_NOIOERR LPT_STAT_NOIOERR @@ -69,7 +68,7 @@ static int get_printer(ioport_t port) return -1; } -static Bit8u printer_io_read(ioport_t port, void *arg) +static Bit8u printer_io_read(ioport_t port) { int i = get_printer(port); Bit8u val; @@ -104,7 +103,7 @@ static Bit8u printer_io_read(ioport_t port, void *arg) return val; } -static void printer_io_write(ioport_t port, Bit8u value, void *arg) +static void printer_io_write(ioport_t port, Bit8u value) { int i = get_printer(port); if (i == -1) @@ -138,7 +137,9 @@ static void printer_io_write(ioport_t port, Bit8u value, void *arg) static int dev_printer_open(int prnum) { + int um = umask(026); lpt[prnum].dev_fd = open(lpt[prnum].dev, O_WRONLY); + umask(um); if (lpt[prnum].dev_fd == -1) { error("LPT%i: error opening %s: %s\n", prnum+1, lpt[prnum].dev, strerror(errno)); @@ -148,7 +149,7 @@ static int dev_printer_open(int prnum) return 0; } -static void pipe_callback(int fd, void *arg) +static void pipe_callback(void *arg) { char buf[1024]; int num = (long)arg; @@ -157,7 +158,6 @@ static void pipe_callback(int fd, void *arg) buf[n] = 0; error("LPT%i: %s\n", num+1, buf); } - ioselect_complete(fd); } static int pipe_printer_open(int prnum) @@ -270,6 +270,8 @@ printer_init(void) io_device.read_portd = NULL; io_device.write_portd = NULL; io_device.handler_name = "Parallel printer"; + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; for (i = 0; i < NUM_PRINTERS; i++) { lpt[i].initialized = 0; diff --git a/src/base/dev/misc/pci.c b/src/base/dev/misc/pci.c index 5ccfae6..f03fd03 100644 --- a/src/base/dev/misc/pci.c +++ b/src/base/dev/misc/pci.c @@ -366,8 +366,8 @@ struct pci_funcs *pci_check_conf(void) port_real_outb(PCI_MODE2_ENABLE_REG, 0x00); port_real_outb(PCI_MODE2_FORWARD_REG, 0x00); - m = (port_inb(PCI_MODE2_ENABLE_REG) == 0x00 && - port_inb(PCI_MODE2_FORWARD_REG) == 0x00) ? &pci_cfg2 : NULL; + m = (inb(PCI_MODE2_ENABLE_REG) == 0x00 && + inb(PCI_MODE2_FORWARD_REG) == 0x00) ? &pci_cfg2 : NULL; } priv_iopl(0); @@ -376,14 +376,14 @@ struct pci_funcs *pci_check_conf(void) return NULL; } -static Bit8u pci_port_inb(ioport_t port, void *arg) +static Bit8u pci_port_inb(ioport_t port) { if (port != 0xcf9) return std_port_inb(port); return 0; } -static void pci_port_outb(ioport_t port, Bit8u byte, void *arg) +static void pci_port_outb(ioport_t port, Bit8u byte) { /* don't allow DOSEMU to reset the CPU */ if (port != 0xcf9) @@ -398,13 +398,19 @@ static void pci_port_outb(ioport_t port, Bit8u byte, void *arg) */ int pci_setup (void) { - emu_iodev_t io_device = {}; + emu_iodev_t io_device; if (config.pci) { pcibios_init(); /* register PCI ports */ io_device.read_portb = pci_port_inb; io_device.write_portb = pci_port_outb; + io_device.read_portw = std_port_inw; + io_device.write_portw = std_port_outw; + io_device.read_portd = std_port_ind; + io_device.write_portd = std_port_outd; + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; if (pciConfigType->name[0] == '1') { io_device.handler_name = "PCI Config Type 1"; @@ -522,7 +528,7 @@ static void pciemu_port_write(ioport_t port, unsigned long val, int len) Z_printf("PCIEMU: writing 0x%lx to %#x, len=%d\n",val,num,len); } -static Bit8u pciemu_port_inb(ioport_t port, void *arg) +static Bit8u pciemu_port_inb(ioport_t port) { /* 0xcf8 -- 0xcfb as bytes or words don't access sub-parts; for instance writing to 0xcf9 as a byte may reset the CPU */ @@ -533,26 +539,26 @@ static Bit8u pciemu_port_inb(ioport_t port, void *arg) return 0xff; } -static void pciemu_port_outb(ioport_t port, Bit8u byte, void *arg) +static void pciemu_port_outb(ioport_t port, Bit8u byte) { if (port >= PCI_CONF_DATA) pciemu_port_write(port, byte, 1); } -static Bit16u pciemu_port_inw(ioport_t port, void *arg) +static Bit16u pciemu_port_inw(ioport_t port) { if (port == PCI_CONF_DATA || port == PCI_CONF_DATA + 2) return pciemu_port_read(port, 2); return 0xffff; } -static void pciemu_port_outw(ioport_t port, Bit16u value, void *arg) +static void pciemu_port_outw(ioport_t port, Bit16u value) { if (port == PCI_CONF_DATA || port == PCI_CONF_DATA + 2) pciemu_port_write(port, value, 2); } -static Bit32u pciemu_port_ind(ioport_t port, void *arg) +static Bit32u pciemu_port_ind(ioport_t port) { if (port == PCI_CONF_DATA) return pciemu_port_read(port, 4); @@ -561,7 +567,7 @@ static Bit32u pciemu_port_ind(ioport_t port, void *arg) return 0xffffffff; } -static void pciemu_port_outd(ioport_t port, Bit32u value, void *arg) +static void pciemu_port_outd(ioport_t port, Bit32u value) { if (port == PCI_CONF_ADDR) current_pci_reg = value & 0x80fffffc; @@ -579,8 +585,7 @@ pciRec *pciemu_setup(unsigned long cls) Z_printf("PCI: initializing, class=%lx\n", cls); pcibios_init(); } -// pci = pcibios_find_class(cls, 0); - pci = pcibios_find_primary_vga(); // XXX + pci = pcibios_find_class(cls, 0); if (pci == NULL) { Z_printf("PCI: class %lx not found\n", cls); return pci; @@ -596,6 +601,8 @@ pciRec *pciemu_setup(unsigned long cls) io_device.write_portw = pciemu_port_outw; io_device.read_portd = pciemu_port_ind; io_device.write_portd = pciemu_port_outd; + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; io_device.handler_name = "PCI Emulated Config"; io_device.start_addr = PCI_CONF_ADDR; diff --git a/src/base/dev/misc/rtc.c b/src/base/dev/misc/rtc.c index 83a6dc1..8b56b6e 100644 --- a/src/base/dev/misc/rtc.c +++ b/src/base/dev/misc/rtc.c @@ -17,7 +17,6 @@ #include "disks.h" #include "timers.h" #include "int.h" -#include "vtmr.h" #include "iodev.h" long sys_base_ticks = 0; @@ -25,6 +24,7 @@ long usr_delta_ticks = 0; unsigned long last_ticks = 0; static unsigned long long q_ticks_m = 0; + static int rtc_get_rate(Bit8u div) { if (!div) @@ -60,11 +60,7 @@ void rtc_run(void) if (debug_level('h') > 7) h_printf("RTC: periodic IRQ, queued=%lli, added=%lli\n", (long long)q_ticks_m, (long long)ticks_m); - /* we only use vtmr in tweaked mode */ - if (config.timer_tweaks) - vtmr_raise(VTMR_RTC); - else - pic_request(8); + pic_request(PIC_IRQ8); } if (!(old_c & 0x40)) q_ticks_m -= 1000000; @@ -105,14 +101,11 @@ Bit8u rtc_read(Bit8u reg) if (debug_level('h') > 8) h_printf("RTC: Read C=%hhx\n", ret); SET_CMOS(CMOS_STATUSC, 0); - pic_untrigger(8); + pic_untrigger(PIC_IRQ8); rtc_run(); break; } - /* below slows down streetfighter2 game so commented out */ -// vtmr_sync(VTMR_RTC); - return ret; } @@ -181,7 +174,7 @@ static void rtc_alarm_check (void) if ((GET_CMOS(CMOS_STATUSB) & 0x20) && !(GET_CMOS(CMOS_STATUSC) & 0x80)) { SET_CMOS(CMOS_STATUSC, GET_CMOS(CMOS_STATUSC) | 0x80); h_printf("RTC: alarm IRQ\n"); - pic_request(8); + pic_request(PIC_IRQ8); } } } @@ -259,7 +252,7 @@ void rtc_update (void) /* called every 1s from SIGALRM */ if ((GET_CMOS(CMOS_STATUSB) & 0x10) && !(GET_CMOS(CMOS_STATUSC) & 0x80)) { SET_CMOS(CMOS_STATUSC, GET_CMOS(CMOS_STATUSC) | 0x80); h_printf("RTC: update IRQ\n"); - pic_request(8); + pic_request(PIC_IRQ8); } SET_CMOS(CMOS_STATUSA, GET_CMOS(CMOS_STATUSA)&~0x80); @@ -269,30 +262,16 @@ void rtc_update (void) /* called every 1s from SIGALRM */ * Initialise the RTC. Key work is now in get_linux_ticks() where we initialise * all of the RTC time/date fields, and only zero the alarm stuff here. */ -void rtc_setup(void) +void rtc_init (void) { + usr_delta_ticks = 0; + last_ticks = sys_base_ticks = get_linux_ticks(1, NULL); + SET_CMOS(CMOS_HOURALRM, 0); SET_CMOS(CMOS_MINALRM, 0); SET_CMOS(CMOS_SECALRM, 0); } -static int rtc_vint(int masked) -{ - if (masked) - pic_request(8); - return 0; -} - -void rtc_init(void) -{ - usr_delta_ticks = 0; - last_ticks = sys_base_ticks = get_linux_ticks(1, NULL); - - vtmr_register(VTMR_RTC, rtc_vint); - /* NOTE: vtmr is only used in tweaked mode, so we set it to 1 beforehands, - * but may not actually use */ - vtmr_set_tweaked(VTMR_RTC, 1, 0); -} /* ========================================================================= */ @@ -352,8 +331,8 @@ void rtc_init(void) * to be used for both the INT-1A AH=0 function (get ticks) and the AH=2 or 4 (get RTC time/date) * without confusing the once per day roll-over count. * - * In addition, should the LINUX time go backwards over midnight (very unfortunate occurrence, but - * it is just possible if ntpdate was used to get things correct at once, rather then the ntm daemon + * In addition, should the LINUX time go backwards over midnight (very unfortunate occurance, but + * it is just possible if ntpdate was used to get things correct at once, rather then the ntm deamon * running to slew time to correctness slowly) it will hold the DOS notion of time at 00:00:00 * until the LINUX time crosses the midnight boundary again, but without producing two day counts. * @@ -364,11 +343,11 @@ void rtc_init(void) * day_rollover : Non-NULL pointer if checking for the day crossing for INT-1A AH=0 use. * * The return value is the DOS 'ticks' from 00:00:00 for this day. - * An error results in -1 return (e.g. from problems converting time, perhaps bad TZ environment). + * An error results in -1 retun (e.g. from problems converting time, perhaps bad TZ environment). * * NOTE: A check in the freedos source shows a *slightly* different value for the nominal tick count * spanning one day, compared to the PIT_TICK_RATE value in timers.h (which is correct, I think). So - * if you compile with the freedos values for 100% time conversion compatibility with it, that is fine + * if you compile with the freedos values for 100% time conversion compatability with it, that is fine * but if you compile with the 'correct' PIT_TICK_RATE value, it limits it near midnight so freedos * never gets a value corresponding equal to, or more than, 24 hours. * @@ -402,7 +381,7 @@ unsigned long get_linux_ticks(int set_cmos, int *day_rollover) /* Compute time of day in 1/100 second units, then to DOS ticks. */ tt = isec * 100 + (tv.tv_usec / 10000); -#ifdef USE_PIT_TICK_RATE +#if USE_PIT_TICK_RATE tt = (tt * PIT_TICK_RATE) / 6553600; /* Correct as per LINUX code, 44-bit intermediate product.*/ if(tt > FREEDOS_TICKS_IN_A_DAY) tt = FREEDOS_TICKS_IN_A_DAY; #else diff --git a/src/base/dev/misc/timers.c b/src/base/dev/misc/timers.c index 8f78326..02b4d2f 100644 --- a/src/base/dev/misc/timers.c +++ b/src/base/dev/misc/timers.c @@ -9,7 +9,7 @@ * REMARK * This is the timer emulation for DOSEMU. It emulates the Programmable * Interval Timer (PIT), and also handles IRQ0 interrupt events. - * A lot of animation and video game software are dependent on this module + * A lot of animation and video game software are dependant on this module * for high frequency timer interrupts (IRQ0). * * This code will actually generate 18.2 DOS interrupts/second (the code @@ -33,58 +33,73 @@ #include "emu.h" #include "port.h" +#include "timers.h" #include "iodev.h" #include "int.h" +#include "pic.h" #include "emudpmi.h" -#include "vtmr.h" -#include "evtimer.h" -#include "timers.h" #undef DEBUG_PIT #undef ONE_MINUTE_TEST -/******************************************************************* - * Programmable Interrupt Timer (PIT) chip * - *******************************************************************/ +pit_latch_struct pit[PIT_TIMERS]; /* values of 3 PIT counters */ -typedef struct { - Bit16u read_state; - Bit16u write_state; - Bit8u mode, outpin; - Bit32u read_latch; - Bit16u write_latch; - Bit32s cntr; - hitimer_u time; - uint32_t q_ticks; - void *evtmr; - int tmr_skip; -} pit_latch_struct; - -static pit_latch_struct pit[PIT_TIMERS]; /* values of 3 PIT counters */ - -hitimer_t pic_sys_time; /* system time set by pic_watch */ -static int irq0_cnt; - -#define NEVER -1 -static hitimer_t pic_itime[33] = /* time to trigger next interrupt */ - {NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, - NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, - NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, - NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, - NEVER}; - -static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) -{ - return /*(__int128_t)*/a * b / c; -} - -#define TICKS_TO_NS(t) muldiv64(t, NANOSECONDS_PER_SECOND, PIT_TICK_RATE) -#define NS_TO_TICKS(n) muldiv64(n, PIT_TICK_RATE, NANOSECONDS_PER_SECOND) +static u_long timer_div; /* used by timer int code */ +static u_long ticks_accum; /* For timer_tick function, 100usec ticks */ static Bit8u port61 = 0x0c; int is_cli; +/* + * DANG_BEGIN_FUNCTION initialize_timers + * + * description: + * ensure the 0x40 port timer is initially set correctly + * + * DANG_END_FUNCTION + */ +void initialize_timers(void) +{ + hitimer_t cur_time; + + cur_time = GETtickTIME(0); + + pit[0].mode = 3; + pit[0].outpin = 0; + pit[0].cntr = 0x10000; + pit[0].time.td = cur_time; + pit[0].read_latch = -1; + pit[0].write_latch = 0; + pit[0].read_state = 3; + pit[0].write_state = 3; + + pit[1].mode = 2; + pit[1].outpin = 0; + pit[1].cntr = 18; + pit[1].time.td = cur_time; + pit[1].read_latch = -1; + pit[1].write_latch = 18; + pit[1].read_state = 3; + pit[1].write_state = 3; + + pit[2].mode = 0; + pit[2].outpin = 0; + pit[2].cntr = -1; + pit[2].time.td = cur_time; + pit[2].read_latch = -1; + pit[2].write_latch = 0; + pit[2].read_state = 3; + pit[2].write_state = 3; + + ticks_accum = 0; + timer_div = (pit[0].cntr * 10000) / PIT_TICK_RATE; + + timer_tick(); /* a starting tick! */ + + port61 = 0x0c; +} + /* * DANG_BEGIN_FUNCTION timer_tick * @@ -97,7 +112,30 @@ int is_cli; */ void timer_tick(void) { - pic_sys_time = GETtickTIME(0); +#ifdef ONE_MINUTE_TEST + static int dbug_count = 0; +#endif + hitimer_u tp; + u_long time_curr; + static u_long time_old = 0; /* Preserve value for next call */ + + /* Get system time in ticks */ + tp.td = GETtickTIME(0); +#ifdef ONE_MINUTE_TEST + if (++dbug_count > 6000) leavedos(0); +#endif + + /* compute the number of 100ticks since we started */ + time_curr = (tp.td - pit[0].time.td) / 100; + + /* Reset old timer value to 0 if time_curr wrapped around back to 0 */ + if (time_curr < time_old) time_old = 0; + + /* Compute number of 100ticks ticks since the last time this function ran */ + ticks_accum += (time_curr - time_old); + + /* Save old value of the timer */ + time_old = time_curr; if (config.cli_timeout && is_cli) { if (isset_IF()) { @@ -109,6 +147,9 @@ void timer_tick(void) } } dpmi_timer(); + + /* test for stuck interrupts, trigger any scheduled interrupts */ + pic_watch(&tp); } @@ -148,7 +189,7 @@ void do_sound(Bit16u period) * * But if you set it too low, then sounds can be cut off - clarence */ - static const unsigned sound_duration = 30000; /* in milliseconds */ + static const unsigned sound_duration = 30000; /* in miliseconds */ switch (port61 & 3) { case 3: /* speaker on & speaker control through timer channel 2 */ if ((pit[2].mode == 2) || (pit[2].mode == 3)) { /* is this test needed? */ @@ -168,11 +209,11 @@ void do_sound(Bit16u period) } } -static int _pit_latch(int latch, uint64_t cur) + +static void pit_latch(int latch) { - int ret = 0; hitimer_u cur_time; - long ticks=0; + u_long ticks=0; pit_latch_struct *p = &pit[latch]; /* check for special 'read latch status' mode */ @@ -191,10 +232,10 @@ static int _pit_latch(int latch, uint64_t cur) if (p->cntr == -1) p->read_latch |= 0x40; p->mode &= ~0x80; - return ret; /* let bit 7 on */ + return; /* let bit 7 on */ } - cur_time.td = cur; + cur_time.td = GETtickTIME(0); if ((p->mode & 2)==0) { /* non-periodical modes 0,1,4,5 - used mainly by games @@ -210,7 +251,7 @@ static int _pit_latch(int latch, uint64_t cur) /* should have been initialized to the value in write_latch */ if (p->cntr != -1) { - ticks = NS_TO_TICKS(cur_time.td - p->time.td); + ticks = (cur_time.td - p->time.td); if (ticks > p->cntr) { /* time has elapsed */ if ((p->mode&0x40)==0) @@ -231,28 +272,24 @@ static int _pit_latch(int latch, uint64_t cur) /* mode 6 -- ??? */ /* mode 3 -- square-wave generator, countdown by 2 */ /* mode 7 -- ??? */ + pic_sys_time = cur_time.td; /* full counter */ + /* NEVER is a special invalid value... skip it if found */ + pic_sys_time += (pic_sys_time == NEVER); + if (latch == 0) { -#if 0 /* when current time is greater than irq time, call pic_request which will then point pic_itime to next interrupt */ + if (((p->mode&0x40)==0) && (pic_sys_time > pic_itime[PIC_IRQ0])) { if (pic_request(PIC_IRQ0)==PIC_REQ_OK) { r_printf("PIT: pit_latch, pic_request IRQ0 mode 2/3\n"); } } -#endif /* while current time is less than next irq time, ticks decrease; * ticks can go out of bounds or negative when the interrupt * is lost or pending */ - if (cur > pic_itime[latch]) { - ticks = 1; - ret++; // underflow seen - } else { - ticks = NS_TO_TICKS(pic_itime[latch] - cur) + 1; - if (ticks > p->cntr) - ticks = 0; // should not be here - } + ticks = (pic_itime[PIC_IRQ0] - pic_sys_time) % p->cntr; } else { - ticks = p->cntr - (cur % p->cntr); + ticks = p->cntr - (pic_sys_time % p->cntr); } if ((p->mode & 3)==3) { @@ -276,57 +313,20 @@ static int _pit_latch(int latch, uint64_t cur) i_printf("PIT%d: ticks=%lx latch=%x pin=%d\n",latch,ticks, p->read_latch,(p->outpin!=0)); #endif - return ret; -} - -static int do_pit_latch(int latch) -{ - int ret; - uint64_t cur_time; - - evtimer_block(pit[latch].evtmr); - cur_time = evtimer_gettime(pit[latch].evtmr); - /* if timer is lagging we run it by hands */ - if (cur_time > pic_itime[latch] && - __sync_bool_compare_and_swap(&pit[latch].q_ticks, 0, 1)) { - /* timer thread blocked, we can increment vars w/o sync/atomics */ - pit[latch].tmr_skip++; - if (!latch) - vtmr_raise(VTMR_PIT); - else - pit[latch].q_ticks--; - pit[latch].time.td = pic_itime[latch]; - pic_itime[latch] += TICKS_TO_NS(pit[latch].cntr); - } - ret = _pit_latch(latch, cur_time); - vtmr_sync(VTMR_PIT); - evtimer_unblock(pit[latch].evtmr); - return ret; -} - -static int pit_latch_hndl(void) -{ - return do_pit_latch(0); -} - -static void pit_latch(int latch) -{ - if (latch == 0) - vtmr_latch(VTMR_PIT); - else - do_pit_latch(latch); } /* This is called also by port 0x61 - some programs can use timer #2 * as a GP timer and read bit 5 of port 0x61 (e.g. Matrox BIOS) */ -Bit8u pit_inp(ioport_t port, void *arg) +Bit8u pit_inp(ioport_t port) { int ret = 0; port -= 0x40; - if ((port == 2) && (config.speaker == SPKR_NATIVE)) - return std_port_inb(0x42); + if ((port == 2) && (config.speaker == SPKR_NATIVE)) { + error ("pit_inp() - how could we come here if we defined PORT_FAST?\n"); + return safe_port_in_byte(0x42); + } else if (port == 1) i_printf("PIT: someone is reading the CMOS refresh time?!?"); @@ -360,14 +360,15 @@ Bit8u pit_inp(ioport_t port, void *arg) return ret; } -void pit_outp(ioport_t port, Bit8u val, void *arg) +void pit_outp(ioport_t port, Bit8u val) { port -= 0x40; if (port == 1) i_printf("PORT: someone is writing the CMOS refresh time?!?"); else if (port == 2 && config.speaker == SPKR_NATIVE) { - std_port_outb(0x42, val); + error ("pit_outp() - how could we come here if we defined PORT_FAST?\n"); + safe_port_out_byte(0x42, val); return; } @@ -402,28 +403,36 @@ void pit_outp(ioport_t port, Bit8u val, void *arg) if (pit[port].write_state != 0) { if (pit[port].write_latch == 0) - pit[port].cntr = 0xffff; + pit[port].cntr = 0x10000; else pit[port].cntr = pit[port].write_latch; - if (!port) - evtimer_set_rel(pit[port].evtmr, TICKS_TO_NS(pit[port].cntr), 1); - else - evtimer_stop(pit[port].evtmr); - h_printf("PIT: timer %i set to %i ticks\n", port, pit[port].cntr); - pit[port].time.td = 0; - pic_itime[port] = TICKS_TO_NS(pit[port].cntr); - if (port == 2 && (port61 & 3) == 3) - do_sound(pit[port].cntr); + pit[port].time.td = GETtickTIME(0); + + if (port == 0) { + ticks_accum = 0; + timer_div = (pit[0].cntr * 10000) / PIT_TICK_RATE; + if (timer_div == 0) + timer_div = 1; +#if 1 + i_printf("timer_interrupt_rate count %i, requested %.3g Hz, granted %.3g Hz\n", + pit[0].cntr, PIT_TICK_RATE/(double)pit[0].cntr, 10000.0/timer_div); +#endif + } +#if 0 + else if (port == 2 && config.speaker == SPKR_EMULATED) { + do_sound(pit[2].write_latch & 0xffff); + } +#endif } } -Bit8u pit_control_inp(ioport_t port, void *arg) +Bit8u pit_control_inp(ioport_t port) { return 0; } -void pit_control_outp(ioport_t port, Bit8u val, void *arg) +void pit_control_outp(ioport_t port, Bit8u val) { int latch = (val >> 6) & 0x03; @@ -454,7 +463,7 @@ void pit_control_outp(ioport_t port, Bit8u val, void *arg) switch (latch) { case 2: if (config.speaker == SPKR_NATIVE) { - std_port_outb(0x43, val); + safe_port_out_byte(0x43, val); break; } /* nobreak; */ @@ -470,7 +479,7 @@ void pit_control_outp(ioport_t port, Bit8u val, void *arg) /* set the time base for the counter - safety code for programs * which use a non-periodical mode without reloading the counter */ - pit[latch].time.td = evtimer_gettime(pit[latch].evtmr); + pit[latch].time.td = GETtickTIME(0); } } #ifdef DEBUG_PIT @@ -494,47 +503,32 @@ void pit_control_outp(ioport_t port, Bit8u val, void *arg) } } -static void timer_activate(int ticks, void *arg) +/* DANG_BEGIN_FUNCTION timer_int_engine + * + * This is experimental TIMER-IRQ CHAIN code! + * This is a function to determine whether it is time to invoke a + * new timer irq 0 event. Normally it is 18 times a second, but + * many video games set it to 100 times per second or more. Since + * the kernel cannot keep an accurate timer interrupt, the job of this + * routine is to perform a chained timer irq 0 right after the previous + * timer irq 0. This routine should, ideally, be called right after + * the end of a timer irq, if possible. + * + * This would speed up high frequency timer interrupts if this code + * can be converted into an assembly macro equivalent! + * + * PLEASE NOTE + * + * This code has been replaced by interrupt scheduling code in pic. + * The result is that we simply call pic_sched and run the dos interrupt. + * If the new code causes no problems, I'll revise this section permanently. + * + * DANG_END_FUNCTION + */ +static int timer_int_engine(int ilevel) { - int pit_num = (uintptr_t)arg; - uint32_t q; - - if (pit[pit_num].tmr_skip) { - pit[pit_num].tmr_skip--; - return; - } - if (!ticks) { - error("0 ticks on PIT\n"); - return; - } - q = __sync_fetch_and_add(&pit[pit_num].q_ticks, ticks); - h_printf("PIT: timer %i expired, %i\n", pit_num, q); - if (pit_num) { - pit[pit_num].time.td = evtimer_gettime(pit[pit_num].evtmr); - return; - } - if (!q) { - vtmr_raise(VTMR_PIT); - pit[0].time.td = pic_itime[0]; - pic_itime[0] += TICKS_TO_NS(pit[0].cntr); - } -} - -static int timer_irq_ack(int masked) -{ - uint32_t q = __sync_sub_and_fetch(&pit[0].q_ticks, 1); - int ret = 0; - - h_printf("PIT: timer 0 acknowledged, %i\n", q); - - if (q) { - pit[0].time.td = pic_itime[0]; - pic_itime[0] += TICKS_TO_NS(pit[0].cntr); - ret = 1; - } - if (!masked) - irq0_cnt++; - return ret; + pic_sched(PIC_IRQ0,pit[0].cntr); + return 1; } /* reads/writes to the speaker control port (0x61) @@ -562,7 +556,7 @@ static int timer_irq_ack(int masked) Bit8u spkr_io_read(ioport_t port) { if (port==0x61) { if (config.speaker == SPKR_NATIVE) - return std_port_inb(0x61); + return port_safe_inb(0x61); else { /* keep the connection between port 0x61 and PIT timer#2 */ pit_latch(2); @@ -578,7 +572,7 @@ void spkr_io_write(ioport_t port, Bit8u value) { if (port==0x61) { switch (config.speaker) { case SPKR_NATIVE: - std_port_outb(0x61, value & 0x03); + port_safe_outb(0x61, value & 0x03); break; case SPKR_EMULATED: @@ -609,11 +603,14 @@ void pit_init(void) io_device.handler_name = "8254 Timer0"; io_device.start_addr = 0x0040; io_device.end_addr = 0x0040; + io_device.irq = 0; + io_device.fd = -1; port_register_handler(io_device, 0); io_device.handler_name = "8254 Timer1"; io_device.start_addr = 0x0041; io_device.end_addr = 0x0041; + io_device.irq = EMU_NO_IRQ; port_register_handler(io_device, 0); io_device.handler_name = "8254 Timer2"; @@ -636,82 +633,54 @@ void pit_init(void) port_register_handler(io_device, 0); #endif - vtmr_register(VTMR_PIT, timer_irq_ack); - vtmr_register_latch(VTMR_PIT, pit_latch_hndl); - vtmr_set_tweaked(VTMR_PIT, config.timer_tweaks, 0); - - pit[0].evtmr = evtimer_create(timer_activate, (void *)(uintptr_t)0); - pit[1].evtmr = evtimer_create(timer_activate, (void *)(uintptr_t)1); - pit[2].evtmr = evtimer_create(timer_activate, (void *)(uintptr_t)2); -} - -void pit_done(void) -{ - evtimer_delete(pit[0].evtmr); - evtimer_delete(pit[1].evtmr); - evtimer_delete(pit[2].evtmr); + pic_seti(PIC_IRQ0, timer_int_engine, 0, NULL); /* do_irq0 in pic.c */ + pic_request(PIC_IRQ0); /* start timer */ } void pit_reset(void) { + hitimer_t cur_time; + + cur_time = GETtickTIME(0); + pit[0].mode = 3; pit[0].outpin = 0; - pit[0].cntr = 0xffff; - pit[0].time.td = 0; + pit[0].cntr = 0x10000; + pit[0].time.td = cur_time; pit[0].read_latch = 0xffffffff; pit[0].write_latch = 0; pit[0].read_state = 3; pit[0].write_state = 3; - pit[0].q_ticks = 0; - evtimer_stop(pit[0].evtmr); pit[1].mode = 2; pit[1].outpin = 0; pit[1].cntr = 18; - pit[1].time.td = 0; + pit[1].time.td = cur_time; pit[1].read_latch = 0xffffffff; pit[1].write_latch = 18; pit[1].read_state = 3; pit[1].write_state = 3; - pit[1].q_ticks = 0; - evtimer_stop(pit[1].evtmr); pit[2].mode = 0; pit[2].outpin = 0; - pit[2].cntr = 0xffff; - pit[2].time.td = 0; + pit[2].cntr = 0x10000; + pit[2].time.td = cur_time; pit[2].read_latch = 0xffffffff; pit[2].write_latch = 0; pit[2].read_state = 3; pit[2].write_state = 3; - pit[2].q_ticks = 0; - evtimer_stop(pit[2].evtmr); pit[3].mode = 0; pit[3].outpin = 0; - pit[3].cntr = 0xffff; - pit[3].time.td = 0; + pit[3].cntr = 0x10000; + pit[3].time.td = cur_time; pit[3].read_latch = 0xffffffff; pit[3].write_latch = 0; pit[3].read_state = 3; pit[3].write_state = 3; +#if 0 + timer_handle = timer_create(pit_timer_func, NULL, pit_timer_usecs(0x10000)); +#endif port61 = 0x0c; - - pic_sys_time = GETtickTIME(0); -} - -void pit_late_init(void) -{ - evtimer_set_rel(pit[0].evtmr, TICKS_TO_NS(pit[0].cntr), 1); - pit[0].time.td = 0; - pic_itime[0] = TICKS_TO_NS(pit[0].cntr); -} - -#define TIMER0_FLOOD_THRESHOLD 50 - -int CAN_SLEEP(void) -{ - return (!(pic_get_isr() || (REG(eflags) & VIP) || signal_pending() || - (pit[0].q_ticks > TIMER0_FLOOD_THRESHOLD) || in_leavedos)); } diff --git a/src/base/dev/misc/virq.c b/src/base/dev/misc/virq.c deleted file mode 100644 index d7d67bc..0000000 --- a/src/base/dev/misc/virq.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: virtual IRQ router - * - * Author: Stas Sergeev. - * - */ -#include -#include -#include -#include "port.h" -#include "pic.h" -#include "hlt.h" -#include "cpu.h" -#include "int.h" -#include "bitops.h" -#include "emu.h" -#include "virq.h" - -#define VIRQ_IRR_PORT 0x50a -#define VIRQ_HWC_PORT (VIRQ_IRR_PORT + 2) -#define VIRQ_RST_PORT (VIRQ_IRR_PORT + 3) -#define VIRQ_TOTAL_PORTS 4 -#define VIRQ_IRQ_NUM 0xf -#define VIRQ_INTERRUPT (VIRQ_IRQ_NUM - 8 + 0x70) - -static uint16_t virq_irr; -static pthread_mutex_t irr_mtx = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t hndl_mtx = PTHREAD_MUTEX_INITIALIZER; -static uint16_t virq_hlt; - -struct vhandler_s { - enum VirqHwRet (*hw_handler)(void *); - enum VirqSwRet (*sw_handler)(void *); - void *arg; -}; -struct vhandler_s vhandlers[VIRQ_MAX]; - -static void virq_lower(int virq_num); - -static Bit16u virq_irr_read(ioport_t port, void *arg) -{ - uint16_t irr; - - pthread_mutex_lock(&irr_mtx); - irr = virq_irr; - pthread_mutex_unlock(&irr_mtx); - return irr; -} - -static void virq_hwc_write(ioport_t port, Bit8u value, void *arg) -{ - struct vhandler_s *vh; - enum VirqHwRet rc = VIRQ_HWRET_DONE; - - switch (port) { - case VIRQ_RST_PORT: - switch (value) { - case 1: - /* re-assert irqs */ - if (virq_irr) - pic_request(VIRQ_IRQ_NUM); - break; - } - break; - - case VIRQ_HWC_PORT: - assert(value < VIRQ_MAX); - vh = &vhandlers[value]; - pthread_mutex_lock(&hndl_mtx); - if (vh->hw_handler) - rc = vh->hw_handler(vh->arg); - if (rc == VIRQ_HWRET_DONE) - virq_lower(value); - pthread_mutex_unlock(&hndl_mtx); - break; - } -} - -static void virq_handler(uint16_t idx, HLT_ARG(arg)) -{ - uint16_t irr; - - while ((irr = port_inw(VIRQ_IRR_PORT))) { - struct vhandler_s *vh; - int inum = find_bit(irr); - - assert(inum < VIRQ_MAX); - port_outb(VIRQ_HWC_PORT, inum); - vh = &vhandlers[inum]; - if (vh->sw_handler) { - enum VirqSwRet rc = vh->sw_handler(vh->arg); - if (rc == VIRQ_SWRET_BH) { - assert(_IP != virq_hlt); - /* If BH is scheduled, we just return and switch back later. */ - set_IF(); - return; - } - } else { - error("virq: no handler for %i\n", inum); - } - } - assert(_IP == virq_hlt); - do_eoi2_iret(); -} - -void virq_init(void) -{ - emu_iodev_t io_dev = {}; - emu_hlt_t hlt_hdlr = HLT_INITIALIZER; - - io_dev.write_portb = virq_hwc_write; - io_dev.read_portw = virq_irr_read; - io_dev.start_addr = VIRQ_IRR_PORT; - io_dev.end_addr = VIRQ_IRR_PORT + VIRQ_TOTAL_PORTS - 1; - io_dev.handler_name = "virtual IRQ router"; - port_register_handler(io_dev, 0); - - hlt_hdlr.name = "virq"; - hlt_hdlr.func = virq_handler; - virq_hlt = hlt_register_handler_vm86(hlt_hdlr); -} - -void virq_reset(void) -{ - pic_untrigger(VIRQ_IRQ_NUM); -} - -void virq_setup(void) -{ - SETIVEC(VIRQ_INTERRUPT, BIOS_HLT_BLK_SEG, virq_hlt); - port_outb(VIRQ_RST_PORT, 1); -} - -void virq_raise(int virq_num) -{ - uint16_t irr; - uint16_t mask = 1 << virq_num; - - assert(virq_num < VIRQ_MAX); - pthread_mutex_lock(&hndl_mtx); - pthread_mutex_lock(&irr_mtx); - /* __sync_fetch_and_or() */ - irr = virq_irr; - virq_irr |= mask; - if (!irr) - pic_request(VIRQ_IRQ_NUM); - pthread_mutex_unlock(&irr_mtx); - pthread_mutex_unlock(&hndl_mtx); -} - -static void virq_lower(int virq_num) -{ - uint16_t irr; - uint16_t mask = 1 << virq_num; - - assert(virq_num < VIRQ_MAX); - pthread_mutex_lock(&irr_mtx); - /* __sync_and_and_fetch() */ - virq_irr &= ~mask; - irr = virq_irr; - if (!irr) - pic_untrigger(VIRQ_IRQ_NUM); - pthread_mutex_unlock(&irr_mtx); -} - -void virq_register(int virq_num, enum VirqHwRet (*hw_handler)(void *), - enum VirqSwRet (*sw_handler)(void *), void *arg) -{ - if (virq_num >= VIRQ_MAX) - return; - vhandlers[virq_num].hw_handler = hw_handler; - vhandlers[virq_num].sw_handler = sw_handler; - vhandlers[virq_num].arg = arg; -} - -void virq_unregister(int virq_num) -{ - vhandlers[virq_num].hw_handler = NULL; - vhandlers[virq_num].sw_handler = NULL; -} diff --git a/src/base/dev/misc/vtmr.c b/src/base/dev/misc/vtmr.c deleted file mode 100644 index c07d425..0000000 --- a/src/base/dev/misc/vtmr.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: virtual timer device extension - * - * Author: Stas Sergeev. - * - * Note: this code shows how to run coopth in a separate thread. - * Many things are written here just as an example. - * Perhaps in the future the example should be moved elsewhere. - */ -#include -#include -#include -#include -#include "port.h" -#include "pic.h" -#include "cpu.h" -#include "int.h" -#include "bitops.h" -#include "emudpmi.h" -#include "emu.h" -#include "coopth.h" -#if MULTICORE_EXAMPLE -#include "lowmem.h" -#include "hlt.h" -#endif -#include "utilities.h" -#include "timers.h" -#include "chipset.h" -#include "vint.h" -#include "vtmr.h" - -#define VTMR_FIRST_PORT 0x550 -#define VTMR_VPEND_PORT VTMR_FIRST_PORT -#define VTMR_IRR_PORT (VTMR_FIRST_PORT + 2) -#define VTMR_ACK_PORT (VTMR_FIRST_PORT + 3) -#define VTMR_REQUEST_PORT (VTMR_FIRST_PORT + 4) -#define VTMR_MASK_PORT (VTMR_FIRST_PORT + 5) -#define VTMR_UNMASK_PORT (VTMR_FIRST_PORT + 6) -#define VTMR_LATCH_PORT (VTMR_FIRST_PORT + 7) -#define VTMR_TOTAL_PORTS 8 - -static uint16_t vtmr_irr; -static uint16_t vtmr_imr; -static uint16_t vtmr_pirr; - -static pthread_t vtmr_thr; -static sem_t vtmr_sem; -static int latch_tid; -static pthread_mutex_t irr_mtx = PTHREAD_MUTEX_INITIALIZER; -#if MULTICORE_EXAMPLE -static int smi_tid; -static char *rmstack; -static uint16_t hlt_off; -#endif - -struct vthandler { - int (*handler)(int); - int (*latch)(void); - int vint; - int done_pred; - pthread_mutex_t done_mtx; - pthread_cond_t done_cnd; -}; -struct vthandler vth[VTMR_MAX]; - -struct vint_presets { - uint8_t irq; - uint8_t orig_irq; - uint8_t interrupt; -}; -static struct vint_presets vip[VTMR_MAX] = { - [VTMR_PIT] = { .irq = VTMR_IRQ, .orig_irq = 0, - .interrupt = VTMR_INTERRUPT }, - [VTMR_RTC] = { .irq = VRTC_IRQ, .orig_irq = 8, - .interrupt = VRTC_INTERRUPT }, -}; - -static int do_vtmr_raise(int timer); - -static Bit8u vtmr_irr_read(ioport_t port, void *arg) -{ - return vtmr_irr; -} - -static Bit16u vtmr_vpend_read(ioport_t port, void *arg) -{ - /* clang has __atomic_swap() */ - return __atomic_exchange_n(&vtmr_pirr, 0, __ATOMIC_ACQ_REL); -} - -static void post_req(int timer) -{ - if (vth[timer].handler) { - int rc = vth[timer].handler(0); - if (rc) - do_vtmr_raise(timer); - } - h_printf("vtmr: post-REQ on %i, irr=%x\n", timer, vtmr_irr); -} - -static void vtmr_io_write(ioport_t port, Bit8u value, void *arg) -{ - int masked = (value >> 7) & 1; - int timer = value & 0x7f; - uint16_t msk = 1 << timer; - - if (timer >= VTMR_MAX) - return; - switch (port) { - case VTMR_REQUEST_PORT: - if (!masked) { - uint16_t irr; - pthread_mutex_lock(&irr_mtx); - irr = __sync_fetch_and_or(&vtmr_irr, msk); - if (!(irr & msk)) { - if (!(vtmr_imr & msk)) - pic_request(vip[timer].irq); - } else { - error("vtmr %i already requested\n", timer); - } - pthread_mutex_unlock(&irr_mtx); - } else { - pic_untrigger(vip[timer].orig_irq); - pic_request(vip[timer].orig_irq); - post_req(timer); - } - h_printf("vtmr: REQ on %i, irr=%x, pirr=%x masked=%i\n", timer, - vtmr_irr, vtmr_pirr, masked); - break; - case VTMR_MASK_PORT: { - uint16_t imr = __sync_fetch_and_or(&vtmr_imr, msk); - if (!(imr & msk)) { - if (vtmr_irr & msk) - pic_untrigger(vip[timer].irq); - } - break; - } - case VTMR_UNMASK_PORT: { - uint16_t imr = __sync_fetch_and_and(&vtmr_imr, ~msk); - if (imr & msk) { - if (vtmr_irr & msk) - pic_request(vip[timer].irq); - } - break; - } - case VTMR_ACK_PORT: { - uint16_t irr; - pthread_mutex_lock(&irr_mtx); - irr = __sync_fetch_and_and(&vtmr_irr, ~msk); - if (irr & msk) { - pic_untrigger(vip[timer].irq); - if (vth[timer].handler) { - int rc = vth[timer].handler(masked); - if (rc) - do_vtmr_raise(timer); - } - } else { - error("vtmr %i not requested\n", timer); - } - pthread_mutex_unlock(&irr_mtx); - h_printf("vtmr: ACK on %i, irr=%x pirr=%x\n", timer, vtmr_irr, - vtmr_pirr); - break; - } - case VTMR_LATCH_PORT: { - int from_irq = masked; - if (vth[timer].latch) { - int rc = vth[timer].latch(); - if (rc && !from_irq) { // underflow seen not from IRQ - uint16_t irr; - pthread_mutex_lock(&irr_mtx); - irr = __sync_fetch_and_and(&vtmr_irr, ~msk); - if (irr & msk) { - pic_untrigger(vip[timer].irq); - if (vth[timer].handler) { - rc = vth[timer].handler(1); - if (rc) - do_vtmr_raise(timer); - } - } - pthread_mutex_unlock(&irr_mtx); - } - } - h_printf("vtmr: LATCH on %i, irr=%x pirr=%x\n", timer, vtmr_irr, - vtmr_pirr); - break; - } - } - -} - -static void do_ack(int timer, int masked) -{ - port_outb(VTMR_ACK_PORT, timer | (masked << 7)); -} - -static void ack_handler(int vint, int masked) -{ - int i; - - for (i = 0; i < VTMR_MAX; i++) { - if (vth[i].vint == vint) { - do_ack(i, masked); - break; - } - } -} - -static void do_mask(int timer) -{ - port_outb(VTMR_MASK_PORT, timer); -} - -static void do_unmask(int timer) -{ - port_outb(VTMR_UNMASK_PORT, timer); -} - -static void mask_handler(int vint, int masked) -{ - int i; - - for (i = 0; i < VTMR_MAX; i++) { - if (vth[i].vint == vint) { - if (masked) - do_mask(i); - else - do_unmask(i); - break; - } - } -} - -int vtmr_pre_irq_dpmi(uint8_t *imr) -{ - int masked = vint_is_masked(vth[VTMR_PIT].vint, imr); - do_mask(VTMR_PIT); - do_ack(VTMR_PIT, masked); - vint_post_irq_dpmi(vth[VTMR_PIT].vint, masked); - return masked; -} - -void vtmr_post_irq_dpmi(int masked) -{ - do_unmask(VTMR_PIT); -} - -int vrtc_pre_irq_dpmi(uint8_t *imr) -{ - int masked = vint_is_masked(vth[VTMR_RTC].vint, imr); - do_mask(VTMR_RTC); - do_ack(VTMR_RTC, masked); - vint_post_irq_dpmi(vth[VTMR_RTC].vint, masked); - return masked; -} - -void vrtc_post_irq_dpmi(int masked) -{ - do_unmask(VTMR_RTC); -} - -static int vtmr_is_masked(int timer) -{ - uint8_t imr[2] = { [0] = port_inb(0x21), [1] = port_inb(0xa1) }; - uint16_t real_imr = (imr[1] << 8) | imr[0]; - return ((imr[0] & 4) || !!(real_imr & (1 << vip[timer].irq))); -} - -static void vtmr_smi(void *arg) -{ - int timer; - uint16_t pirr = port_inw(VTMR_VPEND_PORT); - - while ((timer = find_bit(pirr)) != -1) { - int masked = vtmr_is_masked(timer); - pirr &= ~(1 << timer); - port_outb(VTMR_REQUEST_PORT, timer | (masked << 7)); - if (!masked) - port_outb(0x4d2, 1); // set fake IRR - pthread_mutex_lock(&vth[timer].done_mtx); - vth[timer].done_pred = 1; - pthread_mutex_unlock(&vth[timer].done_mtx); - pthread_cond_signal(&vth[timer].done_cnd); - } -} - -static void vtmr_latch_smi(void *arg) -{ - uint16_t isr; - int from_irq; - int timer = (uintptr_t)arg; - - assert(timer < VTMR_MAX); - port_outb(0x20, 0xb); - isr = port_inb(0x20); - port_outb(0xa0, 0xb); - isr = (port_inb(0xa0) << 8); - from_irq = !!(isr & (1 << vip[timer].orig_irq)); - port_outb(VTMR_LATCH_PORT, timer | (from_irq << 7)); -} - -#if MULTICORE_EXAMPLE -static void thr_cleanup(void *arg) -{ - coopth_done(); - lowmem_free(rmstack); -} -#endif - -#define RMSTACK_SIZE 32 - -static void *vtmr_thread(void *arg) -{ -#if MULTICORE_EXAMPLE - /* init coopth in new thread */ - coopth_init(); - pthread_cleanup_push(thr_cleanup, NULL); - smi_tid = coopth_create("vtmr smi", vtmr_smi); - cpu_reset(); - _SS = DOSEMU_LMHEAP_SEG; - _SP = DOSEMU_LMHEAP_OFFS_OF(rmstack) + RMSTACK_SIZE; - _CS = BIOS_HLT_BLK_SEG; - _IP = hlt_off; - clear_IF(); - - /* run our fake core */ - while (1) - run_vm86(); - pthread_cleanup_pop(1); -#else - while (1) { - sem_wait(&vtmr_sem); - vtmr_smi(NULL); - } -#endif - return NULL; -} - -#if MULTICORE_EXAMPLE -static void vtmr_hlt(Bit16u idx, HLT_ARG(arg)) -{ - sem_wait(&vtmr_sem); - coopth_start(smi_tid, NULL); -} -#endif - -void vtmr_init(void) -{ - emu_iodev_t io_dev = {}; -#if MULTICORE_EXAMPLE - emu_hlt_t hlt_hdlr = HLT_INITIALIZER; -#endif - int i; - - io_dev.write_portb = vtmr_io_write; - io_dev.read_portb = vtmr_irr_read; - io_dev.read_portw = vtmr_vpend_read; - io_dev.start_addr = VTMR_FIRST_PORT; - io_dev.end_addr = VTMR_FIRST_PORT + VTMR_TOTAL_PORTS - 1; - io_dev.handler_name = "virtual timer"; - port_register_handler(io_dev, 0); - -#if MULTICORE_EXAMPLE - rmstack = lowmem_alloc(RMSTACK_SIZE); - hlt_hdlr.name = "vtmr sleep"; - hlt_hdlr.func = vtmr_hlt; - hlt_off = hlt_register_handler_vm86(hlt_hdlr); -#endif - - latch_tid = coopth_create("vtmr latch smi", vtmr_latch_smi); - coopth_set_ctx_handlers(latch_tid, sig_ctx_prepare, sig_ctx_restore, NULL); - - sem_init(&vtmr_sem, 0, 0); - for (i = 0; i < VTMR_MAX; i++) { - pthread_mutex_init(&vth[i].done_mtx, NULL); - pthread_cond_init(&vth[i].done_cnd, NULL); - vth[i].done_pred = 1; - } - pthread_create(&vtmr_thr, NULL, vtmr_thread, NULL); -#if defined(HAVE_PTHREAD_SETNAME_NP) && defined(__GLIBC__) - pthread_setname_np(vtmr_thr, "dosemu: vtmr"); -#endif -} - -void vtmr_done(void) -{ - int i; - - pthread_cancel(vtmr_thr); - pthread_join(vtmr_thr, NULL); - sem_destroy(&vtmr_sem); - for (i = 0; i < VTMR_MAX; i++) { - pthread_mutex_destroy(&vth[i].done_mtx); - pthread_cond_destroy(&vth[i].done_cnd); - } -#if MULTICORE_EXAMPLE - lowmem_free(rmstack); -#endif -} - -void vtmr_reset(void) -{ - int i; - - vtmr_irr = 0; - vtmr_imr = 0; - vtmr_pirr = 0; - for (i = 0; i < VTMR_MAX; i++) - pic_untrigger(vip[i].irq); -} - -static int do_vtmr_raise(int timer) -{ - uint16_t pirr; - uint16_t mask = 1 << timer; - - assert(timer < VTMR_MAX); - h_printf("vtmr: raise timer %i\n", timer); - pirr = __sync_fetch_and_or(&vtmr_pirr, mask); - if (!(pirr & mask)) { - h_printf("vtmr: posting timer event\n"); - sem_post(&vtmr_sem); - return 1; - } - return 0; -} - -void vtmr_raise(int timer) -{ - int rc; - - pthread_mutex_lock(&vth[timer].done_mtx); - vth[timer].done_pred = 0; - pthread_mutex_unlock(&vth[timer].done_mtx); - - rc = do_vtmr_raise(timer); - if (!rc) { - pthread_mutex_lock(&vth[timer].done_mtx); - vth[timer].done_pred = 1; - pthread_mutex_unlock(&vth[timer].done_mtx); - pthread_cond_signal(&vth[timer].done_cnd); - } -} - -void vtmr_latch(int timer) -{ - if (in_dpmi_pm()) - fake_pm_int(); - coopth_start(latch_tid, (void *)(uintptr_t)timer); -} - -void vtmr_sync(int timer) -{ - pthread_mutex_lock(&vth[timer].done_mtx); - while (!vth[timer].done_pred) - cond_wait(&vth[timer].done_cnd, &vth[timer].done_mtx); - pthread_mutex_unlock(&vth[timer].done_mtx); -} - -void vtmr_register(int timer, int (*handler)(int)) -{ - struct vthandler *vt = &vth[timer]; - struct vint_presets *vp = &vip[timer]; - assert(timer < VTMR_MAX); - vt->handler = handler; - vt->vint = vint_register(ack_handler, mask_handler, vp->irq, - vp->orig_irq, vp->interrupt); -} - -void vtmr_register_latch(int timer, int (*handler)(void)) -{ - struct vthandler *vt = &vth[timer]; - assert(timer < VTMR_MAX); - vt->latch = handler; -} - -void vtmr_set_tweaked(int timer, int on, unsigned flags) -{ - vint_set_tweaked(vth[timer].vint, on, flags); -} diff --git a/src/base/dev/ne2k/ne2000.c b/src/base/dev/ne2k/ne2000.c index c9fb068..72f1829 100644 --- a/src/base/dev/ne2k/ne2000.c +++ b/src/base/dev/ne2k/ne2000.c @@ -25,10 +25,9 @@ #include #include #include -#include -#include "emu.h" + #include "dosemu_debug.h" -#include "ioselect.h" +#include "emu.h" #include "pic.h" #include "port.h" #include "libpacket.h" @@ -124,7 +123,7 @@ #define ENTSR_OWC 0x80 /* There was an out-of-window collision. */ #define NE2000_IRQ 10 -#define NE2000_IOBASE 0x310 +#define NE2000_IOBASE 0x300 #define NE2000_PMEM_SIZE (32 * 1024) #define NE2000_PMEM_START (16 * 1024) @@ -170,15 +169,14 @@ typedef struct NE2000State { static NE2000State ne2000state; // For io_device -Bit16u ne2000_io_read16(ioport_t port, void *arg); -void ne2000_io_write16(ioport_t port, Bit16u value, void *arg); -Bit8u ne2000_io_read8(ioport_t port, void *arg); -void ne2000_io_write8(ioport_t port, Bit8u value, void *arg); +Bit16u ne2000_io_read16(ioport_t port); +void ne2000_io_write16(ioport_t port, Bit16u value); +Bit8u ne2000_io_read8(ioport_t port); +void ne2000_io_write8(ioport_t port, Bit8u value); static void ne2000_irq_activate(int); -static void ne2000_receive_req_async(int fd, void *arg); +static void ne2000_receive_req_async(void *arg); static size_t ne2000_receive(NE2000State *s, const uint8_t *buf, size_t size_); -static int ne2000_buffer_full(NE2000State *s); #ifdef DEBUG_NE2000 static void N_printhdr(uint8_t *buf); @@ -189,6 +187,13 @@ static void init_cbk(int fd, int mode) ne2000state.fdnet = fd; } +void ne2000_priv_init(void) +{ + if (!config.ne2k) + return; + LibpacketInit(); +} + void ne2000_init(void) { NE2000State *s = &ne2000state; @@ -218,6 +223,8 @@ void ne2000_init(void) io_device.handler_name = "NE2000 Emulation"; io_device.start_addr = /* config.ne2000_base */ NE2000_IOBASE; io_device.end_addr = /* config.ne2000_base */ NE2000_IOBASE + 0x1f; + io_device.irq = /* config.ne2000_irq */ NE2000_IRQ; + io_device.fd = -1; if (port_register_handler(io_device, 0) != 0) { N_printf("NE2000: Error registering NE2000 port handler\n"); ne2000_done(); @@ -225,7 +232,13 @@ void ne2000_init(void) } /* init control defaults */ - s->irq = NE2000_IRQ; + s->irq = pic_irq_list[NE2000_IRQ]; + + /* We let DOSEMU handle the interrupt */ + pic_seti(s->irq, NULL, 0, NULL); + + /* Connect up the receiver */ + add_to_io_select(s->fdnet, ne2000_receive_req_async, NULL); N_printf("NE2000: Initialisation - Base 0x%03x, IRQ %d\n", NE2000_IOBASE, NE2000_IRQ); } @@ -241,7 +254,6 @@ static void _ne2000_reset(NE2000State *s) N_printf("NE2000: ne2000_reset()\n"); s->isr = ENISR_RESET; - s->cmd = E8390_STOP; s->mem[0] = NE2000_EADDR0; s->mem[1] = NE2000_EADDR1; s->mem[2] = NE2000_EADDR2; @@ -279,9 +291,7 @@ void ne2000_done(void) N_printf("NE2000: ne2000_done()\n"); - if (!(s->cmd & E8390_STOP)) - remove_from_io_select(s->fdnet); - CloseNetworkLink(s->fdnet); + close(s->fdnet); s->fdnet = -1; } @@ -302,10 +312,29 @@ static void ne2000_ether_send(NE2000State *s, uint8_t *buf, int len) static int ne2000_ether_recv(NE2000State *s, uint8_t *buf, int bufsiz) { + struct timeval tv; + fd_set readset; int ret; + tv.tv_sec = 0; + tv.tv_usec = 0; + + /* anything ready? */ + FD_ZERO(&readset); + FD_SET(s->fdnet, &readset); + + /* anything ready? */ + if (select(s->fdnet + 1, &readset, NULL, NULL, &tv) <= 0) { + N_printf("NE2000: ne2000_ether_recv() select failed\n"); + return -1; + } + + if (!FD_ISSET(s->fdnet, &readset)) { + N_printf("NE2000: ne2000_ether_recv() nothing to read\n"); + return -1; + } + ret = read(s->fdnet, buf, bufsiz); - ioselect_complete(s->fdnet); if (ret < 0) { N_printf("NE2000: ne2000_ether_recv() read failed\n"); return -1; @@ -316,17 +345,12 @@ static int ne2000_ether_recv(NE2000State *s, uint8_t *buf, int bufsiz) return ret; } -static void ne2000_receive_req_async(int fd, void *arg) +static void ne2000_receive_req_async(void *arg) { NE2000State *s = &ne2000state; uint8_t mybuf[MAX_ETH_FRAME_SIZE]; int ret; - if (ne2000_buffer_full(s)) { - N_printf("NE2000: ne2000_receive_req_async() called but buffer full\n"); - return; - } - N_printf("NE2000: ne2000_receive_req_async() called\n"); ret = ne2000_ether_recv(s, mybuf, sizeof mybuf); @@ -470,7 +494,6 @@ static size_t ne2000_receive(NE2000State *s, const uint8_t *buf, size_t size_) static void ne2000_ioport_write(NE2000State *s, uint32_t addr, uint32_t val) { int offset, page, index; - int old_full = ne2000_buffer_full(s); N_printf("NE2000: ne2000_ioport_write()\n"); @@ -479,14 +502,9 @@ static void ne2000_ioport_write(NE2000State *s, uint32_t addr, uint32_t val) N_printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val); #endif if (addr == E8390_CMD) { - uint32_t old_cmd = s->cmd; /* control register */ s->cmd = val; if (!(val & E8390_STOP)) { /* START bit makes no sense on RTL8029... */ - if (old_cmd & E8390_STOP) { - N_printf("NE2000: enable receiver\n"); - add_to_io_select(s->fdnet, ne2000_receive_req_async, NULL); - } s->isr &= ~ENISR_RESET; /* test specific case: zero length transfer */ if ((val & (E8390_RREAD | E8390_RWRITE)) && @@ -509,11 +527,6 @@ static void ne2000_ioport_write(NE2000State *s, uint32_t addr, uint32_t val) s->cmd &= ~E8390_TRANS; ne2000_update_irq(s); } - } else { - if (!(old_cmd & E8390_STOP)) { - N_printf("NE2000: disable receiver\n"); - remove_from_io_select(s->fdnet); - } } } else { page = s->cmd >> 6; @@ -574,10 +587,6 @@ static void ne2000_ioport_write(NE2000State *s, uint32_t addr, uint32_t val) break; } } - - /* flush if buffer was full */ - if (old_full && !ne2000_buffer_full(s)) - ioselect_complete(s->fdnet); } static uint32_t ne2000_ioport_read(NE2000State *s, uint32_t addr) @@ -869,7 +878,7 @@ static void ne2000_write(NE2000State *s, uint32_t addr, uint64_t data, unsigned /* --------------------------------- */ /* 16 bit io functions - only on data port */ -Bit16u ne2000_io_read16(ioport_t port, void *arg) +Bit16u ne2000_io_read16(ioport_t port) { NE2000State *s = &ne2000state; ioport_t addr = port - NE2000_IOBASE; @@ -882,7 +891,7 @@ Bit16u ne2000_io_read16(ioport_t port, void *arg) return ne2000_read(s, addr, 1); } -void ne2000_io_write16(ioport_t port, Bit16u value, void *arg) +void ne2000_io_write16(ioport_t port, Bit16u value) { NE2000State *s = &ne2000state; ioport_t addr = port - NE2000_IOBASE; @@ -899,7 +908,7 @@ void ne2000_io_write16(ioport_t port, Bit16u value, void *arg) /* handle io reads from ne2000 */ -Bit8u ne2000_io_read8(ioport_t port, void *arg) +Bit8u ne2000_io_read8(ioport_t port) { NE2000State *s = &ne2000state; ioport_t addr = port - NE2000_IOBASE; @@ -912,7 +921,7 @@ Bit8u ne2000_io_read8(ioport_t port, void *arg) /* handle io writes to ne2000 */ -void ne2000_io_write8(ioport_t port, Bit8u value, void *arg) +void ne2000_io_write8(ioport_t port, Bit8u value) { NE2000State *s = &ne2000state; ioport_t addr = port - NE2000_IOBASE; diff --git a/src/base/dev/pic/Makefile b/src/base/dev/pic/Makefile index 475e459..b91efb2 100644 --- a/src/base/dev/pic/Makefile +++ b/src/base/dev/pic/Makefile @@ -2,7 +2,15 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.conf -CFILES = pic.c irq.c i8259.c i8259_common.c + +CFILES = pic.c +HFILES = +DEPENDS= pic.d + +ALL = $(CFILES) $(HFILES) README.pic + +OBJS = pic.o + all: lib diff --git a/src/base/dev/pic/i8259.c b/src/base/dev/pic/i8259.c deleted file mode 100644 index 2224759..0000000 --- a/src/base/dev/pic/i8259.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * QEMU 8259 interrupt controller emulation - * - * Copyright (c) 2003-2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "i8259.h" -#include "i8259_internal.h" - -/* debug PIC */ -//#define DEBUG_PIC - -//#define DEBUG_IRQ_LATENCY - -#define trace_pic_update_irq(...) -#define trace_pic_set_irq(...) -#define trace_pic_interrupt(...) -#define trace_pic_ioport_write(...) -#define trace_pic_ioport_read(...) -#define qemu_log_mask(...) - -#define TYPE_I8259 "isa-i8259" - -#ifdef DEBUG_IRQ_LATENCY -static int64_t irq_time[16]; -#endif -extern PICCommonState *slave_pic; - -/* return the highest priority found in mask (highest = smallest - number). Return 8 if no irq */ -static int get_priority(PICCommonState *s, int mask) -{ - int priority; - - if (mask == 0) { - return 8; - } - priority = 0; - while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0) { - priority++; - } - return priority; -} - -/* return the pic wanted interrupt. return -1 if none */ -static int pic_get_irq(PICCommonState *s) -{ - int mask, cur_priority, priority; - - mask = s->irr & ~s->imr; - priority = get_priority(s, mask); - if (priority == 8) { - return -1; - } - /* compute current priority. If special fully nested mode on the - master, the IRQ coming from the slave is not taken into account - for the priority computation. */ - mask = s->isr; - if (s->special_mask) { - mask &= ~s->imr; - } - if (s->special_fully_nested_mode && s->master) { - mask &= ~(1 << 2); - } - cur_priority = get_priority(s, mask); - if (priority < cur_priority) { - /* higher priority found: an irq should be generated */ - return (priority + s->priority_add) & 7; - } else { - return -1; - } -} - -/* Update INT output. Must be called every time the output may have changed. */ -static void pic_update_irq(PICCommonState *s) -{ - int irq; - - irq = pic_get_irq(s); - if (irq >= 0) { - trace_pic_update_irq(s->master, s->imr, s->irr, s->priority_add); - qemu_irq_raise(s->int_out[0]); - } else { - qemu_irq_lower(s->int_out[0]); - } -} - -/* set irq level. If an edge is detected, then the IRR is set to 1 */ -void pic_set_irq(PICCommonState *s, int irq, int level) -{ - int mask = 1 << irq; - int irq_index = s->master ? irq : irq + 8; - - trace_pic_set_irq(s->master, irq, level); - pic_stat_update_irq(irq_index, level); - -#ifdef DEBUG_IRQ_LATENCY - if (level) { - irq_time[irq_index] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - } -#endif - - if (s->elcr & mask) { - /* level triggered */ - if (level) { - s->irr |= mask; - s->last_irr |= mask; - } else { - s->irr &= ~mask; - s->last_irr &= ~mask; - } - } else { - /* edge triggered */ - if (level) { - if ((s->last_irr & mask) == 0) { - s->irr |= mask; - } - s->last_irr |= mask; - } else { - s->irr &= ~mask; // dosemu2 mod: clear IRR bit even in edge mode - s->last_irr &= ~mask; - } - } - pic_update_irq(s); -} - -/* acknowledge interrupt 'irq' */ -static void pic_intack(PICCommonState *s, int irq) -{ - if (s->auto_eoi) { - if (s->rotate_on_auto_eoi) { - s->priority_add = (irq + 1) & 7; - } - } else { - s->isr |= (1 << irq); - } - /* We don't clear a level sensitive interrupt here */ - if (!(s->elcr & (1 << irq))) { - s->irr &= ~(1 << irq); - } - pic_update_irq(s); -} - -int pic_read_irq(PICCommonState *s) -{ - int irq, irq2, intno; - - irq = pic_get_irq(s); - if (irq >= 0) { - if (irq == 2) { - irq2 = pic_get_irq(slave_pic); - if (irq2 >= 0) { - pic_intack(slave_pic, irq2); - } else { - /* spurious IRQ on slave controller */ - irq2 = 7; - } - intno = slave_pic->irq_base + irq2; - } else { - intno = s->irq_base + irq; - } - pic_intack(s, irq); - } else { - /* spurious IRQ on host controller */ - irq = 7; - intno = s->irq_base + irq; - } - - if (irq == 2) { - irq = irq2 + 8; - } - -#ifdef DEBUG_IRQ_LATENCY - printf("IRQ%d latency=%0.3fus\n", - irq, - (double)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - - irq_time[irq]) * 1000000.0 / NANOSECONDS_PER_SECOND); -#endif - - trace_pic_interrupt(irq, intno); - return intno; -} - -static void pic_init_reset(PICCommonState *s) -{ - pic_reset_common(s); - pic_update_irq(s); -} - -void qemu_pic_reset(PICCommonState *s) -{ - s->elcr = 0; - pic_init_reset(s); -} - -void pic_ioport_write(PICCommonState *s, hwaddr addr64, - uint64_t val64, unsigned size) -{ - uint32_t addr = addr64; - uint32_t val = val64; - int priority, cmd, irq; - - trace_pic_ioport_write(s->master, addr, val); - - if (s->poll) { // dosemu2 mod: poll extension - s->fake_irr &= ~(1 << val); - pic_intack(s, val); - s->poll = 0; - } else if (addr == 0) { - if (val & 0x10) { - pic_init_reset(s); - s->init_state = 1; - s->init4 = val & 1; - s->single_mode = val & 2; - if (val & 0x08) { - qemu_log_mask(LOG_UNIMP, - "i8259: level sensitive irq not supported\n"); - } - } else if (val & 0x08) { - if (val & 0x04) { - s->poll = 1; - } - if (val & 0x02) { - s->read_reg_select = val & 1; - } - if (val & 0x40) { - s->special_mask = (val >> 5) & 1; - } - } else { - cmd = val >> 5; - switch (cmd) { - case 0: - case 4: - s->rotate_on_auto_eoi = cmd >> 2; - break; - case 1: /* end of interrupt */ - case 5: - priority = get_priority(s, s->isr); - if (priority != 8) { - irq = (priority + s->priority_add) & 7; - s->isr &= ~(1 << irq); - if (cmd == 5) { - s->priority_add = (irq + 1) & 7; - } - pic_update_irq(s); - } - break; - case 3: - irq = val & 7; - s->isr &= ~(1 << irq); - pic_update_irq(s); - break; - case 6: - s->priority_add = (val + 1) & 7; - pic_update_irq(s); - break; - case 7: - irq = val & 7; - s->isr &= ~(1 << irq); - s->priority_add = (irq + 1) & 7; - pic_update_irq(s); - break; - default: - /* no operation */ - break; - } - } - } else { - switch (s->init_state) { - case 0: - /* normal mode */ - s->imr = val; - pic_update_irq(s); - break; - case 1: - s->irq_base = val & 0xf8; - s->init_state = s->single_mode ? (s->init4 ? 3 : 0) : 2; - break; - case 2: - if (s->init4) { - s->init_state = 3; - } else { - s->init_state = 0; - } - break; - case 3: - s->special_fully_nested_mode = (val >> 4) & 1; - s->auto_eoi = (val >> 1) & 1; - s->init_state = 0; - break; - } - } -} - -uint64_t pic_ioport_read(PICCommonState *s, hwaddr addr, unsigned size) -{ - int ret; - -#if 0 - if (s->poll) { -#else - if (s->poll && addr == 0) { // dosemu2 mod -#endif - ret = pic_get_irq(s); - if (ret >= 0) { - pic_intack(s, ret); - ret |= 0x80; - } else { - ret = 0; - } - s->poll = 0; - } else { - if (addr == 0) { - if (s->read_reg_select) { - ret = s->isr; - } else { - ret = s->irr | s->fake_irr; - } - } else { - ret = s->imr; - } - } - trace_pic_ioport_read(s->master, addr, ret); - return ret; -} - -int pic_get_output(PICCommonState *s) -{ - return (pic_get_irq(s) >= 0); -} - -void elcr_ioport_write(PICCommonState *s, hwaddr addr, - uint64_t val, unsigned size) -{ - s->elcr = val & s->elcr_mask; -} - -uint64_t elcr_ioport_read(PICCommonState *s, hwaddr addr, unsigned size) -{ - return s->elcr; -} diff --git a/src/base/dev/pic/i8259.h b/src/base/dev/pic/i8259.h deleted file mode 100644 index 93d1bdc..0000000 --- a/src/base/dev/pic/i8259.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef HW_I8259_H -#define HW_I8259_H - -#include - -typedef uint32_t hwaddr; - -/* i8259.c */ - -typedef struct PICCommonState PICCommonState; -int pic_get_output(PICCommonState *s); -int pic_read_irq(PICCommonState *s); - -void qemu_pic_reset(PICCommonState *s); -void pic_set_irq(PICCommonState *s, int irq, int level); -void pic_ioport_write(PICCommonState *s, hwaddr addr64, - uint64_t val64, unsigned size); -uint64_t pic_ioport_read(PICCommonState *s, hwaddr addr, unsigned size); -void elcr_ioport_write(PICCommonState *s, hwaddr addr, - uint64_t val, unsigned size); -uint64_t elcr_ioport_read(PICCommonState *s, hwaddr addr, unsigned size); - -#endif diff --git a/src/base/dev/pic/i8259_common.c b/src/base/dev/pic/i8259_common.c deleted file mode 100644 index 85c079c..0000000 --- a/src/base/dev/pic/i8259_common.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * QEMU 8259 - common bits of emulated and KVM kernel model - * - * Copyright (c) 2003-2004 Fabrice Bellard - * Copyright (c) 2011 Jan Kiszka, Siemens AG - * - * 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 "utilities.h" -#include "i8259.h" -#include "i8259_internal.h" - -static int irq_level[16]; -static uint64_t irq_count[16]; - -void pic_reset_common(PICCommonState *s) -{ - s->last_irr = 0; - s->irr &= s->elcr; - s->imr = 0; - s->isr = 0; - s->priority_add = 0; - s->irq_base = 0; - s->read_reg_select = 0; - s->poll = 0; - s->special_mask = 0; - s->init_state = 0; - s->auto_eoi = 0; - s->rotate_on_auto_eoi = 0; - s->special_fully_nested_mode = 0; - s->init4 = 0; - s->single_mode = 0; - /* Note: ELCR is not reset */ - s->fake_irr = 0; -} - -void pic_stat_update_irq(int irq, int level) -{ - if (level != irq_level[irq]) { - irq_level[irq] = level; - if (level == 1) { - irq_count[irq]++; - } - } -} - -bool pic_get_statistics(PICCommonState *s, - uint64_t **irq_counts, unsigned int *nb_irqs) -{ - if (s->master) { - *irq_counts = irq_count; - *nb_irqs = ARRAY_SIZE(irq_count); - } else { - *irq_counts = NULL; - *nb_irqs = 0; - } - - return true; -} diff --git a/src/base/dev/pic/i8259_internal.h b/src/base/dev/pic/i8259_internal.h deleted file mode 100644 index c803e1b..0000000 --- a/src/base/dev/pic/i8259_internal.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * QEMU 8259 - internal interfaces - * - * Copyright (c) 2011 Jan Kiszka, Siemens AG - * - * 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 QEMU_I8259_INTERNAL_H -#define QEMU_I8259_INTERNAL_H - -#include -#include -#include "irq.h" -#include "i8259.h" - -struct PICCommonState { - uint8_t last_irr; /* edge detection */ - uint8_t irr; /* interrupt request register */ - uint8_t imr; /* interrupt mask register */ - uint8_t isr; /* interrupt service register */ - uint8_t priority_add; /* highest irq priority */ - uint8_t irq_base; - uint8_t read_reg_select; - uint8_t poll; - uint8_t special_mask; - uint8_t init_state; - uint8_t auto_eoi; - uint8_t rotate_on_auto_eoi; - uint8_t special_fully_nested_mode; - uint8_t init4; /* true if 4 byte init */ - uint8_t single_mode; /* true if slave pic is not initialized */ - uint8_t elcr; /* PIIX edge/trigger selection*/ - uint8_t elcr_mask; - struct IRQState _int_out; - qemu_irq int_out[1]; - uint32_t master; /* reflects /SP input pin */ - uint32_t iobase; - uint32_t elcr_addr; - uint8_t fake_irr; /* dosemu2 extension */ -}; - -void pic_reset_common(PICCommonState *s); -void pic_stat_update_irq(int irq, int level); -bool pic_get_statistics(PICCommonState *s, - uint64_t **irq_counts, unsigned int *nb_irqs); - -#endif /* QEMU_I8259_INTERNAL_H */ diff --git a/src/base/dev/pic/irq.c b/src/base/dev/pic/irq.c deleted file mode 100644 index 216bfc6..0000000 --- a/src/base/dev/pic/irq.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * QEMU IRQ/GPIO common code. - * - * Copyright (c) 2007 CodeSourcery. - * - * 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 "irq.h" - -void qemu_set_irq(qemu_irq irq, int level) -{ - if (!irq) - return; - - irq->handler(irq->opaque, irq->n, level); -} diff --git a/src/base/dev/pic/irq.h b/src/base/dev/pic/irq.h deleted file mode 100644 index c199e90..0000000 --- a/src/base/dev/pic/irq.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef QEMU_IRQ_H -#define QEMU_IRQ_H - -/* Generic IRQ/GPIO pin infrastructure. */ - -#define TYPE_IRQ "irq" - -typedef struct IRQState *qemu_irq; -typedef void (*qemu_irq_handler)(void *opaque, int n, int level); -struct IRQState { - qemu_irq_handler handler; - void *opaque; - int n; -}; - -void qemu_set_irq(qemu_irq irq, int level); - -static inline void qemu_irq_raise(qemu_irq irq) -{ - qemu_set_irq(irq, 1); -} - -static inline void qemu_irq_lower(qemu_irq irq) -{ - qemu_set_irq(irq, 0); -} - -static inline void qemu_irq_pulse(qemu_irq irq) -{ - qemu_set_irq(irq, 1); - qemu_set_irq(irq, 0); -} - -#endif diff --git a/src/base/dev/pic/pic.c b/src/base/dev/pic/pic.c index a9c9bcf..feef69b 100644 --- a/src/base/dev/pic/pic.c +++ b/src/base/dev/pic/pic.c @@ -1,294 +1,992 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. +/* DANG_BEGIN_MODULE * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * REMARK + * pic.c is a fairly complete emulation of both 8259 Priority Interrupt + * Controllers. It also includes provision for 16 lower level interrupts. + * This implementation supports the following i/o commands: * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * VERB + * ICW1 bits 0 and 1 number of ICWs to expect + * ICW2 bits 3 - 7 base address of IRQs + * ICW3 no bits accepted but ignored + * ICW4 no bits accepted but ignored + * + * OCW1 all bits sets interrupt mask + * OCW2 bits 7,5-0 EOI commands only + * OCW3 bits 0,1,5,6 select read register, + * select special mask mode + * + * Reads of both pic ports are supported completely. + * /VERB + * + * An important concept to understand in pic is the interrupt level. + * This is a value which represents the priority of the current interrupt. + * It is used to identify interrupts, and IRQs can be mapped to these + * levels(see pic.h~). The currently active interrupt level is maintained + * in pic_ilevel, which is globally available, A pic_ilevel of 32 means + * no interrupts are active; 0, the highest priority, represents the NMI. + * IRQs 0 through 15 are mapped, in priority order, to values of 1-15 + * (there is no IRQ2 in an AT). Values of 16 - 31 represent additional + * interrupt levels available for internal dosemu usage. + * + * More detail is available in the file README.pic + * + * Debug information: + * + * A debug flag of +r or 1r will generate debug messages concerning + * reads and writes to pic ports. Many of these messages are not yet + * implemented. A debug flag of 2r will generate messages concerning + * activation, nesting, and completion of interrupts. A flag of -r + * or 0r will turn off debugging messages. Flags may be combined: + * to get both 1r and 2r, use a value of 3r. + * + * /REMARK + * DANG_END_MODULE */ /* - * Purpose: glue to qemu PIC impl. + * > + * > In 0.66.x the new interrupt is scheduled too early, and restore_rm_regs() + * > is never called. Then the crash. + * > + * > There are at least 2 problems with this kind of code: + * > 1) avoiding interrupt reentrancy + * > 2) avoiding too early interrupt scheduling + * > * - * Author: stsp + * You have run into an old problem, which was created through attempts + * (not by me) to speed up pic by creating holes in its re-entrancy protection. + * As I released pic, it was quite safe on this score, however, that made + * dosemu unpleasantly slow. For everyone's edification, here's the problem: * + * As dos is designed, it is sometimes necessary to presume that an interrupt + * (most often the timer, but sometimes the keyboard or even a serial port) + * could not possibly re-trigger before a certain amount of time has elapsed. + * Sloppy dos programmers have also often made this assumption even when it was + * not necessary. + * + * Dosemu breaks this assumption, because dos doesn't always have the entire + * machine, and interrupts can "pile-up" while other processes are running. + * As far as pic (hardware or emulated) is concerned, an interrupt ends + * when the interrupt acknowledge is sent to pic. However, to avoid + * re-entrancy, pic.c points the iret to a HLT, which is trapped, and used to + * allow re-triggerring of an interrupt. This works, and would completely + * eliminate the above problem, but there's more to the story. + * + * Since some programs put great piles of code inside an interrupt ("I've ACK'd + * the interrupt, what's the hurry on the IRET?"), this kind of hold-off slows + * dosemu down. A few (2 or 3) people have modified pic since I released it + * to create holes in the hold-off mechanism, citing the need for more speed. + * They were certainly right that speed was needed, but I could never get them + * to understand the problem they were creating. These changes are what's + * creating the re-entrancy, I believe. + * + * To make matters worse, dos uses IRETs for software interrupts, even inside + * hardware interrupt routines. So the only reliable way to catch the IRET of + * a hardware interrupt is to point it to a HLT by modifying the stack. Please + * don't question this, I've many hours of debugging time that demonstrated + * this quite thoroughly. + * + * BUT...task-switching environments (MS-Win) use hardware interrupts (mostly + * timer and keyboard, but sometimes serial, too) to switch tasks. When a new + * task is created, there is no address pointing to a HLT on the (new) stack, + * so the end of the interrupt code will never be sensed, and the re-trigger + * protection will lock up dosemu. So it is necessary to detect this event, + * and decide that the interrupt has terminated, or we'll never let the timer + * (or keyboard, etc. as the case may be) interrupt re-trigger. So, in a way, + * we MUST create some kind of hole in the hold-off process. + * + * The entire pic debate is one of finding the right kind of hole to make, and + * the trade-off is robustness vs. speed. Since the task switch problem only + * occurs on the initial invocation of a dos task (when a new stack is built), + * I elected to use a conservative hole, to maintain robustness. Others have + * since modified pic.c to gain speed, often without adequate testing of + * robustness. + * + * There's lots of re-entrancy protection in pic, but it has largely been + * defeated by speed-up efforts. Perhaps the best fix is to re-visit those + * speed-up efforts, and see if a better solution can't be found. + * + * My next thing to try was to put back the correct pic_icount stuff and see if + * I can't set up separate HLTs for each IRQ, automatically releasing any + * pending (pic_pirr) interrupts when their HLT is encountered. The pic_icount + * and related stuf may still be needed for stack switches. This may be + * enough to gain the full speed-up without creating significant holes. + * + * The other thing I want to do is some timer changes to better guarantee + * interrupts get activated in their proper order. This is a bit messy, and + * I've got the code somewhere. It involves threading the timer queue. Some of + * it may already be done, but I think not. + * + * Larry */ -#include + +#include +#include + #include "port.h" -#include "sig.h" -#include "dosemu_debug.h" -#include "i8259.h" -#include "i8259_internal.h" +#include "hlt.h" +#include "bitops.h" +#include "mhpdbg.h" +#include "memory.h" +#include +#include "cpu.h" +#include "emu.h" +#include "timers.h" +#include "iodev.h" +#include "emudpmi.h" +#include "serial.h" +#include "int.h" +#include "ipx.h" #include "pic.h" -static PICCommonState pic[2]; -PICCommonState *slave_pic; -static pthread_mutex_t pic_mtx = PTHREAD_MUTEX_INITIALIZER; +#undef us +#define us unsigned +static void pic_activate(void); -static void write_pic0(ioport_t port, Bit8u value, void *arg) +#define TIMER0_FLOOD_THRESHOLD 50000 + +static unsigned long pic1_isr; /* second isr for pic1 irqs */ +static unsigned long pic_irq2_ivec = 0; + +unsigned long pic_irq_list[] = {PIC_IRQ0, PIC_IRQ1, PIC_IRQ9, PIC_IRQ3, + PIC_IRQ4, PIC_IRQ5, PIC_IRQ6, PIC_IRQ7, + PIC_IRQ8, PIC_IRQ9, PIC_IRQ10, PIC_IRQ11, + PIC_IRQ12, PIC_IRQ13, PIC_IRQ14, PIC_IRQ15}; +hitimer_t pic_dos_time; /* dos time of last interrupt,1193047/sec.*/ +hitimer_t pic_sys_time; /* system time set by pic_watch */ + +/* + * pic_pirr contains a bit set for each interrupt which has attempted to + * re-trigger. + * + * pic_icount is an attempt to count active interrupts. Pending (pic_pirr) + * interrupts are released when pic_icount gets back to zero (as designed). + * Haven't looked how it is now, this is one thing others have played with. + * + * pic_watch() has the primary job of releasing interrupts when a stack switch + * occurs. + */ + +/* PIC "registers", plus a few more */ + +static unsigned long pic_irr; /* interrupt request register */ +static unsigned long pic0_isr; /* interrupt in-service register */ +#define pic_isr (pic0_isr | pic1_isr) +static unsigned int pic_iflag; /* interrupt enable flag: en-/dis- =0/0xfffe */ +static unsigned long pic_irqall = 0xfffe; /* bits for all IRQs set. */ + +static unsigned long pic0_imr = 0xf800; /* interrupt mask register, pic0 */ +static unsigned long pic1_imr = 0x0660; /* interrupt mask register, pic1 */ +static unsigned long pic_imr = 0xfff8; /* interrupt mask register */ +static unsigned int pic_vm86_count = 0; /* count of times 'round the vm86 loop*/ +static unsigned int pic_dpmi_count = 0; /* count of times 'round the dpmi loop*/ +static unsigned long pic1_mask = 0x07f8; /* bits set for pic1 levels */ +static unsigned long pic_smm = 0; /* 32=>special mask mode, 0 otherwise */ + +static unsigned long pic_pirr; /* pending requests: ->irr when icount==0 */ + +static hitimer_t pic_ltime[33] = /* timeof last pic request honored */ + {NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, + NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, + NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, + NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, + NEVER}; + hitimer_t pic_itime[33] = /* time to trigger next interrupt */ + {NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, + NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, + NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, + NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, + NEVER}; + +#define PNULL (void *) 0 +static struct lvldef pic_iinfo[32] = { +{PNULL,PNULL,0x02}, {PNULL,PNULL,0x08}, {PNULL,PNULL,0x09}, {PNULL,PNULL,0x70}, +{PNULL,PNULL,0x71}, {PNULL,PNULL,0x72}, {PNULL,PNULL,0x73}, {PNULL,PNULL,0x74}, +{PNULL,PNULL,0x75}, {PNULL,PNULL,0x76}, {PNULL,PNULL,0x77}, {PNULL,PNULL,0x0b}, +{PNULL,PNULL,0x0c}, {PNULL,PNULL,0x0d}, {PNULL,PNULL,0x0e}, {PNULL,PNULL,0x0f}, +{PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, +{PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, +{PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, +{PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00} +}; + +static void do_irq(int ilevel); +static int pic_get_ilevel(void); + +/* + * run_irq() checks for and runs any interrupts requested in pic_irr + * do_irq() runs the dos interrupt for the current irq + * set_pic0_imr() sets pic0 interrupt mask register \\ + * set_pic1_imr() sets pic1 interrupt mask register || + * get_pic0_imr() returns pic0 interrupt mask register || + * get_pic1_imr() returns pic1 interrupt mask register || called by read_ + * get_pic0_isr() returns pic0 in-service register || and write_ picX + * get_pic1_isr() returns pic1 in-service register || + * get_pic0_irr() returns pic0 interrupt request register || + * get_pic1_irr() returns pic1 interrupt request register || + * set_pic0_base() sets base interrupt for irq0 - irq7 || + * set_pic1_base() sets base interrupt for irq8 - irq15 // + * write_pic0() processes write to pic0 i/o + * write_pic1() processes write to pic1 i/o + * read_pic0() processes read from pic0 i/o + * read_pic1() processes read from pic1 i/o + * pic_print() print pic debug messages + * pic_watch() catch any un-reset irets, increment time + * pic_push() save active dos interrupt level + * pic_pop() restore active dos interrupt level + * pic_pending() detect if interrupt is requested and unmasked + */ + +#define set_pic0_imr(x) pic0_imr=pic0_to_emu(x);pic_set_mask +#define set_pic1_imr(x) pic1_imr=(((long)x)<<3);pic_set_mask +#define get_pic0_imr() emu_to_pic0(pic0_imr) +#define get_pic1_imr() (pic1_imr>>3) +#define get_pic0_isr() emu_to_pic0(pic0_isr) +#define get_pic1_isr() (pic1_isr>>3) +#define get_pic0_irr() emu_to_pic0(pic_irr) +#define get_pic1_irr() (pic_irr>>3) + + +/* State flags. picX_cmd is only read by debug output */ + +static unsigned char pic0_isr_requested; /* 0/1 =>next port 0 read= irr/isr */ +static unsigned char pic1_isr_requested; +static unsigned char pic0_icw_state; /* 0-3=>next port 1 write= mask,ICW2,3,4 */ +static unsigned char pic1_icw_state; +static unsigned char pic0_cmd; /* 0-3=>last port 0 write was none,ICW1,OCW2,3*/ +static unsigned char pic1_cmd; + +//static int pic_pending_masked(uint8_t mask); + +/* DANG_BEGIN_FUNCTION pic_print + * + * This is the pic debug message printer. It writes out some basic + * information, followed by an informative message. The basic information + * consists of: + * interrupt nesting counter change flag (+, -, or blank) + * interrupt nesting count (pic_icount) + * interrupt level change flag (+, -, or blank) + * current interrupt level + * interrupt in-service register + * interrupt mask register + * interrupt request register + * message part one + * decimal data value + * message part two + * + * If the message part 2 pointer is a null pointer, then only message + * part one (without the data value) is printed. + * + * The change flags are there to facilitate grepping for changes in + * pic_ilevel and pic_icount + * + * To avoid line wrap, the first seven values are printed without labels. + * Instead, a header line is printed every 15 messages. + * + * DANG_END_FUNCTION pic_print + */ +#ifdef NO_DEBUGPRINT_AT_ALL +#define pic_print(code,s1,v1,s2) +#define pic_print2(code,s1,v1,s2) +#else +#define pic_print(code,s1,v1,s2) if (debug_level('r')>code){p_pic_print(s1,v1,s2);} +#define pic_print2(code,s1,v1,s2) \ + if (debug_level('r')>code){ \ + log_printf(1, "PIC: %s%"PRIu64"%s\n", s1, v1, s2); \ + } + +static void p_pic_print(const char *s1, int v1, const char *s2) { - r_printf("PIC0: write 0x%x --> 0x%x\n", value, port); - pthread_mutex_lock(&pic_mtx); - pic_ioport_write(&pic[0], port - 0x20, value, 1); - pthread_mutex_unlock(&pic_mtx); - r_printf("PIC0: isr=%x imr=%x irr=%x\n", - pic[0].isr, pic[0].imr, pic[0].irr); + static int oldi = 0, header_count = 0; + int pic_ilevel = find_bit(pic_isr); + char ci; + + if (pic_ilevel > oldi) + ci = '+'; + else if (pic_ilevel < oldi) + ci = '-'; + else + ci = ' '; + oldi = pic_ilevel; + if (!header_count++) + log_printf(1, "PIC: cnt lvl pic_isr pic_imr pic_irr (column headers)\n"); + if (header_count > 15) + header_count = 0; + + if (s2) + log_printf(1, "PIC: %c%2d %08lx %08lx %08lx %s%02d%s\n", + ci, pic_ilevel, pic_isr, pic_imr, pic_irr, s1, v1, s2); + else + log_printf(1, "PIC: %c%2d %08lx %08lx %08lx %s\n", + ci, pic_ilevel, pic_isr, pic_imr, pic_irr, s1); +} +#endif + +static int emu_to_pic0(int flags) +{ + /* + * This function takes the pic0 bits from the overall pic bit field + * and concatenates them into a single byte. + */ + + /* move bits 7654 3xxx xxxx 210x to xxxx xxxx 7654 3210 */ + /* where 76543210 are final 8 bits and x = don't care */ + int pic1 = ((flags & 0b11111111000) ? 4 : 0); + return (((flags >> 1) & 3) | pic1 | (flags >> 8)); } -static void write_pic1(ioport_t port, Bit8u value, void *arg) +static int pic0_to_emu(char flags) { - r_printf("PIC1: write 0x%x --> 0x%x\n", value, port); - pthread_mutex_lock(&pic_mtx); - pic_ioport_write(&pic[1], port - 0xa0, value, 1); - pthread_mutex_unlock(&pic_mtx); - r_printf("PIC1: isr=%x imr=%x irr=%x\n", - pic[1].isr, pic[1].imr, pic[1].irr); + /* This function maps pic0 bits to their positions in priority order */ + /* + * It makes room for the pic1 bits in between. + */ + + /* move bits xxxx xxxx 7654 3210 to 7654 3222 2222 210o */ + /* where 76543210 are original 8 bits, x = don't care, and o = zero */ + /* bit 2 (cascade int) is used to mask/unmask pic1 (Larry) */ + int pic1 = ((flags & 4) ? 0b11111111000 : 0); + return (((flags & 0xf8) << 8) | pic1 | ((flags & 3) << 1)); } -static Bit8u read_pic0(ioport_t port, void *arg) +static void set_pic0_base(unsigned char int_num) { - Bit8u ret; - - pthread_mutex_lock(&pic_mtx); - ret = pic_ioport_read(&pic[0], port - 0x20, 1); - pthread_mutex_unlock(&pic_mtx); - r_printf("PIC0: read 0x%x <-- 0x%x\n", ret, port); - return ret; + unsigned char int_n; + int_n = int_num & 0xf8; /* it's not worth doing a loop */ + pic_iinfo[1].ivec = int_n++; /* irq 0 */ + pic_iinfo[2].ivec = int_n++; /* irq 1 */ + pic_irq2_ivec = int_n++; /* irq 2 */ + pic_iinfo[11].ivec = int_n++; /* irq 3 */ + pic_iinfo[12].ivec = int_n++; /* irq 4 */ + pic_iinfo[13].ivec = int_n++; /* irq 5 */ + pic_iinfo[14].ivec = int_n++; /* irq 6 */ + pic_iinfo[15].ivec = int_n; /* irq 7 */ + return; } -static Bit8u read_pic1(ioport_t port, void *arg) -{ - Bit8u ret; - pthread_mutex_lock(&pic_mtx); - ret = pic_ioport_read(&pic[1], port - 0xa0, 1); - pthread_mutex_unlock(&pic_mtx); - r_printf("PIC1: read 0x%x <-- 0x%x\n", ret, port); - return ret; +static void set_pic1_base(unsigned char int_num) +{ + unsigned char int_n; + int_n = int_num & 0xf8; /* it's not worth doing a loop */ + pic_iinfo[3].ivec = int_n++; /* irq 8 */ + pic_iinfo[4].ivec = int_n++; /* irq 9 */ + pic_iinfo[5].ivec = int_n++; /* irq 10 */ + pic_iinfo[6].ivec = int_n++; /* irq 11 */ + pic_iinfo[7].ivec = int_n++; /* irq 12 */ + pic_iinfo[8].ivec = int_n++; /* irq 13 */ + pic_iinfo[9].ivec = int_n++; /* irq 14 */ + pic_iinfo[10].ivec = int_n; /* irq 15 */ + return; } -static Bit8u read_elcr(ioport_t port, void *arg) -{ - Bit8u ret; - pthread_mutex_lock(&pic_mtx); - ret = elcr_ioport_read(&pic[port & 1], port & 1, 1); - pthread_mutex_unlock(&pic_mtx); - return ret; +/* DANG_BEGIN_FUNCTION write_pic0,write_pic1 + * + * write_pic_0() and write_pic1() implement dos writes to the pic ports. + * They are called by the code that emulates inb and outb instructions. + * Each function implements both ports for the pic: pic0 is on ports + * 0x20 and 0x21; pic1 is on ports 0xa0 and 0xa1. These functions take + * two arguments: a port number (0 or 1) and a value to be written. + * + * DANG_END_FUNCTION + */ +void write_pic0(ioport_t port, Bit8u value) +{ + +/* if port == 0 this must be either an ICW1, OCW2, or OCW3 + * if port == 1 this must be either ICW2, ICW3, ICW4, or load IMR + */ + +#if 0 +static char icw_state, /* !=0 => port 1 does icw 2,3,(4) */ +#endif +static char icw_max_state; /* number of icws expected */ +int ilevel; /* level to reset on outb 0x20 */ + +port -= 0x20; +ilevel = 32; +if (pic_isr) + ilevel=find_bit(pic_isr); +if (ilevel != 32 && !test_bit(ilevel, &pic_irqall)) { + /* this is a fake IRQ, don't allow to reset its ISR bit */ + pic_print(1, "Protecting ISR bit for lvl ", ilevel, " from spurious EOI"); + ilevel = 32; } -static void write_elcr(ioport_t port, Bit8u value, void *arg) -{ - pthread_mutex_lock(&pic_mtx); - elcr_ioport_write(&pic[port & 1], port & 1, value, 1); - pthread_mutex_unlock(&pic_mtx); -} +if (in_dpmi_pm()) + dpmi_return_request(); /* we have to leave the signal context */ -static Bit8u read_firr(ioport_t port, void *arg) -{ - Bit8u ret; - - pthread_mutex_lock(&pic_mtx); - ret = pic[port & 1].fake_irr; - pthread_mutex_unlock(&pic_mtx); - return ret; -} - -static void write_firr(ioport_t port, Bit8u value, void *arg) -{ - pthread_mutex_lock(&pic_mtx); - pic[port & 1].fake_irr = value; - pthread_mutex_unlock(&pic_mtx); -} - -void pic_request(int irq) -{ - PICCommonState *p = pic; - - r_printf("PIC: Requested irq lvl %x\n", irq); - if (irq >= 8) { - irq -= 8; - p++; +if(!port){ /* icw1, ocw2, ocw3 */ + if(value&0x10){ /* icw1 */ + icw_max_state = (value & 1) + 1; + if(value&2) ++icw_max_state; + pic0_icw_state = 1; + pic0_cmd=1; } - pthread_mutex_lock(&pic_mtx); - pic_set_irq(p, irq, 1); - pthread_mutex_unlock(&pic_mtx); - r_printf("PIC%i: isr=%x imr=%x irr=%x\n", - p->master ? 0 : 1, p->isr, p->imr, p->irr); -} -void pic_untrigger(int irq) -{ - PICCommonState *p = pic; - - r_printf("PIC: irq lvl %x untriggered\n", irq); - if (irq >= 8) { - irq -= 8; - p++; + else if (value&0x08){ /* ocw3 */ + if(value&2) pic0_isr_requested = value&1; + if(value&64)pic_smm = value&32; /* must be either 0 or 32, conveniently */ + pic0_cmd=3; } - pthread_mutex_lock(&pic_mtx); - pic_set_irq(p, irq, 0); - pthread_mutex_unlock(&pic_mtx); - r_printf("PIC%i: isr=%x imr=%x irr=%x\n", - p->master ? 0 : 1, p->isr, p->imr, p->irr); + else if((value&0xb8) == 0x20) { /* ocw2 */ + clear_bit(ilevel,&pic0_isr); /* the famous outb20 */ + pic_print(1,"EOI resetting bit ",ilevel, " on pic0"); +#if 1 + /* XXX hack: to avoid timer interrupt re-entrancy, + * we try to disable interrupts in a hope IRET will re-enable + * them. This fixes Tetris Classic problem: + * https://github.com/stsp/dosemu2/issues/99 + * Need to check also IMR because DPMI uses another hack + * that masks the IRQs. */ + if (ilevel == PIC_IRQ0 && isset_IF() && !(pic_imr & (1 << ilevel))) { + r_printf("PIC: disabling interrupts to avoid reentrancy\n"); + clear_IF_timed(); + } +#endif + pic0_cmd=2; + } + } +else /* icw2, icw3, icw4, or mask register */ + switch(pic0_icw_state){ + case 0: /* mask register */ + set_pic0_imr(value); + pic_print(1, "Set mask to ", value, " on pic0"); + break; + case 1: /* icw2 */ + set_pic0_base(value); + /* Fall through */ + default: /* icw2, 3, and 4*/ + if(pic0_icw_state++ >= icw_max_state) pic0_icw_state=0; + } } -int pic_get_inum(void) -{ - int inum; - pthread_mutex_lock(&pic_mtx); - if (!slave_pic) - slave_pic = &pic[1]; - inum = pic_read_irq(&pic[0]); - pthread_mutex_unlock(&pic_mtx); - r_printf("PIC: Running interrupt %x\n", inum); - return inum; +void write_pic1(ioport_t port, Bit8u value) +{ +/* if port == 0 this must be either an ICW1, OCW2, or OCW3 */ +/* if port == 1 this must be either ICW2, ICW3, ICW4, or load IMR */ +static char /* icw_state, */ /* !=0 => port 1 does icw 2,3,(4) */ + icw_max_state; /* number of icws expected */ +int ilevel; /* level to reset on outb 0x20 */ + +port -= 0xa0; +ilevel = 32; +if (pic_isr) + ilevel=find_bit(pic_isr); +if (ilevel != 32 && !test_bit(ilevel, &pic_irqall)) { + /* this is a fake IRQ, don't allow to reset its ISR bit */ + pic_print(1, "Protecting ISR bit for lvl ", ilevel, " from spurious EOI"); + ilevel = 32; } -static void set_irq_level(void *opaque, int n, int level) -{ - /* running under mutex */ - r_printf("PIC: Cascade irq %i set to %i\n", n, level); - pic_set_irq(opaque, n, level); +if (in_dpmi_pm()) + dpmi_return_request(); /* we have to leave the signal context */ + +if(!port){ /* icw1, ocw2, ocw3 */ + if(value&0x10){ /* icw1 */ + icw_max_state = (value & 1) + 1; + if(value&2) ++icw_max_state; + pic1_icw_state = 1; + pic1_cmd=1; + } + else if (value&0x08) { /* ocw3 */ + if(value&2) pic1_isr_requested = value&1; + if(value&64)pic_smm = value&32; /* must be either 0 or 32, conveniently */ + pic1_cmd=3; + } + else if((value&0xb8) == 0x20) { /* ocw2 */ + clear_bit(ilevel,&pic1_isr); + pic_print(1,"EOI resetting bit ",ilevel, " on pic1"); + pic0_cmd=2; + } + } +else /* icw2, icw3, icw4, or mask register */ + switch(pic1_icw_state){ + case 0: /* mask register */ + set_pic1_imr(value); + pic_print(1, "Set mask to ", value, " on pic1"); + break; + case 1: /* icw 2 */ + set_pic1_base(value); + /* Fall through */ + default: /* icw 2,3 and 4 */ + if(pic1_icw_state++ >= icw_max_state) pic1_icw_state=0; + } } -static void int_raise(void *arg) + +/* DANG_BEGIN_FUNCTION read_pic0,read_pic1 + * + * read_pic0 and read_pic1 return the values for the interrupt mask register + * (port 1), or either the in service register or interrupt request register, + * as determined by the last OCW3 command (port 0). These functions take + * a single parameter, which is a port number (0 or 1). They are called by + * code that emulates the inb instruction. + * + * DANG_END_FUNCTION + */ +Bit8u read_pic0(ioport_t port) { - int level = (uintptr_t)arg; - /* If we are here, guest code already interrupted. So nothing to do. */ - r_printf("int level from thread set to %i\n", level); + port -= 0x20; + if(port) return((unsigned char)get_pic0_imr()); + if(pic0_isr_requested) return((unsigned char)get_pic0_isr()); + return((unsigned char)get_pic0_irr()); } -static void set_int_out(void *opaque, int n, int level) -{ - pthread_t thr = (pthread_t)opaque; - r_printf("PIC: int out set to %i\n", level); - if (!pthread_equal(thr, pthread_self())) - add_thread_callback(int_raise, (void *)(uintptr_t)level, "pic"); +Bit8u read_pic1(ioport_t port) +{ + port -= 0xa0; + if(port) return((unsigned char)get_pic1_imr()); + if(pic1_isr_requested) return((unsigned char)get_pic1_isr()); + return((unsigned char)get_pic1_irr()); } -void pic_init(void) +/* DANG_BEGIN_FUNCTION pic_seti + * + * pic_seti is used to initialize an interrupt for dosemu. It requires + * four parameters. The first parameter is the interrupt level, which + * may select the NMI, any of the IRQs, or any of the 16 extra levels + * (16 - 31). The second parameter is the dosemu function to be called + * when the interrupt is activated. This function should call do_irq() + * if the DOS interrupt is really to be activated. If there is no special + * dosemu code to call, the second parameter can specify do_irq(), but + * see that description for some special considerations. + * The third parameter is a number of an interrupt to activate if there is + * no default interrupt for this ilevel. + * The fourth parameter is the dosemu function to be called from do_irq(). + * Required by some internal dosemu drivers that needs some additional code + * before calling an actual handler. This function MUST provide a EOI at + * the end of a callback. + * + * DANG_END_FUNCTION + */ +void pic_seti(unsigned int level, int (*func)(int), unsigned int ivec, + void (*callback)(void)) { - /* do any one-time initialization of the PIC */ - emu_iodev_t io_device; - - /* 8259 PIC (Programmable Interrupt Controller) */ - io_device.read_portb = read_pic0; - io_device.write_portb = write_pic0; - io_device.read_portw = NULL; - io_device.write_portw = NULL; - io_device.read_portd = NULL; - io_device.write_portd = NULL; - io_device.handler_name = "8259 PIC0"; - io_device.start_addr = 0x0020; - io_device.end_addr = 0x0021; - port_register_handler(io_device, 0); - - io_device.handler_name = "8259 PIC1"; - io_device.start_addr = 0x00A0; - io_device.end_addr = 0x00A1; - io_device.read_portb = read_pic1; - io_device.write_portb = write_pic1; - port_register_handler(io_device, 0); - - io_device.handler_name = "ELCR"; - io_device.start_addr = 0x04D0; - io_device.end_addr = 0x04D1; - io_device.read_portb = read_elcr; - io_device.write_portb = write_elcr; - port_register_handler(io_device, 0); - - io_device.handler_name = "fake irr"; - io_device.start_addr = 0x04D2; - io_device.end_addr = 0x04D3; - io_device.read_portb = read_firr; - io_device.write_portb = write_firr; - port_register_handler(io_device, 0); - - /* set up cascading bits */ - pic[0].master = 1; - pic[0].int_out[0] = &pic[0]._int_out; - pic[0]._int_out.handler = set_int_out; - pic[0]._int_out.opaque = (void *)pthread_self(); - pic[0]._int_out.n = 0; - - pic[1].int_out[0] = &pic[1]._int_out; - pic[1]._int_out.handler = set_irq_level; - pic[1]._int_out.opaque = &pic[0]; - pic[1]._int_out.n = 2; - /* set up qemu extensions */ - pic[0].elcr_mask = 0xf8; - pic[1].elcr_mask = 0xde; + if(level>=32) return; + if(pic_iinfo[level].func) { + if(pic_iinfo[level].func != func) { + error("Attempt to register more than one handler for IRQ level %i (%p %p)\n", + level, pic_iinfo[level].func, func); + config.exitearly = 1; + } else { + error("Handler for IRQ level %i was registered more than once! (%p)\n", + level, func); + } + } + pic_iinfo[level].func = func; + if(callback) { + pic_iinfo[level].callback = callback; + set_bit(level, &pic_irqall); + } + if(level>15) pic_iinfo[level].ivec = ivec; } -void pic_reset(void) +static int pic_isset_IF(void) { - qemu_pic_reset(&pic[0]); - qemu_pic_reset(&pic[1]); + if (in_dpmi_pm()) + return dpmi_isset_IF(); + return isset_IF(); } -/* PIC extensions */ - -Bit8u pic0_get_base(void) +void run_irqs(void) +/* find the highest priority unmasked requested irq and run it */ { - Bit8u ret; + int local_pic_ilevel, ret; - pthread_mutex_lock(&pic_mtx); - ret = pic[0].irq_base; - pthread_mutex_unlock(&pic_mtx); - return ret; + /* don't allow HW interrupts in force trace mode */ + pic_activate(); + if (!pic_isset_IF()) { + if (pic_pending()) { +#if 0 + /* try to detect timer flood, and not set VIP if it is there. + * See https://github.com/stsp/dosemu2/issues/918 + */ + if (pic_sys_time < pic_dos_time + + TIMER0_FLOOD_THRESHOLD || + pic_pending_masked(1 << PIC_IRQ0)) + set_VIP(); + else + r_printf("PIC: timer flood work-around\n"); +#else + /* the above work-around regresses goblins2, see + * https://github.com/dosemu2/dosemu2/issues/1300 + */ + set_VIP(); +#endif + } + return; /* exit if ints are disabled */ + } + clear_VIP(); + + /* check for and find any requested irqs. Having found one, we atomic-ly + * clear it and verify it was there when we cleared it. If it wasn't, we + * look for the next request. There are two in_service bits for pic1 irqs. + * This is needed, because irq 8-15 must do 2 outb20s, which, if the dos + * irq code actually runs, will reset the bits. We also reset them here, + * since dos code won't necessarily run. + */ + if((local_pic_ilevel = pic_get_ilevel()) != -1) { /* if something to do*/ + pic_print(1, "Running irq lvl ", local_pic_ilevel, ""); + clear_bit(local_pic_ilevel, &pic_irr); + /* pic_isr bit is set in do_irq() */ + ret = (pic_iinfo[local_pic_ilevel].func ? + pic_iinfo[local_pic_ilevel].func(local_pic_ilevel) : 1); /* run the function */ + if (ret) { + do_irq(local_pic_ilevel); + if (pic_pending()) + /* If special mask mode is active, multiple IRQs + can be pending. In that cases we need to + return from dos code asap when it enables + interrupts to schedule the next interrupt. */ + set_VIP(); + } + } } -Bit8u pic1_get_base(void) -{ - Bit8u ret; - pthread_mutex_lock(&pic_mtx); - ret = pic[1].irq_base; - pthread_mutex_unlock(&pic_mtx); - return ret; +/* DANG_BEGIN_FUNCTION do_irq + * + * do_irq() calls the correct do_int(). + * It then executes a vm86 loop until an outb( end-of-interrupt) is found. + * For priority levels 0 and >15 (not real IRQs), vm86 executes once, then + * returns, since no outb20 will come. + * Returns: 0 = complete, 1 = interrupt not run because it directly + * calls our "bios" See run_timer_tick() in timer.c for an example + * To assure notification when the irq completes, we push flags, ip, and cs + * here and fake cs:ip to PIC_[SEG,OFF], where there is a hlt. This makes + * the irq generate a sigsegv, which calls pic_iret when it completes. + * pic_iret then pops the real cs:ip from the stack. + * This routine is RE-ENTRANT - it calls run_irqs, + * which may call an interrupt routine, + * which may call do_irq(). Be Careful! !!!!!!!!!!!!!!!!!! + * No single interrupt is ever re-entered. + * + * Callers: + * base/misc/ioctl.c + * base/keyboard/serv_8042.c + * base/keyboard/keyboard-server.c + * base/serial/ser_irq.c + * dosext/sound/sound.c + * dosext/net/net/pktnew.c + * + * DANG_END_FUNCTION + */ +static void do_irq(int ilevel) +{ + int intr; + + set_bit(ilevel, &pic0_isr); /* set in-service bit */ + set_bit(ilevel, &pic1_isr); /* pic1 too */ + pic1_isr &= pic1_mask; /* isolate pic1 irqs */ + + intr=pic_iinfo[ilevel].ivec; + + if (pic_iinfo[ilevel].callback) { + if(in_dpmi_pm()) + fake_pm_int(); + fake_int_to(BIOSSEG, EOI_OFF); + pic_iinfo[ilevel].callback(); + } else { + if (dpmi_active()) run_pm_int(intr); + else { + /* schedule the requested interrupt, then enter the vm86() loop */ + run_int(intr); + } + } } -unsigned pic_get_isr(void) +/* DANG_BEGIN_FUNCTION pic_request + * + * pic_request triggers an interrupt. There is presently no way to + * "un-trigger" an interrupt. The interrupt will be initiated the + * next time pic_run is called, unless masked or superceded by a + * higher priority interrupt. pic_request takes one argument, an + * interrupt level, which specifies the interrupt to be triggered. + * If that interrupt is already active, the request will be queued + * until all active interrupts have been completed. The queue is + * only one request deep for each interrupt, so it is the responsibility + * of the interrupt code to retrigger itself if more interrupts are + * needed. + * + * DANG_END_FUNCTION + */ +int pic_request(int inum) { - unsigned ret; +static char buf[81]; + int ret=PIC_REQ_NOP; - pthread_mutex_lock(&pic_mtx); - ret = (pic[0].isr | (pic[1].isr << 8)); - pthread_mutex_unlock(&pic_mtx); - return ret; + if ((pic_irr|pic_isr)&(1<2) { + /* avoid going through sprintf for non-debugging */ + sprintf(buf,", k%d",(int)pic_dpmi_count); + pic_print(2,"Zeroing vm86, DPMI from ",pic_vm86_count,buf); + } + pic_vm86_count=pic_dpmi_count=0; + return ret; +} + +void pic_untrigger(int inum) +{ + if (!((pic_irr | pic_pirr) & (1<high transition is detected. After which, it again mirrors + * the IRQ pin directly. In level mode it always mirrors the input. + * This means that with "level-delivering" devices there is no + * difference AT ALL with what triggering mode is used. Their + * inactive state is low, so on the first transition to high, IRR + * bit starts following the input in any trigger mode. The difference + * is there only with the "edge-delivering" devices: their inactive + * state is high and the IRQ delivery start from the short pulse to + * low and back. Before that starting pulse, IRR bit remains low even + * though the IRQ line is high. There are probably not much of the + * "edge-delivering" devices though: PIT in mode 2 is the only + * one known to me. + * In short: we should allow untriggering the interrupt regardless + * of the trigger mode. + * + * Note: spurious IRQ should be generated in any trigger mode if + * all IRQ lines went low before INTA. This is because even in edge + * mode the IRR bit gets cleared when IRQ line goes down, so at + * INTA time there will be nothing to read from IRR. + */ + pic_pirr &= ~(1<td; + + /* check for any freshly initiated timers, and sync them to s_time */ + pic_print2(2,"pic_itime[1]= ",pic_itime[1]," "); + pic_sys_time=t_time + (t_time == NEVER); + pic_print2(2,"pic_sys_time set to ",pic_sys_time," "); + pic_dos_time = pic_itime[32]; + + pic_activate(); +} + +static int pic_get_ilevel_masked(uint8_t mask) +{ + int local_pic_ilevel, old_ilevel; + int int_req = (pic_irr & ~(pic_isr | pic_imr | mask)); + if (!int_req) + return -1; + local_pic_ilevel = find_bit(int_req); /* find out what it is */ + old_ilevel = find_bit(pic_isr); + /* note that this priority check is a no-op if special mask mode + is active (ie. pic_smm == 32, and local_pic_level is always <= 31) */ + if (local_pic_ilevel >= old_ilevel + pic_smm) /* priority check */ + return -1; + /* HACK to not allow timer IRQ to interrupt anything else */ + if (old_ilevel != -1 && (local_pic_ilevel == PIC_IRQ0 || + local_pic_ilevel == PIC_IRQ8)) + return -1; + return local_pic_ilevel; +} + +static int pic_get_ilevel(void) +{ + return pic_get_ilevel_masked(0); } int pic_pending(void) { - int ret; - - pthread_mutex_lock(&pic_mtx); - ret = pic_get_output(&pic[0]); - pthread_mutex_unlock(&pic_mtx); - return ret; + return (pic_get_ilevel() != -1); } -int pic_irq_active(int irq) +#if 0 +int pic_pending_masked(uint8_t mask) { - int ret; - PICCommonState *p = pic; - - if (irq >= 8) { - irq -= 8; - p++; - } - pthread_mutex_lock(&pic_mtx); - ret = !!((1 << irq) & p->isr); - pthread_mutex_unlock(&pic_mtx); - return ret; + return (pic_get_ilevel_masked(mask) != -1); +} +#endif + +int pic_irq_active(int num) +{ + unsigned isr = pic_isr; + return test_bit(num, &isr); +} + +int pic_irq_masked(int num) +{ + return test_bit(num, &pic_imr); +} + +/* DANG_BEGIN_FUNCTION pic_activate + * + * pic_activate requests any interrupts whose scheduled time has arrived. + * anything after pic_dos_time and before pic_sys_time is activated. + * pic_dos_time is advanced to the earliest time scheduled. + * DANG_END_FUNCTION + */ +static void pic_activate(void) +{ + hitimer_t earliest; + int timer, count; + unsigned pic_newirr; + + if (pic_pending()) + return; + pic_newirr = pic_pirr & ~(pic_irr | pic_isr); + pic_irr |= pic_newirr; + pic_pirr &= ~pic_newirr; + +/*if(pic_irr&~pic_imr) return;*/ + earliest = pic_sys_time; + count = 0; + for (timer=0; timer<32; ++timer) { + if ((pic_itime[timer] != NEVER) && (pic_itime[timer] < pic_sys_time)) { + if (pic_itime[timer] != pic_ltime[timer]) { + if ((earliest == NEVER) || (pic_itime[timer] < earliest)) + earliest = pic_itime[timer]; + pic_request(timer); + ++count; + } + } + } + if(count) pic_print(2,"Activated ",count, " interrupts."); + pic_print2(2,"Activate ++ dos time to ",earliest, " "); + pic_print2(2,"pic_sys_time is ",pic_sys_time," "); + pic_itime[32] = earliest; + if (count) + pic_dos_time = earliest; +} + +/* DANG_BEGIN_FUNCTION pic_sched + * pic_sched schedules an interrupt for activation after a designated + * time interval. The time measurement is in unis of 1193047/second, + * the same rate as the pit counters. This is convenient for timer + * emulation, but can also be used for pacing other functions, such as + * serial emulation, incoming keystrokes, or video updates. Some sample + * intervals: + * + * rate/sec: 5 7.5 11 13.45 15 30 60 + * interval: 238608 159072 108459 88702 79536 39768 19884 + * + * rate/sec: 120 180 200 240 360 480 720 + * interval: 9942 6628 5965 4971 3314 2485 1657 + * + * rate/sec: 960 1440 1920 2880 3840 5760 11520 + * interval: 1243 829 621 414 311 207 103 + * + * pic_sched expects two parameters: an interrupt level and an interval. + * To assure proper repeat scheduling, pic_sched should be called from + * within the interrupt handler for the same interrupt. The maximum + * interval is 15 minutes (0x3fffffff). + * DANG_END_FUNCTION + */ + +void pic_sched(int ilevel, int interval) +{ + char mesg[35]; + + /* default for interval is 65536 (=54.9ms) + * There's a problem with too small time intervals - an interrupt can + * be continuously scheduled, without letting any time to process other + * code. + * + * BIG WARNING - in non-periodic timer modes pit[0].cntr goes to -1 + * at the end of the interval - was this the reason for the following + * [1u-15sec] range check? + */ + if(interval > 0 && interval < 0x3fffffff) { + if(pic_ltime[ilevel]==NEVER) { + pic_itime[ilevel] = pic_itime[32] + interval; + } else { + pic_itime[ilevel] = pic_itime[ilevel] + interval; + } + } + if (debug_level('r') > 2) { + /* avoid going through sprintf for non-debugging */ + sprintf(mesg,", delay= %d.",interval); + pic_print(2,"Scheduling lvl= ",ilevel,mesg); + pic_print2(2,"pic_itime set to ",pic_itime[ilevel],""); + } +} + +int CAN_SLEEP(void) +{ + return (!(pic_isr || (REG(eflags) & VIP) || signal_pending() || + (pic_sys_time > pic_dos_time + TIMER0_FLOOD_THRESHOLD) || in_leavedos)); +} + +void pic_init(void) +{ + /* do any one-time initialization of the PIC */ + emu_iodev_t io_device; + + /* 8259 PIC (Programmable Interrupt Controller) */ + io_device.read_portb = read_pic0; + io_device.write_portb = write_pic0; + io_device.read_portw = NULL; + io_device.write_portw = NULL; + io_device.read_portd = NULL; + io_device.write_portd = NULL; + io_device.handler_name = "8259 PIC0"; + io_device.start_addr = 0x0020; + io_device.end_addr = 0x0021; + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; + port_register_handler(io_device, 0); + + io_device.handler_name = "8259 PIC1"; + io_device.start_addr = 0x00A0; + io_device.end_addr = 0x00A1; + io_device.read_portb = read_pic1; + io_device.write_portb = write_pic1; + port_register_handler(io_device, 0); +} + +void pic_reset(void) +{ + pic_set_mask; } diff --git a/src/base/dev/sb16/Makefile b/src/base/dev/sb16/Makefile index 94210ba..b87ddcf 100644 --- a/src/base/dev/sb16/Makefile +++ b/src/base/dev/sb16/Makefile @@ -8,7 +8,11 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.conf -CFILES = sb16.c dspio.c adlib.c opl.c dbadlib.c mpu401.c mt32.c +CFILES = sb16.c dspio.c adlib.c opl.c dbadlib.c ALL_CPPFLAGS += -DOPLTYPE_IS_OPL3 +all: lib + +install: + include $(REALTOPDIR)/src/Makefile.common diff --git a/src/base/dev/sb16/adlib.c b/src/base/dev/sb16/adlib.c index e81476e..66a51ad 100644 --- a/src/base/dev/sb16/adlib.c +++ b/src/base/dev/sb16/adlib.c @@ -34,11 +34,11 @@ #include "sound/sound.h" #include "sound/oplplug.h" #include "sound.h" +#include "adlib.h" #include "dbadlib.h" #include #include #include -#include "adlib.h" #define ADLIB_BASE 0x388 #define OPL3_INTERNAL_FREQ 14400000 // The OPL3 operates at 14.4MHz @@ -66,6 +66,7 @@ static const int opl3_format = PCM_FORMAT_S8; #endif static const int opl3_rate = 44100; +static pthread_mutex_t synth_mtx = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t run_mtx = PTHREAD_MUTEX_INITIALIZER; static pthread_t syn_thr; static sem_t syn_sem; @@ -74,13 +75,15 @@ static void *synth_thread(void *arg); Bit8u adlib_io_read_base(ioport_t port) { Bit8u ret; + pthread_mutex_lock(&synth_mtx); ret = oplops->PortRead(opl3_impl, port); + pthread_mutex_unlock(&synth_mtx); if (debug_level('S') >= 9) S_printf("Adlib: Read %hhx from port %x\n", ret, port); return ret; } -static Bit8u adlib_io_read(ioport_t port, void *arg) +static Bit8u adlib_io_read(ioport_t port) { return adlib_io_read_base(port - ADLIB_BASE); } @@ -92,12 +95,15 @@ void adlib_io_write_base(ioport_t port, Bit8u value) adlib_time_last = GETusTIME(0); if (debug_level('S') >= 9) S_printf("Adlib: Write %hhx to port %x\n", value, port); - if (port & 1) + if ( port&1 ) { opl3_update(); + } + pthread_mutex_lock(&synth_mtx); oplops->PortWrite(opl3_impl, port, value); + pthread_mutex_unlock(&synth_mtx); } -static void adlib_io_write(ioport_t port, Bit8u value, void *arg) +static void adlib_io_write(ioport_t port, Bit8u value) { adlib_io_write_base(port - ADLIB_BASE, value); } @@ -118,6 +124,7 @@ static void opl3_update(void) pthread_mutex_unlock(&run_mtx); if (!a_run) adlib_start(); + run_sb(); } void opl3_init(void) @@ -136,6 +143,8 @@ void opl3_init(void) io_device.handler_name = "OPL3"; io_device.start_addr = ADLIB_BASE; io_device.end_addr = ADLIB_BASE + 3; + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; if (port_register_handler(io_device, 0) != 0) { error("ADLIB: Cannot registering port handler\n"); } @@ -168,10 +177,12 @@ void adlib_done(void) sem_destroy(&syn_sem); } -static void adlib_process_samples(int nframes, double cur, double per) +static void adlib_process_samples(int nframes) { sndbuf_t buf[OPL3_MAX_BUF][SNDBUF_CHANS]; - oplops->Generate(nframes, buf, cur, per); + pthread_mutex_lock(&synth_mtx); + oplops->Generate(nframes, buf); + pthread_mutex_unlock(&synth_mtx); pcm_write_interleaved(buf, nframes, opl3_rate, opl3_format, ADLIB_CHANNELS, adlib_strm); } @@ -197,7 +208,7 @@ static void adlib_run(void) if (nframes > OPL3_MAX_BUF) nframes = OPL3_MAX_BUF; if (nframes >= OPL3_MIN_BUF) { - adlib_process_samples(nframes, adlib_time_cur, period); + adlib_process_samples(nframes); adlib_time_cur = pcm_get_stream_time(adlib_strm); if (debug_level('S') >= 7) S_printf("SB: processed %i Adlib samples\n", nframes); diff --git a/src/base/dev/sb16/dbadlib.c b/src/base/dev/sb16/dbadlib.c index 48e9668..fac811d 100644 --- a/src/base/dev/sb16/dbadlib.c +++ b/src/base/dev/sb16/dbadlib.c @@ -30,7 +30,6 @@ #include "timers.h" #include "opl.h" #include "sound/oplplug.h" -#include "sequencr.h" #include "dbadlib.h" typedef struct _AdlibTimer AdlibTimer; @@ -95,8 +94,7 @@ static AdlibTimer opl3_timers[2]; static uint8_t dbadlib_PortRead(void *impl, uint16_t port); static void dbadlib_PortWrite(void *impl, uint16_t port, uint8_t val ); static void *dbadlib_create(int opl3_rate); -static void dbadlib_generate(int total, int16_t output[][2], double start, - double period); +static void dbadlib_generate(int total, int16_t output[][2]); //Check for it being a write to the timer static bool AdlibChip__WriteTimer(AdlibTimer *timer, Bit32u reg, Bit8u val) { @@ -172,26 +170,17 @@ static struct { Bit32u normal; } reg; -static void *seq; -enum { STAG_PORT, STAG_VAL }; - // stripped down from DOSBOX adlib.cpp: Adlib::Module::PortWrite static void dbadlib_PortWrite(void *impl, uint16_t port, uint8_t val ) { AdlibTimer *timer = impl; - int add_ev = 0; if ( port&1 ) { if ( !AdlibChip__WriteTimer( timer, reg.normal, val ) ) { - add_ev++; + opl_write( reg.normal, val ); } } else { - add_ev++; + opl_write_index( port, val ); reg.normal = val & 0x1ff; } - if (add_ev) { - struct seq_item_s *i = sequencer_add(seq, GETusTIME(0)); - sequencer_add_tag(i, STAG_PORT, port); - sequencer_add_tag(i, STAG_VAL, val); - } } @@ -211,56 +200,13 @@ static void *dbadlib_create(int opl3_rate) { AdlibChip__AdlibChip(opl3_timers); opl_init(opl3_rate); - seq = sequencer_init(); return opl3_timers; } -static int opl_idx; - -static void extract_event(void) +// converted from DOSBOX dbopl.cpp: DBOPL::Handler::Generate +static void dbadlib_generate(int total, int16_t output[][2]) { - struct seq_item_s *i = sequencer_get(seq); - int port, val; - assert(i); - port = sequencer_find(i, STAG_PORT); - val = sequencer_find(i, STAG_VAL); - sequencer_free(i); - if (port & 1) { - opl_write(opl_idx, val); - } else { - opl_write_index(port, val); - opl_idx = val & 0x1ff; - } -} - -static void dbadlib_generate(int total, int16_t output[][2], double start, - double period) -{ - int done = 0; - double end = start + total * period; - long long next = sequencer_get_next(seq); - while (next && start > next) { - extract_event(); - next = sequencer_get_next(seq); - } - while (total > done) { - int todo = total - done; - if (next > end) - next = 0; - if (next) - todo = (next - start) / period; - opl_getsample((Bit16s *)(output + done), todo); - start += todo * period; - done += todo; - if (next) { - long long next1 = next; - do { - extract_event(); - next1 = sequencer_get_next(seq); - } while (next1 == next); // timestamps may duplicate - next = next1; - } - } + opl_getsample((Bit16s *)output, total); } struct opl_ops dbadlib_ops = { diff --git a/src/base/dev/sb16/dspio.c b/src/base/dev/sb16/dspio.c index 5c62fec..053ea79 100644 --- a/src/base/dev/sb16/dspio.c +++ b/src/base/dev/sb16/dspio.c @@ -49,7 +49,7 @@ #define PCM_MAX_BUF 512 struct dspio_dma { - unsigned int running:1; + int running:1; int num; int broken_hdma; int rate; @@ -69,17 +69,22 @@ struct dspio_dma { struct dspio_state { double input_time_cur, midi_time_cur; int dma_strm, dac_strm; - unsigned int input_running:1, output_running:1, dac_running:1, speaker:1; - unsigned int pcm_input_running:1, lin_input_running:1, mic_input_running:1; + int input_running:1, output_running:1, dac_running:1, speaker:1; + int pcm_input_running:1, lin_input_running:1, mic_input_running:1; int i_handle, i_started; #define DSP_FIFO_SIZE 64 struct rng_s fifo_in; struct rng_s fifo_out; #define DSP_OUT_FIFO_TRIGGER 32 #define DSP_IN_FIFO_TRIGGER 32 +#define MIDI_FIFO_SIZE 32 + struct rng_s midi_fifo_in; + struct rng_s midi_fifo_out; struct dspio_dma dma; }; +#define DSPIO ((struct dspio_state *)dspio) + static void dma_get_silence(int is_signed, int is16bit, void *ptr) { if (is16bit) { @@ -91,22 +96,29 @@ static void dma_get_silence(int is_signed, int is16bit, void *ptr) } } -void dspio_toggle_speaker(struct dspio_state *dspio, int on) +void dspio_toggle_speaker(void *dspio, int on) { - if (!on && dspio->speaker) { - if (dspio->dac_running) { - pcm_flush(dspio->dac_strm); - dspio->dac_running = 0; + if (!on && DSPIO->speaker) { + if (DSPIO->dac_running) { + pcm_flush(DSPIO->dac_strm); + DSPIO->dac_running = 0; } /* we don't flush PCM stream here because DSP uses PCM layer * for timing, and timing is needed even when speaker is disabled... */ } - dspio->speaker = on; + DSPIO->speaker = on; } -int dspio_get_speaker_state(struct dspio_state *dspio) +int dspio_get_speaker_state(void *dspio) { - return dspio->speaker; + return DSPIO->speaker; +} + +void dspio_write_midi(void *dspio, Bit8u value) +{ + rng_put(&DSPIO->midi_fifo_out, &value); + + run_sb(); } static void run_sound(void) @@ -142,6 +154,42 @@ static int dspio_input_fifo_empty(struct dspio_state *state) return !rng_count(&state->fifo_in); } +static int dspio_midi_output_empty(struct dspio_state *state) +{ + return !rng_count(&state->midi_fifo_out); +} + +static Bit8u dspio_get_midi_data(struct dspio_state *state) +{ + Bit8u val; + int ret = rng_get(&state->midi_fifo_out, &val); + assert(ret == 1); + return val; +} + +Bit8u dspio_get_midi_in_byte(void *dspio) +{ + Bit8u val; + int ret = rng_get(&DSPIO->midi_fifo_in, &val); + assert(ret == 1); + return val; +} + +void dspio_put_midi_in_byte(void *dspio, Bit8u val) +{ + rng_put_const(&DSPIO->midi_fifo_in, val); +} + +int dspio_get_midi_in_fillup(void *dspio) +{ + return rng_count(&DSPIO->midi_fifo_in); +} + +void dspio_clear_midi_in_fifo(void *dspio) +{ + rng_clear(&DSPIO->midi_fifo_in); +} + static int dspio_get_dma_data(struct dspio_state *state, void *ptr, int is16bit) { static int warned; @@ -305,11 +353,11 @@ static int dspio_put_input_sample(struct dspio_state *state, void *ptr, return ret; } -void dspio_clear_fifos(struct dspio_state *dspio) +void dspio_clear_fifos(void *dspio) { - rng_clear(&dspio->fifo_in); - rng_clear(&dspio->fifo_out); - dspio->dma.dsp_fifo_enabled = 1; + rng_clear(&DSPIO->fifo_in); + rng_clear(&DSPIO->fifo_out); + DSPIO->dma.dsp_fifo_enabled = 1; } static void dspio_i_start(void *arg) @@ -349,7 +397,7 @@ static double dspio_get_volume(int id, int chan_dst, int chan_src, void *arg); static int dspio_is_connected(int id, void *arg); static int dspio_checkid2(void *id2, void *arg); -struct dspio_state *dspio_init(void) +void *dspio_init(void) { struct dspio_state *state; state = malloc(sizeof(struct dspio_state)); @@ -364,6 +412,8 @@ struct dspio_state *dspio_init(void) rng_init(&state->fifo_in, DSP_FIFO_SIZE, 2); rng_init(&state->fifo_out, DSP_FIFO_SIZE, 2); + rng_init(&state->midi_fifo_in, MIDI_FIFO_SIZE, 1); + rng_init(&state->midi_fifo_out, MIDI_FIFO_SIZE, 1); state->i_handle = pcm_register_player(&player, state); pcm_init(); @@ -382,31 +432,38 @@ struct dspio_state *dspio_init(void) return state; } -void dspio_reset(struct dspio_state *dspio) +void dspio_reset(void *dspio) { } -void dspio_done(struct dspio_state *dspio) +void dspio_done(void *dspio) { midi_done(); /* shutdown midi before pcm as midi may use pcm */ pcm_done(); - rng_destroy(&dspio->fifo_in); - rng_destroy(&dspio->fifo_out); + rng_destroy(&DSPIO->fifo_in); + rng_destroy(&DSPIO->fifo_out); + rng_destroy(&DSPIO->midi_fifo_in); + rng_destroy(&DSPIO->midi_fifo_out); free(dspio); } -void dspio_stop_midi(struct dspio_state *dspio) +int dspio_is_mt32_mode(void) { - dspio->midi_time_cur = GETusTIME(0); + return (midi_get_synth_type() == ST_MT32); +} + +void dspio_stop_midi(void *dspio) +{ + DSPIO->midi_time_cur = GETusTIME(0); midi_stop(); } -Bit32u dspio_get_midi_in_time(struct dspio_state *dspio) +Bit32u dspio_get_midi_in_time(void *dspio) { - Bit32u delta = GETusTIME(0) - dspio->midi_time_cur; + Bit32u delta = GETusTIME(0) - DSPIO->midi_time_cur; S_printf("SB: midi clock, delta=%i\n", delta); return delta; } @@ -460,7 +517,7 @@ static void dspio_stop_input(struct dspio_state *state) state->pcm_input_running = 0; } -int dspio_input_enable(struct dspio_state *dspio, enum MixChan mc) +int dspio_input_enable(void *dspio, enum MixChan mc) { struct dspio_state *state = dspio; switch (mc) { @@ -484,7 +541,7 @@ int dspio_input_enable(struct dspio_state *dspio, enum MixChan mc) return 1; } -int dspio_input_disable(struct dspio_state *dspio, enum MixChan mc) +int dspio_input_disable(void *dspio, enum MixChan mc) { struct dspio_state *state = dspio; switch (mc) { @@ -614,30 +671,30 @@ static int dspio_drain_input(struct dspio_state *state) return dma_cnt; } -void dspio_start_dma(struct dspio_state *dspio) +void dspio_start_dma(void *dspio) { int dma_cnt = 0; - dspio->dma.running = 1; - dspio->dma.time_cur = GETusTIME(0); - get_dma_params(&dspio->dma); + DSPIO->dma.running = 1; + DSPIO->dma.time_cur = GETusTIME(0); + get_dma_params(&DSPIO->dma); - if (dspio->dma.input) { - dspio_start_input(dspio); + if (DSPIO->dma.input) { + dspio_start_input(DSPIO); } else { - dma_cnt = dspio_fill_output(dspio); - if (dspio->dma.running && dspio_output_fifo_filled(dspio)) + dma_cnt = dspio_fill_output(DSPIO); + if (DSPIO->dma.running && dspio_output_fifo_filled(DSPIO)) S_printf("SB: Output filled, processed %i DMA cycles\n", dma_cnt); else S_printf("SB: Output fillup incomplete (%i %i %i)\n", - dspio->dma.running, dspio->output_running, dma_cnt); + DSPIO->dma.running, DSPIO->output_running, dma_cnt); } } -void dspio_stop_dma(struct dspio_state *dspio) +void dspio_stop_dma(void *dspio) { - dspio_stop_input(dspio); - dspio->dma.running = 0; + dspio_stop_input(DSPIO); + DSPIO->dma.running = 0; } static int calc_nframes(struct dspio_state *state, @@ -810,29 +867,45 @@ static void dspio_process_dma(struct dspio_state *state) in_fifo_cnt, out_fifo_cnt, dma_cnt, state->output_running, state->dma.running); } +static void dspio_process_midi(struct dspio_state *state) +{ + Bit8u data; + /* no timing for now */ + while (!dspio_midi_output_empty(state)) { + data = dspio_get_midi_data(state); + midi_write(data); + } + + while (midi_get_data_byte(&data)) { + dspio_put_midi_in_byte(state, data); + sb_handle_midi_data(); + } +} + void dspio_run_synth(void) { adlib_timer(); midi_timer(); } -void dspio_timer(struct dspio_state *dspio) +void dspio_timer(void *dspio) { - dspio_process_dma(dspio); + dspio_process_dma(DSPIO); + dspio_process_midi(DSPIO); } -void dspio_write_dac(struct dspio_state *dspio, Bit8u samp) +void dspio_write_dac(void *dspio, Bit8u samp) { sndbuf_t buf[1][SNDBUF_CHANS]; #if 0 /* on SB16 speaker control does not exist */ - if (!dspio->speaker) + if (!DSPIO->speaker) return; #endif buf[0][0] = samp; - dspio->dac_running = 1; + DSPIO->dac_running = 1; pcm_write_interleaved(buf, 1, DAC_BASE_FREQ, PCM_FORMAT_U8, - 1, dspio->dac_strm); + 1, DSPIO->dac_strm); } /* the volume APIs for sb16 and sndpcm are very different. diff --git a/src/base/dev/sb16/dspio.h b/src/base/dev/sb16/dspio.h index edce8a9..c491035 100644 --- a/src/base/dev/sb16/dspio.h +++ b/src/base/dev/sb16/dspio.h @@ -23,23 +23,27 @@ #ifndef __DSPIO_H__ #define __DSPIO_H__ -struct dspio_state; - -extern struct dspio_state *dspio_init(void); -extern void dspio_reset(struct dspio_state *dspio); -extern void dspio_done(struct dspio_state *dspio); -extern void dspio_start_dma(struct dspio_state *dspio); -extern void dspio_stop_dma(struct dspio_state *dspio); -extern void dspio_stop_midi(struct dspio_state *dspio); -extern void dspio_toggle_speaker(struct dspio_state *dspio, int on); -extern int dspio_get_speaker_state(struct dspio_state *dspio); -extern Bit32u dspio_get_midi_in_time(struct dspio_state *dspio); -extern void dspio_write_dac(struct dspio_state *dspio, Bit8u samp); -extern void dspio_timer(struct dspio_state *dspio); +extern void *dspio_init(void); +extern void dspio_reset(void *dspio); +extern void dspio_done(void *dspio); +extern void dspio_start_dma(void *dspio); +extern void dspio_stop_dma(void *dspio); +extern void dspio_stop_midi(void *dspio); +extern void dspio_toggle_speaker(void *dspio, int on); +extern int dspio_get_speaker_state(void *dspio); +extern Bit32u dspio_get_midi_in_time(void *dspio); +extern void dspio_write_dac(void *dspio, Bit8u samp); +extern void dspio_timer(void *dspio); extern void dspio_run_synth(void); -extern void dspio_clear_fifos(struct dspio_state *dspio); -extern int dspio_input_enable(struct dspio_state *dspio, enum MixChan mc); -extern int dspio_input_disable(struct dspio_state *dspio, enum MixChan mc); +extern void dspio_write_midi(void *dspio, Bit8u value); +extern void dspio_clear_fifos(void *dspio); +extern Bit8u dspio_get_midi_in_byte(void *dspio); +extern void dspio_put_midi_in_byte(void *dspio, Bit8u val); +extern int dspio_get_midi_in_fillup(void *dspio); +extern void dspio_clear_midi_in_fifo(void *dspio); +extern int dspio_input_enable(void *dspio, enum MixChan mc); +extern int dspio_input_disable(void *dspio, enum MixChan mc); extern double dspio_calc_vol(int val, int step, int init_db); +extern int dspio_is_mt32_mode(void); #endif diff --git a/src/base/dev/sb16/mpu401.c b/src/base/dev/sb16/mpu401.c deleted file mode 100644 index 90dd7b3..0000000 --- a/src/base/dev/sb16/mpu401.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: MPU401 emulation. - * - * Author: @stsp - * - */ -#include -#include -#include "ringbuf.h" -#include "port.h" -#include "dosemu_debug.h" -#include "sound/midi.h" -#include "mpu401.h" - -struct mpu401_s { -#define MIDI_FIFO_SIZE 32 - struct rng_s fifo_in; - unsigned int uart:1; - ioport_t base; - struct mpu401_ops *ops; -}; - -static void mpu401_stop_midi(struct mpu401_s *mpu) -{ - midi_stop(); -} - -static Bit8u get_midi_in_byte(struct mpu401_s *mpu) -{ - Bit8u val; - int ret = rng_get(&mpu->fifo_in, &val); - assert(ret == 1); - return val; -} - -static int get_midi_in_fillup(struct mpu401_s *mpu) -{ - return rng_count(&mpu->fifo_in); -} - -static void put_midi_in_byte(struct mpu401_s *mpu, Bit8u val) -{ - rng_put_const(&mpu->fifo_in, val); -#define MPU401_IN_FIFO_TRIGGER 1 - if (get_midi_in_fillup(mpu) == MPU401_IN_FIFO_TRIGGER) - mpu->ops->activate_irq(mpu); -} - -void mpu401_put_midi_in_byte(struct mpu401_s *mpu, Bit8u val) -{ - put_midi_in_byte(mpu, val); -} - -void mpu401_clear_midi_in_fifo(struct mpu401_s *mpu) -{ - rng_clear(&mpu->fifo_in); -} - -void mpu401_process(struct mpu401_s *mpu) -{ - Bit8u data; - while (midi_get_data_byte(&data)) - put_midi_in_byte(mpu, data); -} - -static Bit8u mpu401_io_read(ioport_t port, void *arg) -{ - struct mpu401_s *mpu = arg; - ioport_t addr; - Bit8u r = 0xff; - - addr = port - mpu->base; - - switch (addr) { - case 0: - /* Read data port */ - if (get_midi_in_fillup(mpu)) { - r = get_midi_in_byte(mpu); - } else { - S_printf("MPU401: ERROR: No data to read\n"); - r = 0xfe; // ACK - } - if (!mpu->uart && mpu->ops->read_hook) - mpu->ops->read_hook(mpu, r); - S_printf("MPU401: Read data port = 0x%02x, %i bytes still in queue\n", - r, get_midi_in_fillup(mpu)); - if (!get_midi_in_fillup(mpu)) - mpu->ops->deactivate_irq(mpu); - mpu->ops->run_irq(mpu); - break; - case 1: - /* Read status port */ - /* 0x40=OUTPUT_AVAIL; 0x80=INPUT_AVAIL */ - r = 0xff & (~0x40); /* Output is always possible */ - if (get_midi_in_fillup(mpu)) - r &= (~0x80); - S_printf("MPU401: Read status port = 0x%02x\n", r); - break; - } - return r; -} - -static void mpu401_io_write(ioport_t port, Bit8u value, void *arg) -{ - struct mpu401_s *mpu = arg; - uint32_t addr; - addr = port - mpu->base; - - switch (addr) { - case 0: - /* Write data port */ - if (debug_level('S') > 5) - S_printf("MPU401: Write 0x%02x to data port\n", value); - mpu->ops->write_midi(mpu, value); - break; - case 1: - /* Write command port */ - S_printf("MPU401: Write 0x%02x to command port\n", value); - mpu401_clear_midi_in_fifo(mpu); - /* the following doc: - * http://www.piclist.com/techref/io/serial/midi/mpu.html - * says 3f does not need ACK. But dosbox sources say that - * it does. Someone please try on a real HW? */ - put_midi_in_byte(mpu, 0xfe); /* A command is sent: MPU_ACK it next time */ - switch (value) { - case 0x3f: // 0x3F = UART mode - mpu->uart = 1; - break; - case 0xff: // 0xFF = reset MPU - mpu->uart = 0; - mpu401_stop_midi(mpu); - break; - default: - if (mpu->ops->cmd_hook) - mpu->ops->cmd_hook(mpu, value); - break; - } - break; - } -} - -struct mpu401_s *mpu401_init(ioport_t base, struct mpu401_ops *ops) -{ - emu_iodev_t io_device; - struct mpu401_s *mpu; - - S_printf("MPU401: MPU-401 Initialisation\n"); - - mpu = malloc(sizeof(*mpu)); - assert(mpu); - - /* This is the MPU-401 */ - io_device.read_portb = mpu401_io_read; - io_device.write_portb = mpu401_io_write; - io_device.read_portw = NULL; - io_device.write_portw = NULL; - io_device.read_portd = NULL; - io_device.write_portd = NULL; - io_device.handler_name = ops->name; - io_device.start_addr = base; - io_device.end_addr = base + 0x001; - io_device.arg = mpu; - if (port_register_handler(io_device, 0) != 0) - error("MPU-401: Cannot registering port handler\n"); - - S_printf("MPU401: MPU-401 Initialisation - Base 0x%03x \n", base); - - rng_init(&mpu->fifo_in, MIDI_FIFO_SIZE, 1); - mpu->base = base; - mpu->ops = ops; - return mpu; -} - -void mpu401_reset(struct mpu401_s *mpu) -{ - mpu->ops->deactivate_irq(mpu); - mpu->uart = 0; -} - -void mpu401_done(struct mpu401_s *mpu) -{ - rng_destroy(&mpu->fifo_in); - free(mpu); -} - -int mpu401_is_uart(struct mpu401_s *mpu) -{ - return mpu->uart; -} diff --git a/src/base/dev/sb16/mpu401.h b/src/base/dev/sb16/mpu401.h deleted file mode 100644 index 8136f84..0000000 --- a/src/base/dev/sb16/mpu401.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#ifndef MPU401_H -#define MPU401_H - -#include - -struct mpu401_s; - -struct mpu401_ops { - void (*activate_irq)(struct mpu401_s *mpu); - void (*deactivate_irq)(struct mpu401_s *mpu); - void (*run_irq)(struct mpu401_s *mpu); - void (*write_midi)(struct mpu401_s *mpu, uint8_t data); - void (*cmd_hook)(struct mpu401_s *mpu, uint8_t cmd); - void (*read_hook)(struct mpu401_s *mpu, uint8_t data); - const char *name; -}; - -int mpu401_is_uart(struct mpu401_s *mpu); -void mpu401_process(struct mpu401_s *mpu); -void mpu401_put_midi_in_byte(struct mpu401_s *mpu, Bit8u val); -void mpu401_clear_midi_in_fifo(struct mpu401_s *mpu); - -struct mpu401_s *mpu401_init(ioport_t base, struct mpu401_ops *ops); -void mpu401_reset(struct mpu401_s *mpu); -void mpu401_done(struct mpu401_s *mpu); - -#endif diff --git a/src/base/dev/sb16/mt32.c b/src/base/dev/sb16/mt32.c deleted file mode 100644 index 77a7ecd..0000000 --- a/src/base/dev/sb16/mt32.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: glue between dosemu2's mpu401 and softmpu. - * - * Author: @stsp - * - */ -#include "pic.h" -#include "dosemu_debug.h" -#include "sound/midi.h" -#include "iodev.h" -#include "emu.h" -#include "softmpu/export.h" -#include "mpu401.h" - -struct mt32state_s { - struct mpu401_s *mpu; - unsigned int irq_active:1; -}; - -static struct mt32state_s mt32; - -static void mpu_activate_irq(struct mpu401_s *mpu) -{ - if (mt32.irq_active) { - S_printf("MT32: Warning: Interrupt already active!\n"); - return; - } - S_printf("MT32: Activating irq %d\n", config.mpu401_irq_mt32); - mt32.irq_active = 1; - pic_request(config.mpu401_irq_mt32); -} - -static void mpu_deactivate_irq(struct mpu401_s *mpu) -{ - S_printf("MT32: Deactivating irq %d\n", config.mpu401_irq_mt32); - if (!mt32.irq_active) { - S_printf("MT32: Warning: Interrupt not active!\n"); - return; - } - mt32.irq_active = 0; - pic_untrigger(config.mpu401_irq_mt32); -} - -static void mpu_run_irq(struct mpu401_s *mpu) -{ - if (!mt32.irq_active) - return; - S_printf("MT32: Run irq %d\n", config.mpu401_irq_mt32); - pic_untrigger(config.mpu401_irq_mt32); - pic_request(config.mpu401_irq_mt32); -} - -static void mpu_write_midi(struct mpu401_s *mpu, uint8_t data) -{ - if (mpu401_is_uart(mpu)) - midi_write(data, ST_ANY); - else - MPU401_WriteData(data); -} - -static void mpu_cmd_hook(struct mpu401_s *mpu, uint8_t cmd) -{ - MPU401_WriteCommand(cmd); -} - -static void mpu_read_hook(struct mpu401_s *mpu, uint8_t data) -{ - MPU401_ReadData(data); -} - -static struct mpu401_ops mops = { - .activate_irq = mpu_activate_irq, - .deactivate_irq = mpu_deactivate_irq, - .run_irq = mpu_run_irq, - .write_midi = mpu_write_midi, - .cmd_hook = mpu_cmd_hook, - .read_hook = mpu_read_hook, - .name = "MT32 MPU401" -}; - -void mt32_init(void) -{ - if (config.mpu401_irq_mt32 == 2) { - error("irq2 for mt32 not supported, using irq 9\n"); - config.mpu401_irq_mt32 = 9; - } - mt32.irq_active = 0; - mt32.mpu = mpu401_init(config.mpu401_base_mt32, &mops); - MPU401_Init(); - S_printf("MT32: Initialisation completed\n"); -} - -void mt32_reset(void) -{ - mpu401_reset(mt32.mpu); // this also deactivates irq -} - -void mt32_done(void) -{ - mpu401_done(mt32.mpu); - MPU401_Done(); -} - -void QueueByte(Bit8u data) -{ - mpu401_put_midi_in_byte(mt32.mpu, data); -} - -void ClrQueue(void) -{ - mpu401_clear_midi_in_fifo(mt32.mpu); -} diff --git a/src/base/dev/sb16/opl.c b/src/base/dev/sb16/opl.c index 5ce6e1f..f404c6c 100644 --- a/src/base/dev/sb16/opl.c +++ b/src/base/dev/sb16/opl.c @@ -50,6 +50,9 @@ static Bit32s vibval_var2[BLOCKBUF_SIZE]; //static Bit32s vibval_var3[BLOCKBUF_SIZE]; //static Bit32s vibval_var4[BLOCKBUF_SIZE]; +// vibrato/trmolo value table pointers +static Bit32s *vibval1, *vibval2, *vibval3, *vibval4; +static Bit32s *tremval1, *tremval2, *tremval3, *tremval4; // key scale level lookup table @@ -966,9 +969,6 @@ void opl_getsample(Bit16s* sndptr, Bits numsamples) { // vibrato/tremolo lookup tables (global, to possibly be used by all operators) Bit32s vib_lut[BLOCKBUF_SIZE]; Bit32s trem_lut[BLOCKBUF_SIZE]; - // vibrato/trmolo value table pointers - Bit32s *vibval1, *vibval2, *vibval3, *vibval4; - Bit32s *tremval1, *tremval2, *tremval3, *tremval4; Bits samples_to_process = numsamples; Bits cursmp; diff --git a/src/base/dev/sb16/sb16.c b/src/base/dev/sb16/sb16.c index 2a023d5..204e676 100644 --- a/src/base/dev/sb16/sb16.c +++ b/src/base/dev/sb16/sb16.c @@ -36,15 +36,13 @@ #include "bitops.h" #include "port.h" #include "sound/sound.h" -#include "sound/midi.h" #include "sound.h" #include "dspio.h" #include "adlib.h" -#include "mpu401.h" #include "sb16.h" #include -static int sb_irq_tab[] = { 9 /* 2 actually */, 5, 7, 10 }; +static int sb_irq_tab[] = { 2, 5, 7, 10 }; static int sb_dma_tab[] = { 0, 1, 3 }; static int sb_hdma_tab[] = { 5, 6, 7 }; @@ -60,51 +58,8 @@ static int sb_hdma_tab[] = { 5, 6, 7 }; #define SB_GET_STATUS() ((rng_count(&sb.dsp_queue) ? SB_DATA_AVAIL : \ SB_DATA_UNAVAIL) | SB_DSP_STATUS) -/* - * DSP information / states - */ -enum { DMA_RESTART_NONE, DMA_RESTART_PENDING, DMA_RESTART_AUTOINIT }; -struct sb_struct { - uint16_t rate; /* The current sample rate for input */ - uint8_t test; /* Storage for the test value */ - uint8_t reset_val; - unsigned int paused:1; /* is DMA transfer paused? */ - unsigned int reset:1; - uint8_t midi_cmd; - uint8_t dma_cmd; /* Information we need on the DMA transfer */ - uint8_t dma_mode; /* Information we need on the DMA transfer */ - unsigned int dma_exit_ai:1; /* exit DMA autoinit */ - struct { - int val; - unsigned int is_16:1; - unsigned int allow:1; - } dma_restart; /* DMA restart on IRQ ACK */ - uint8_t new_dma_cmd; /* Information we need on the DMA transfer */ - uint8_t new_dma_mode; /* Information we need on the DMA transfer */ - uint16_t dma_init_count; - uint16_t dma_count; - uint8_t mixer_regs[256]; - uint8_t mixer_index; - uint8_t E2Count; - uint8_t asp_regs[256]; - int asp_init; - uint8_t last_data; - int busy; - int irq_pend; - int irq_delay_cnt; -/* All values are imperical! */ -#define SB_DSP_CMD_BUF_SZ 8 - uint8_t command[SB_DSP_CMD_BUF_SZ]; - int command_idx; -#define DSP_QUEUE_SIZE 64 - struct rng_s dsp_queue; - struct dspio_state *dspio; - struct mpu401_s *mpu; -}; - static struct sb_struct sb; -static void process_sb_midi_input(Bit8u val); static int sb_get_dsp_irq_num(void) { @@ -116,6 +71,14 @@ static int sb_get_dsp_irq_num(void) return sb_irq_tab[idx]; } +int get_mpu401_irq_num(void) +{ + if (!dspio_is_mt32_mode()) + return config.mpu401_irq; + return (sb.mpu401_uart ? config.mpu401_uart_irq_mt32 : + config.mpu401_irq_mt32); +} + int sb_get_dma_num(void) { int idx = find_bit(sb.mixer_regs[0x81] & 0x0f); @@ -278,7 +241,7 @@ static int sb_dma_autoinit(void) if (!sb.dma_cmd) error("SB: used inactive DMA (ai)\n"); #if 0 - /* if speaker state is not consistent with direction, don't autoinit - correct? */ + /* if speaker state is not consistent with direction, dont autoinit - correct? */ if (!(sb_dma_input() ^ sb.speaker)) return 0; #endif @@ -426,9 +389,9 @@ static int sb_irq_active(int type) static void sb_request_irq(int type) { if (type & SB_IRQ_DSP) - pic_request(sb_get_dsp_irq_num()); + pic_request(pic_irq_list[sb_get_dsp_irq_num()]); if (type & SB_IRQ_MPU401) - pic_request(config.mpu401_irq); + pic_request(pic_irq_list[get_mpu401_irq_num()]); } static void sb_activate_irq(int type) @@ -445,7 +408,7 @@ static void sb_activate_irq(int type) static void sb_deactivate_irq(int type) { uint32_t act_map; - int mpu_irq = config.mpu401_irq; + int mpu_irq = get_mpu401_irq_num(); S_printf("SB: Deactivating irq type %d\n", type); if (!(sb.mixer_regs[0x82] & type)) { @@ -460,11 +423,11 @@ static void sb_deactivate_irq(int type) ((!!(sb.mixer_regs[0x82] & SB_IRQ_MPU401)) << mpu_irq); if (type & SB_IRQ_DSP) { if (!(act_map & (1 << sb_get_dsp_irq_num()))) - pic_untrigger(sb_get_dsp_irq_num()); + pic_untrigger(pic_irq_list[sb_get_dsp_irq_num()]); } if (type & SB_IRQ_MPU401) { if (!(act_map & (1 << mpu_irq))) - pic_untrigger(mpu_irq); + pic_untrigger(pic_irq_list[mpu_irq]); } } @@ -473,10 +436,6 @@ static void sb_run_irq(int type) if (!sb_irq_active(type)) return; S_printf("SB: Run irq type %d\n", type); - if (type & SB_IRQ_DSP) - pic_untrigger(sb_get_dsp_irq_num()); - if (type & SB_IRQ_MPU401) - pic_untrigger(config.mpu401_irq); sb_request_irq(type); } @@ -568,7 +527,6 @@ static void sb_dsp_reset(void) dspio_toggle_speaker(sb.dspio, 0); dspio_clear_fifos(sb.dspio); rng_clear(&sb.dsp_queue); - sb_deactivate_irq(SB_IRQ_ALL); sb.paused = 0; sb.midi_cmd = 0; sb.dma_mode = 0; @@ -706,22 +664,6 @@ static void sb_reset(void) sb.busy = 1; sb_mixer_reset(); adlib_reset(); - mpu401_reset(sb.mpu); -} - -static void do_process_midi(void) -{ - Bit8u data; - - if (sb_midi_input()) { - int cnt = 0; - while (midi_get_data_byte(&data)) { - process_sb_midi_input(data); - cnt++; - } - if (cnt && sb_midi_int()) - sb_activate_irq(SB_IRQ_MIDI); - } } /* @@ -882,7 +824,7 @@ static void sb_dsp_write(Bit8u value) case 0x38: /* Midi Write */ REQ_PARAMS(1); S_printf("SB: Write 0x%x to SB Midi Port\n", sb.command[1]); - midi_write(sb.command[1], ST_GM); + dspio_write_midi(sb.dspio, sb.command[1]); break; /* == SAMPLE SPEED == */ @@ -1075,7 +1017,7 @@ static void sb_dsp_write(Bit8u value) negmsk &= 0x0f; if (test_bit(i, &sb.command[1])) incval += - ((1 << sb.E2Count) & negmsk) ? -inctmp : inctmp; + test_bit_i(sb.E2Count, negmsk) ? -inctmp : inctmp; inctmp <<= 1; } incmagic = E2_incmagic; @@ -1121,13 +1063,13 @@ static void sb_dsp_write(Bit8u value) /* 8-bit IRQ - SB */ case 0xF2: S_printf("SB: Activating 8bit IRQ\n"); - sb.irq_pend |= SB_IRQ_8BIT; + sb_activate_irq(SB_IRQ_8BIT); break; /* 16-bit IRQ - SB16 */ case 0xF3: S_printf("SB: Activating 16bit IRQ\n"); - sb.irq_pend |= SB_IRQ_8BIT; + sb_activate_irq(SB_IRQ_16BIT); break; case 0xf9: /* from bochs */ @@ -1587,7 +1529,7 @@ int sb_mixer_get_chan_num(enum MixChan ch) * DANG_END_FUNCTION */ -static void sb_io_write(ioport_t port, Bit8u value, void *arg) +static void sb_io_write(ioport_t port, Bit8u value) { ioport_t addr; addr = port - config.sb_base; @@ -1632,7 +1574,7 @@ static void sb_io_write(ioport_t port, Bit8u value, void *arg) /* == DSP == */ case 0x0C: /* dsp write register */ if (sb_midi_uart()) { - midi_write(value, ST_GM); + dspio_write_midi(sb.dspio, value); break; } if (sb_dma_active() && sb_dma_high_speed()) { @@ -1660,7 +1602,7 @@ static void sb_io_write(ioport_t port, Bit8u value, void *arg) * DANG_END_FUNCTION */ -static Bit8u sb_io_read(ioport_t port, void *arg) +static Bit8u sb_io_read(ioport_t port) { ioport_t addr; Bit8u result = 0; @@ -1790,35 +1732,157 @@ int sb_get_dma_data(void *ptr, int is16bit) return 0; } -static void process_sb_midi_input(Bit8u val) +static Bit8u mpu401_io_read(ioport_t port) { + ioport_t addr; + Bit8u r = 0xff; + + addr = port - config.mpu401_base; + + switch (addr) { + case 0: + /* Read data port */ + if (dspio_get_midi_in_fillup(sb.dspio)) + r = dspio_get_midi_in_byte(sb.dspio); + else + S_printf("MPU401: ERROR: No data to read\n"); + S_printf("MPU401: Read data port = 0x%02x, %i bytes still in queue\n", + r, dspio_get_midi_in_fillup(sb.dspio)); + if (!dspio_get_midi_in_fillup(sb.dspio)) + sb_deactivate_irq(SB_IRQ_MPU401); + sb_run_irq(SB_IRQ_MPU401); + break; + case 1: + /* Read status port */ + /* 0x40=OUTPUT_AVAIL; 0x80=INPUT_AVAIL */ + r = 0xff & (~0x40); /* Output is always possible */ + if (dspio_get_midi_in_fillup(sb.dspio)) + r &= (~0x80); + S_printf("MPU401: Read status port = 0x%02x\n", r); + break; + } + return r; +} + +static void mpu401_io_write(ioport_t port, Bit8u value) +{ + uint32_t addr; + addr = port - config.mpu401_base; + + switch (addr) { + case 0: + /* Write data port */ + if (debug_level('S') > 5) + S_printf("MPU401: Write 0x%02x to data port\n", value); + dspio_write_midi(sb.dspio, value); + if (!sb.mpu401_uart && debug_level('S') > 5) + S_printf("MPU401: intelligent mode write unhandled\n"); + break; + case 1: + /* Write command port */ + S_printf("MPU401: Write 0x%02x to command port\n", value); + dspio_clear_midi_in_fifo(sb.dspio); + /* the following doc: + * http://www.piclist.com/techref/io/serial/midi/mpu.html + * says 3f does not need ACK. But dosbox sources say that + * it does. Someone please try on a real HW? */ + dspio_put_midi_in_byte(sb.dspio, 0xfe); /* A command is sent: MPU_ACK it next time */ + switch (value) { + case 0x3f: // 0x3F = UART mode + sb.mpu401_uart = 1; + break; + case 0xff: // 0xFF = reset MPU + sb.mpu401_uart = 0; + dspio_stop_midi(sb.dspio); + break; + case 0x80: // Clock ?? + break; + case 0xac: // Query version + dspio_put_midi_in_byte(sb.dspio, 0x15); + break; + case 0xad: // Query revision + dspio_put_midi_in_byte(sb.dspio, 0x1); + break; + } + sb_activate_irq(SB_IRQ_MPU401); + break; + } +} + +static void process_sb_midi_input(void) +{ + Bit8u tmp; if (sb_midi_timestamp()) { Bit32u time = dspio_get_midi_in_time(sb.dspio); dsp_write_output(time); dsp_write_output(time >> 8); dsp_write_output(time >> 16); } - dsp_write_output(val); + tmp = dspio_get_midi_in_byte(sb.dspio); + dsp_write_output(tmp); +} + +void sb_handle_midi_data(void) +{ +#define MPU401_IN_FIFO_TRIGGER 1 + if (sb_midi_input()) { + while (dspio_get_midi_in_fillup(sb.dspio)) + process_sb_midi_input(); + if (sb_midi_int()) + sb_activate_irq(SB_IRQ_MIDI); + } else if (sb.mpu401_uart) { + if (dspio_get_midi_in_fillup(sb.dspio) == MPU401_IN_FIFO_TRIGGER) + sb_activate_irq(SB_IRQ_MPU401); + } } void run_sb(void) { if (!config.sound) return; + dspio_timer(sb.dspio); +} - /* https://github.com/dosemu2/dosemu2/issues/2172 */ - if (sb.irq_pend /*&& ++sb.irq_delay_cnt > 5*/) { - if (sb.irq_pend & SB_IRQ_8BIT) - sb_activate_irq(SB_IRQ_8BIT); - if (sb.irq_pend & SB_IRQ_16BIT) - sb_activate_irq(SB_IRQ_16BIT); - sb.irq_pend = 0; - sb.irq_delay_cnt = 0; +static void mpu401_init(void) +{ + emu_iodev_t io_device; + + S_printf("MPU401: MPU-401 Initialisation\n"); + + if (config.mpu401_irq == -1) { + config.mpu401_irq = config.sb_irq; + config.mpu401_uart_irq_mt32 = config.mpu401_irq_mt32; + S_printf("SB: mpu401 irq set to %i\n", config.mpu401_irq); + } else { + config.mpu401_uart_irq_mt32 = config.mpu401_irq; } - dspio_timer(sb.dspio); - do_process_midi(); - mpu401_process(sb.mpu); + /* This is the MPU-401 */ + io_device.read_portb = mpu401_io_read; + io_device.write_portb = mpu401_io_write; + io_device.read_portw = NULL; + io_device.write_portw = NULL; + io_device.read_portd = NULL; + io_device.write_portd = NULL; + io_device.handler_name = "Midi Emulation"; + io_device.start_addr = config.mpu401_base; + io_device.end_addr = config.mpu401_base + 0x001; + if (config.mpu401_irq == config.sb_irq) { + S_printf("SB: same irq for DSP and MPU401\n"); + io_device.irq = EMU_NO_IRQ; + } else { + io_device.irq = config.mpu401_irq; + } + io_device.fd = -1; + if (port_register_handler(io_device, 0) != 0) + error("MPU-401: Cannot registering port handler\n"); + + S_printf("MPU401: MPU-401 Initialisation - Base 0x%03x \n", + config.mpu401_base); +} + +static void mpu401_done(void) +{ } static void sb_dsp_init(void) @@ -1833,34 +1897,6 @@ static void sb_dsp_done(void) rng_destroy(&sb.dsp_queue); } -static void mpu_activate_irq(struct mpu401_s *mpu) -{ - sb_activate_irq(SB_IRQ_MPU401); -} - -static void mpu_deactivate_irq(struct mpu401_s *mpu) -{ - sb_deactivate_irq(SB_IRQ_MPU401); -} - -static void mpu_run_irq(struct mpu401_s *mpu) -{ - sb_run_irq(SB_IRQ_MPU401); -} - -static void mpu_write_midi(struct mpu401_s *mpu, uint8_t data) -{ - midi_write(data, ST_GM); -} - -static struct mpu401_ops mops = { - .activate_irq = mpu_activate_irq, - .deactivate_irq = mpu_deactivate_irq, - .run_irq = mpu_run_irq, - .write_midi = mpu_write_midi, - .name = "SB MPU401" -}; - /* * Sound Initialisation * ==================== @@ -1881,6 +1917,8 @@ static void sb_init(void) io_device.handler_name = "SB Emulation"; io_device.start_addr = config.sb_base; io_device.end_addr = config.sb_base + 0x013; + io_device.irq = config.sb_irq; + io_device.fd = -1; if (port_register_handler(io_device, 0) != 0) { error("SB: Cannot registering DSP port handler\n"); } @@ -1888,12 +1926,7 @@ static void sb_init(void) sb_dsp_init(); sb_mixer_init(); opl3_init(); - - if (config.mpu401_irq == -1) { - config.mpu401_irq = config.sb_irq; - S_printf("SB: mpu401 irq set to %i\n", config.mpu401_irq); - } - sb.mpu = mpu401_init(config.mpu401_base, &mops); + mpu401_init(); S_printf("SB: Initialisation - Base 0x%03x\n", config.sb_base); } @@ -1902,7 +1935,7 @@ static void sb_done(void) { sb_dsp_done(); adlib_done(); - mpu401_done(sb.mpu); + mpu401_done(); } void sound_init(void) @@ -1911,7 +1944,7 @@ void sound_init(void) return; sb.dspio = dspio_init(); if (!sb.dspio) { - error("dspio failed\n"); + error("dspio faild\n"); leavedos(93); } sb_init(); diff --git a/src/base/dev/sb16/sb16.h b/src/base/dev/sb16/sb16.h index 63da504..bcd7270 100644 --- a/src/base/dev/sb16/sb16.h +++ b/src/base/dev/sb16/sb16.h @@ -43,6 +43,46 @@ #define SB_IRQ_DSP (SB_IRQ_8BIT | SB_IRQ_16BIT | SB_IRQ_MIDI) #define SB_IRQ_ALL (SB_IRQ_DSP | SB_IRQ_MPU401) +/* + * DSP information / states + */ +enum { DMA_RESTART_NONE, DMA_RESTART_PENDING, DMA_RESTART_AUTOINIT }; +struct sb_struct { + uint16_t rate; /* The current sample rate for input */ + uint8_t test; /* Storage for the test value */ + uint8_t reset_val; + int paused:1; /* is DMA transfer paused? */ + int reset:1; + int mpu401_uart:1; + uint8_t midi_cmd; + uint8_t dma_cmd; /* Information we need on the DMA transfer */ + uint8_t dma_mode; /* Information we need on the DMA transfer */ + int dma_exit_ai:1; /* exit DMA autoinit */ + struct { + int val; + int is_16:1; + int allow:1; + } dma_restart; /* DMA restart on IRQ ACK */ + uint8_t new_dma_cmd; /* Information we need on the DMA transfer */ + uint8_t new_dma_mode; /* Information we need on the DMA transfer */ + uint16_t dma_init_count; + uint16_t dma_count; + uint8_t mixer_regs[256]; + uint8_t mixer_index; + uint8_t E2Count; + uint8_t asp_regs[256]; + int asp_init; + uint8_t last_data; + int busy; +/* All values are imperical! */ +#define SB_DSP_CMD_BUF_SZ 8 + uint8_t command[SB_DSP_CMD_BUF_SZ]; + int command_idx; +#define DSP_QUEUE_SIZE 64 + struct rng_s dsp_queue; + void *dspio; +}; + extern int sb_get_dma_num(void); extern int sb_get_hdma_num(void); extern int sb_dma_active(void); @@ -60,6 +100,7 @@ extern void sb_handle_dma(void); extern void sb_dma_nack(void); extern void sb_handle_dma_timeout(void); extern int sb_input_enabled(void); +extern void sb_handle_midi_data(void); enum MixRet sb_mixer_get_input_volume(enum MixChan ch, enum MixSubChan sc, double *r_vol); diff --git a/src/base/dev/sb16/softmpu/Makefile b/src/base/dev/sb16/softmpu/Makefile deleted file mode 100644 index 6207d9e..0000000 --- a/src/base/dev/sb16/softmpu/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". -# -# for details see file COPYING.DOSEMU in the DOSEMU distribution -# - -top_builddir=../../../../.. -include $(top_builddir)/Makefile.conf - - -CFILES = mpu401.c pic.c - -include $(REALTOPDIR)/src/Makefile.common diff --git a/src/base/dev/sb16/softmpu/export.h b/src/base/dev/sb16/softmpu/export.h deleted file mode 100644 index ea210ac..0000000 --- a/src/base/dev/sb16/softmpu/export.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2002-2012 The DOSBox Team - * Copyright (C) 2013-2014 bjt, elianda - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * ------------------------------------------ - * SoftMPU by bjt - Software MPU-401 Emulator - * ------------------------------------------ - * - * C types/functions used from ASM - * - */ - -#ifndef EXPORT_H - -typedef unsigned char Bit8u; -typedef unsigned int Bitu; - -typedef enum EventID {MPU_EVENT,RESET_DONE,EOI_HANDLER,NUM_EVENTS} EventID; - -/* Interface functions */ -void MPU401_Init(void); -void MPU401_Done(void); -void MPU401_WriteCommand(Bit8u val); -void MPU401_ReadData(Bit8u val); -void MPU401_WriteData(Bit8u val); - -void MPU401_Event(void); -void MPU401_ResetDone(void); -void MPU401_EOIHandler(void); - -void PIC_Init(void); /* SOFTMPU */ -void PIC_Done(void); -void PIC_AddEvent(EventID event,Bitu delay); -void PIC_RemoveEvents(EventID event); -void PIC_Start(void); -void PIC_Stop(void); - -void QueueByte(Bit8u data); -void ClrQueue(void); - -#define EXPORT_H -#endif diff --git a/src/base/dev/sb16/softmpu/mpu401.c b/src/base/dev/sb16/softmpu/mpu401.c deleted file mode 100644 index 5f44393..0000000 --- a/src/base/dev/sb16/softmpu/mpu401.c +++ /dev/null @@ -1,638 +0,0 @@ -/* rip-off for dosemu2 project by stsp */ -/* - * Copyright (C) 2002-2012 The DOSBox Team - * Copyright (C) 2013-2014 bjt, elianda - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * ------------------------------------------ - * SoftMPU by bjt - Software MPU-401 Emulator - * ------------------------------------------ - * - * Based on original mpu401.c from DOSBox - * - */ -#include "sound/midi.h" -#include "pic.h" -#include "emu.h" -/* SOFTMPU: Moved exported functions & types to header */ -#include "export.h" - -/* SOFTMPU: Additional defines, typedefs etc. for C */ -typedef unsigned short Bit16u; -typedef int Bits; - -static void MIDI_RawOutByte(Bit8u data) -{ - midi_write(data, ST_MT32); -} - -void MPU401_Event(void); -void MPU401_ResetDone(void); /* SOFTMPU */ -void MPU401_EOIHandler(void); -static void MPU401_Reset(void); -static void MPU401_EOIHandlerDispatch(void); - -#define MPU401_VERSION 0x15 -#define MPU401_REVISION 0x01 -#define MPU401_TIMECONSTANT (60000000 / 1000.0) -#define MPU401_RESETBUSY 14.0 - -enum MpuMode { M_UART,M_INTELLIGENT }; -typedef enum MpuMode MpuMode; /* SOFTMPU */ -enum MpuDataType {T_OVERFLOW,T_MARK,T_MIDI_SYS,T_MIDI_NORM,T_COMMAND}; -typedef enum MpuDataType MpuDataType; /* SOFTMPU */ - -/* Messages sent to MPU-401 from host */ -#define MSG_EOX 0xf7 -#define MSG_OVERFLOW 0xf8 -#define MSG_MARK 0xfc - -/* Messages sent to host from MPU-401 */ -#define MSG_MPU_OVERFLOW 0xf8 -#define MSG_MPU_COMMAND_REQ 0xf9 -#define MSG_MPU_END 0xfc -#define MSG_MPU_CLOCK 0xfd -#define MSG_MPU_ACK 0xfe - -static struct { - bool intelligent; - bool generate_irqs; /* SOFTMPU */ - bool mpu_ver_fix; /* SOFTMPU */ - MpuMode mode; - /*Bitu irq;*/ /* SOFTMPU */ - struct track { - Bits counter; - Bit8u value[8],sys_val; - Bit8u vlength,length; - MpuDataType type; - } playbuf[8],condbuf; - struct { - bool conductor,cond_req,cond_set, block_ack; - bool playing,reset; - bool wsd,wsm,wsd_start; - bool run_irq,irq_pending; - bool send_now; - bool eoi_scheduled; - Bits data_onoff; - Bitu command_byte,cmd_pending; - Bit8u tmask,cmask,amask; - Bit16u midi_mask; - Bit16u req_mask; - Bit8u channel,old_chan; - } state; - struct { - Bit8u timebase; - Bit8u tempo; - Bit8u tempo_rel; - Bit8u tempo_grad; - Bit8u cth_rate,cth_counter; - bool clock_to_host,cth_active; - } clock; -} mpu; - -void MPU401_WriteCommand(Bit8u val) /* SOFTMPU */ -{ - Bitu i; /* SOFTMPU */ - if (mpu.state.reset) { - if (mpu.state.cmd_pending || (val!=0x3f && val!=0xff)) { - mpu.state.cmd_pending=val+1; - return; - } - PIC_RemoveEvents(RESET_DONE); - mpu.state.reset=false; - } - if (val<=0x2f) { - switch (val&3) { /* MIDI stop, start, continue */ - case 1: {MIDI_RawOutByte(0xfc);break;} - case 2: {MIDI_RawOutByte(0xfa);break;} - case 3: {MIDI_RawOutByte(0xfb);break;} - } - /*if (val&0x20) LOG(LOG_MISC,LOG_ERROR)("MPU-401:Unhandled Recording Command %x",val);*/ /* SOFTMPU */ - switch (val&0xc) { - case 0x4: /* Stop */ - PIC_RemoveEvents(MPU_EVENT); - PIC_Stop(); - mpu.state.playing=false; - for (i=0xb0;i<0xbf;i++) { /* All notes off */ - MIDI_RawOutByte((Bit8u)i); - MIDI_RawOutByte(0x7b); - MIDI_RawOutByte(0); - } - break; - case 0x8: /* Play */ - /*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Intelligent mode playback started");*/ /* SOFTMPU */ - mpu.state.playing=true; - PIC_RemoveEvents(MPU_EVENT); - PIC_AddEvent(MPU_EVENT,(Bitu)MPU401_TIMECONSTANT/(mpu.clock.tempo*mpu.clock.timebase)); - PIC_Start(); - ClrQueue(); - break; - } - } - else if (val>=0xa0 && val<=0xa7) { /* Request play counter */ - if (mpu.state.cmask&(1<<(val&7))) QueueByte((Bit8u)mpu.playbuf[val&7].counter); - } - else if (val>=0xd0 && val<=0xd7) { /* Send data */ - mpu.state.old_chan=mpu.state.channel; - mpu.state.channel=val&7; - mpu.state.wsd=true; - mpu.state.wsm=false; - mpu.state.wsd_start=true; - } - else - switch (val) { - case 0xdf: /* Send system message */ - mpu.state.wsd=false; - mpu.state.wsm=true; - mpu.state.wsd_start=true; - break; - case 0x8e: /* Conductor */ - mpu.state.cond_set=false; - break; - case 0x8f: - mpu.state.cond_set=true; - break; - case 0x94: /* Clock to host */ - mpu.clock.clock_to_host=false; - break; - case 0x95: - mpu.clock.clock_to_host=true; - break; - case 0xc2: /* Internal timebase */ - mpu.clock.timebase=48; - break; - case 0xc3: - mpu.clock.timebase=72; - break; - case 0xc4: - mpu.clock.timebase=96; - break; - case 0xc5: - mpu.clock.timebase=120; - break; - case 0xc6: - mpu.clock.timebase=144; - break; - case 0xc7: - mpu.clock.timebase=168; - break; - case 0xc8: - mpu.clock.timebase=192; - break; - /* Commands with data byte */ - case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6: - case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef: - mpu.state.command_byte=val; - break; - /* Commands 0xa# returning data */ - case 0xab: /* Request and clear recording counter */ - QueueByte(MSG_MPU_ACK); - QueueByte(0); - return; - case 0xac: /* Request version */ - if (mpu.mpu_ver_fix) - { - /* SOFTMPU: Fix missing music in Gateway by reversing version and ACK */ - QueueByte(MPU401_VERSION); - QueueByte(MSG_MPU_ACK); - } - else - { - QueueByte(MSG_MPU_ACK); - QueueByte(MPU401_VERSION); - } - return; - case 0xad: /* Request revision */ - QueueByte(MSG_MPU_ACK); - QueueByte(MPU401_REVISION); - return; - case 0xaf: /* Request tempo */ - QueueByte(MSG_MPU_ACK); - QueueByte(mpu.clock.tempo); - return; - case 0xb1: /* Reset relative tempo */ - mpu.clock.tempo_rel=40; - break; - case 0xb9: /* Clear play map */ - case 0xb8: /* Clear play counters */ - for (i=0xb0;i<0xbf;i++) { /* All notes off */ - MIDI_RawOutByte((Bit8u)i); - MIDI_RawOutByte(0x7b); - MIDI_RawOutByte(0); - } - for (i=0;i<8;i++) { - mpu.playbuf[i].counter=0; - mpu.playbuf[i].type=T_OVERFLOW; - } - mpu.condbuf.counter=0; - mpu.condbuf.type=T_OVERFLOW; - if (!(mpu.state.conductor=mpu.state.cond_set)) mpu.state.cond_req=0; - mpu.state.amask=mpu.state.tmask; - mpu.state.req_mask=0; - mpu.state.irq_pending=true; - break; - case 0xff: /* Reset MPU-401 */ - /*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Reset %X",val);*/ /* SOFTMPU */ - PIC_AddEvent(RESET_DONE,MPU401_RESETBUSY); - mpu.state.reset=true; - MPU401_Reset(); - if (mpu.mode==M_UART) return;//do not send ack in UART mode - break; - case 0x3f: /* UART mode */ - /*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Set UART mode %X",val);*/ /* SOFTMPU */ - mpu.mode=M_UART; - break; - default: - /*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Unhandled command %X",val);*/ - break; - } - QueueByte(MSG_MPU_ACK); -} - -void MPU401_ReadData(Bit8u data) /* SOFTMPU */ -{ - Bit8u ret=data; - -// if ((mpu.queue_used == 0) && mpu.generate_irqs) PIC_DeActivateIRQ(); /* SOFTMPU */ - - if (ret>=0xf0 && ret<=0xf7) { /* MIDI data request */ - mpu.state.channel=ret&7; - mpu.state.data_onoff=0; - mpu.state.cond_req=false; - } - if (ret==MSG_MPU_COMMAND_REQ) { - mpu.state.data_onoff=0; - mpu.state.cond_req=true; - if (mpu.condbuf.type!=T_OVERFLOW) { - mpu.state.block_ack=true; - MPU401_WriteCommand(mpu.condbuf.value[0]); - if (mpu.state.command_byte) MPU401_WriteData(mpu.condbuf.value[1]); - } - mpu.condbuf.type=T_OVERFLOW; - } - if (ret==MSG_MPU_END || ret==MSG_MPU_CLOCK || ret==MSG_MPU_ACK) { - mpu.state.data_onoff=-1; - MPU401_EOIHandlerDispatch(); - } -} - -void MPU401_WriteData(Bit8u val) { /* SOFTMPU */ - static Bitu length,cnt,posd; /* SOFTMPU */ - if (mpu.mode==M_UART) {MIDI_RawOutByte((Bit8u)val);return;} - switch (mpu.state.command_byte) { /* 0xe# command data */ - case 0x00: - break; - case 0xe0: /* Set tempo */ - mpu.state.command_byte=0; - mpu.clock.tempo=val; - return; - case 0xe1: /* Set relative tempo */ - mpu.state.command_byte=0; - /*if (val!=0x40) //default value - LOG(LOG_MISC,LOG_ERROR)("MPU-401:Relative tempo change not implemented");*/ /* SOFTMPU */ - return; - case 0xe7: /* Set internal clock to host interval */ - mpu.state.command_byte=0; - mpu.clock.cth_rate=val>>2; - return; - case 0xec: /* Set active track mask */ - mpu.state.command_byte=0; - mpu.state.tmask=val; - return; - case 0xed: /* Set play counter mask */ - mpu.state.command_byte=0; - mpu.state.cmask=val; - return; - case 0xee: /* Set 1-8 MIDI channel mask */ - mpu.state.command_byte=0; - mpu.state.midi_mask&=0xff00; - mpu.state.midi_mask|=val; - return; - case 0xef: /* Set 9-16 MIDI channel mask */ - mpu.state.command_byte=0; - mpu.state.midi_mask&=0x00ff; - mpu.state.midi_mask|=((Bit16u)val)<<8; - return; - //case 0xe2: /* Set graduation for relative tempo */ - //case 0xe4: /* Set metronome */ - //case 0xe6: /* Set metronome measure length */ - default: - mpu.state.command_byte=0; - return; - } - if (mpu.state.wsd) { /* Directly send MIDI message */ - if (mpu.state.wsd_start) { - mpu.state.wsd_start=0; - cnt=0; - switch (val&0xf0) { - case 0xc0:case 0xd0: - mpu.playbuf[mpu.state.channel].value[0]=val; - length=2; - break; - case 0x80:case 0x90:case 0xa0:case 0xb0:case 0xe0: - mpu.playbuf[mpu.state.channel].value[0]=val; - length=3; - break; - case 0xf0: - /*LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal WSD byte");*/ /* SOFTMPU */ - mpu.state.wsd=0; - mpu.state.channel=mpu.state.old_chan; - return; - default: /* MIDI with running status */ - cnt++; - MIDI_RawOutByte(mpu.playbuf[mpu.state.channel].value[0]); - } - } - if (cnt0xf7) { - mpu.playbuf[mpu.state.channel].type=T_MARK; - mpu.playbuf[mpu.state.channel].sys_val=val; - length=1; - } else { - /*LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal message");*/ /* SOFTMPU */ - mpu.playbuf[mpu.state.channel].type=T_MIDI_SYS; - mpu.playbuf[mpu.state.channel].sys_val=val; - length=1; - } - break; - case 0xc0: case 0xd0: /* MIDI Message */ - mpu.playbuf[mpu.state.channel].type=T_MIDI_NORM; - length=mpu.playbuf[mpu.state.channel].length=2; - break; - case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xe0: - mpu.playbuf[mpu.state.channel].type=T_MIDI_NORM; - length=mpu.playbuf[mpu.state.channel].length=3; - break; - default: /* MIDI data with running status */ - posd++; - mpu.playbuf[mpu.state.channel].vlength++; - mpu.playbuf[mpu.state.channel].type=T_MIDI_NORM; - length=mpu.playbuf[mpu.state.channel].length; - break; - } - } - if (!(posd==1 && val>=0xf0)) mpu.playbuf[mpu.state.channel].value[posd-1]=val; - if (posd==length) MPU401_EOIHandlerDispatch(); - } -} - -static void MPU401_IntelligentOut(Bit8u chan) { - Bitu val, i; /* SOFTMPU */ - switch (mpu.playbuf[chan].type) { - case T_OVERFLOW: - break; - case T_MARK: - val=mpu.playbuf[chan].sys_val; - if (val==0xfc) { - MIDI_RawOutByte((Bit8u)val); - mpu.state.amask&=~(1<= mpu.clock.cth_rate) { - mpu.clock.cth_counter=0; - mpu.state.req_mask|=(1<<13); - } - } - if (!mpu.state.irq_pending && mpu.state.req_mask) MPU401_EOIHandler(); -next_event: - PIC_RemoveEvents(MPU_EVENT); - if ((new_time=mpu.clock.tempo*mpu.clock.timebase)==0) return; - PIC_AddEvent(MPU_EVENT,(Bitu)MPU401_TIMECONSTANT/new_time); -} - -static void MPU401_EOIHandlerDispatch(void) { - if (mpu.state.send_now) { - mpu.state.eoi_scheduled=true; - PIC_AddEvent(EOI_HANDLER,1); // Possible a bit longer - } - else if (!mpu.state.eoi_scheduled) MPU401_EOIHandler(); -} - -//Updates counters and requests new data on "End of Input" -void MPU401_EOIHandler(void) { - Bitu i=0; /* SOFTMPU */ - mpu.state.eoi_scheduled=false; - if (mpu.state.send_now) { - mpu.state.send_now=false; - if (mpu.state.cond_req) UpdateConductor(); - else UpdateTrack(mpu.state.channel); - } - mpu.state.irq_pending=false; - if (!mpu.state.playing || !mpu.state.req_mask) return; - do { - if (mpu.state.req_mask&(1< -#include "sig.h" -#include "evtimer.h" -/* SOFTMPU: Moved exported functions & types to header */ -#include "export.h" - -static void *evtimer; - -static void PIC_Update(int ms_ticks, void *arg); - -static void _MPU401_Event(void *arg) -{ - MPU401_Event(); -} - -static void _MPU401_ResetDone(void *arg) -{ - MPU401_ResetDone(); -} - -static void _MPU401_EOIHandler(void *arg) -{ - MPU401_EOIHandler(); -} - -/* SOFTMPU: Event countdown timers */ -static Bitu event_countdown[NUM_EVENTS]; -static Bitu MIDI_sysex_delay; /* SOFTMPU: Initialised in midi.c */ - -void PIC_AddEvent(EventID event, Bitu delay) -{ - /* Dispatch event immediately on zero delay */ - /* Watch out for blocking loops here... */ - if (delay==0) - { - switch (event) - { - case MPU_EVENT: - /* Don't dispatch immediately as we'll enter an - infinite loop if tempo is high enough */ - delay=1; /* Enforce minimum delay */ - break; - case RESET_DONE: - MPU401_ResetDone(); - break; - case EOI_HANDLER: - MPU401_EOIHandler(); - break; - default: - break; - } - } - - /* SOFTMPU: Set the countdown timer */ - event_countdown[event]=delay; -} - -void PIC_RemoveEvents(EventID event) -{ - /* SOFTMPU: Zero the countdown timer (disable event) */ - event_countdown[event]=0; -} - -void PIC_Start(void) -{ - evtimer_set_rel(evtimer, SCALE_MS, 1); -} - -void PIC_Stop(void) -{ - evtimer_stop(evtimer); -} - -void PIC_Init(void) -{ - Bitu i; - - /* SOFTMPU: Zero countdown timers */ - for (i=0;i= ms_ticks) - { - MIDI_sysex_delay -= ms_ticks; - } - else - MIDI_sysex_delay = 0; - - /* SOFTMPU: Decrement countdown timers and dispatch as needed */ - for (i=0;i 0) { - if (event_countdown[i] >= ms_ticks) - event_countdown[i] -= ms_ticks; - else - event_countdown[i] = 0; - - if (event_countdown[i]==0) - { - /* Dispatch */ - switch (i) - { - case MPU_EVENT: - add_thread_callback(_MPU401_Event, NULL, "mpu401 event"); - break; - case RESET_DONE: - add_thread_callback(_MPU401_ResetDone, NULL, "mpu401 reset done"); - break; - case EOI_HANDLER: - add_thread_callback(_MPU401_EOIHandler, NULL, "mpu401 EOI"); - break; - default: - break; - } - } - } - } -} diff --git a/src/base/dev/vga/attremu.c b/src/base/dev/vga/attremu.c index 5dcb44c..02e3236 100644 --- a/src/base/dev/vga/attremu.c +++ b/src/base/dev/vga/attremu.c @@ -192,7 +192,7 @@ static unsigned char clear_undef_bits(unsigned char i, unsigned char v) * DANG_END_FUNCTION * */ -void Attr_init(void) +void Attr_init() { int i = 0, j; @@ -284,7 +284,7 @@ void Attr_set_entry(unsigned char index, unsigned char value) * DANG_END_FUNCTION * */ -unsigned char Attr_read_value(void) +unsigned char Attr_read_value() { unsigned i = vga.attr.index; unsigned char uc = i | vga.attr.cpu_video; @@ -382,7 +382,7 @@ void Attr_write_value(unsigned char data) * DANG_END_FUNCTION * */ -unsigned char Attr_get_index(void) +unsigned char Attr_get_index() { unsigned char uc = vga.attr.index | vga.attr.cpu_video; diff --git a/src/base/dev/vga/crtcemu.c b/src/base/dev/vga/crtcemu.c index 59c2f89..c7842d9 100644 --- a/src/base/dev/vga/crtcemu.c +++ b/src/base/dev/vga/crtcemu.c @@ -52,7 +52,6 @@ #include "emu.h" #include "vgaemu.h" #include "video.h" -#include "timers.h" // for reset_idle() #include "memory.h" @@ -89,7 +88,7 @@ static unsigned char crtc_ival[16][CRTC_MAX_INDEX + 1] = { * DANG_END_FUNCTION * */ -void CRTC_init(void) +void CRTC_init() { unsigned i, j = 15; @@ -149,7 +148,7 @@ void CRTC_set_index(unsigned char index) } -unsigned char CRTC_get_index(void) +unsigned char CRTC_get_index() { crtc_deb2("CRTC_get_index: 0x%02x\n", (unsigned) vga.crtc.index); @@ -169,8 +168,6 @@ void CRTC_write_value(unsigned char data) crtc_deb2("CRTC_write_value: crtc[0x%02x] = 0x%02x\n", ind, u); - untrigger_idle(); - if(vga.crtc.readonly) { /* read only regs 00h-07h with the exception of bit4 in 07h */ if (ind <= 6) @@ -328,7 +325,7 @@ void CRTC_write_value(unsigned char data) } -unsigned char CRTC_read_value(void) +unsigned char CRTC_read_value() { unsigned char uc; diff --git a/src/base/dev/vga/dacemu.c b/src/base/dev/vga/dacemu.c index 43ef54f..4bdc0c3 100644 --- a/src/base/dev/vga/dacemu.c +++ b/src/base/dev/vga/dacemu.c @@ -181,7 +181,7 @@ static _DAC_entry dac_vga[256] = { * DANG_END_FUNCTION * */ -void DAC_init(void) +void DAC_init() { DAC_entry dac_zero = {True, 0, 0, 0}, de = dac_zero; int i; @@ -403,7 +403,7 @@ void DAC_set_write_index(unsigned char index) * DANG_END_FUNCTION * */ -unsigned char DAC_read_value(void) +unsigned char DAC_read_value() { unsigned char rv; @@ -509,7 +509,7 @@ void DAC_write_value(unsigned char value) * DANG_END_FUNCTION * */ -unsigned char DAC_get_pel_mask(void) +unsigned char DAC_get_pel_mask() { dac_deb("DAC_get_pel_mask: mask = 0x%02x\n", (unsigned) vga.dac.pel_mask); @@ -549,7 +549,7 @@ void DAC_set_pel_mask(unsigned char mask) * DANG_END_FUNCTION * */ -unsigned char DAC_get_state(void) +unsigned char DAC_get_state() { dac_deb("DAC_get_state: state = 0x%02x\n", vga.dac.state); diff --git a/src/base/dev/vga/gfxemu.c b/src/base/dev/vga/gfxemu.c index f52b516..97cfb15 100644 --- a/src/base/dev/vga/gfxemu.c +++ b/src/base/dev/vga/gfxemu.c @@ -100,7 +100,7 @@ static unsigned char gfx_ival[16][2] = { * DANG_END_FUNCTION * */ -void GFX_init(void) +void GFX_init() { unsigned i, j = 15; @@ -152,7 +152,7 @@ void GFX_set_index(unsigned char index) } -unsigned char GFX_get_index(void) +unsigned char GFX_get_index() { gfx_deb2("GFX_get_index: 0x%02x\n", (unsigned) vga.gfx.index); @@ -320,7 +320,7 @@ void GFX_write_value(unsigned char data) } -unsigned char GFX_read_value(void) +unsigned char GFX_read_value() { unsigned char uc; diff --git a/src/base/dev/vga/hercemu.c b/src/base/dev/vga/hercemu.c index 94b21de..96b724e 100644 --- a/src/base/dev/vga/hercemu.c +++ b/src/base/dev/vga/hercemu.c @@ -72,7 +72,7 @@ * DANG_END_FUNCTION * */ -void Herc_init(void) +void Herc_init() { vga.herc.cfg_switch = 0; vga.herc.mode_ctrl = 0; @@ -203,7 +203,7 @@ void Herc_set_mode_ctrl(unsigned char data) * DANG_END_FUNCTION * */ -unsigned char Herc_get_mode_ctrl(void) +unsigned char Herc_get_mode_ctrl() { herc_deb("Herc_get_mode_ctrl: 0x%02x\n", (unsigned) vga.herc.mode_ctrl); diff --git a/src/base/dev/vga/miscemu.c b/src/base/dev/vga/miscemu.c index 1c2ca81..cad2bb9 100644 --- a/src/base/dev/vga/miscemu.c +++ b/src/base/dev/vga/miscemu.c @@ -86,7 +86,7 @@ hitimer_t t_vretrace = 0; /* cf. base/dev/misc/timers.c */ * DANG_END_FUNCTION * */ -void Misc_init(void) +void Misc_init() { unsigned char u; @@ -220,7 +220,7 @@ void Misc_set_color_select(unsigned char data) * DANG_END_FUNCTION * */ -unsigned char Misc_get_misc_output(void) +unsigned char Misc_get_misc_output() { misc_deb("Misc_get_misc_output: 0x%02x\n", (unsigned) vga.misc.misc_output); @@ -256,7 +256,7 @@ void Misc_set_feature_ctrl(unsigned char data) * DANG_END_FUNCTION * */ -unsigned char Misc_get_feature_ctrl(void) +unsigned char Misc_get_feature_ctrl() { misc_deb("Misc_get_feature_ctrl: 0x%02x\n", (unsigned) vga.misc.feature_ctrl); @@ -276,7 +276,7 @@ unsigned char Misc_get_feature_ctrl(void) * DANG_END_FUNCTION * */ -unsigned char Misc_get_input_status_0(void) +unsigned char Misc_get_input_status_0() { unsigned char u = 0; @@ -299,7 +299,7 @@ unsigned char Misc_get_input_status_0(void) * DANG_END_FUNCTION * */ -unsigned char Misc_get_input_status_1(void) +unsigned char Misc_get_input_status_1() { /* * Graphic status - many programs will use this port to sync with diff --git a/src/base/dev/vga/seqemu.c b/src/base/dev/vga/seqemu.c index 2868fee..47a2883 100644 --- a/src/base/dev/vga/seqemu.c +++ b/src/base/dev/vga/seqemu.c @@ -155,7 +155,7 @@ static void seq_map_select(unsigned data) vga.reconfig.re_init = 1; } -void Seq_init(void) +void Seq_init() { unsigned i, j = 15; @@ -209,7 +209,7 @@ void Seq_set_index(unsigned char index) } -unsigned char Seq_get_index(void) +unsigned char Seq_get_index() { seq_deb2("Seq_get_index: 0x%02x\n", (unsigned) vga.seq.index); @@ -328,7 +328,7 @@ void Seq_write_value(unsigned char data) } -unsigned char Seq_read_value(void) +unsigned char Seq_read_value() { unsigned char uc, uc1; diff --git a/src/base/dev/vga/vesa.c b/src/base/dev/vga/vesa.c index 663ea6f..d26c6b2 100644 --- a/src/base/dev/vga/vesa.c +++ b/src/base/dev/vga/vesa.c @@ -54,14 +54,11 @@ #include "video.h" #include "render.h" #include "vgaemu.h" -#include "mapping.h" #include "emudpmi.h" -#include "vesabios_pm_offsets.h" -#include "vesabios_offsets.h" #include "vesa.h" #include "int.h" -#define VBE_BIOS_MAXPAGES 4 /* max. 16k BIOS size, more than enough */ +#define VBE_BIOS_MAXPAGES 2 /* max. 8k BIOS size, more than enough */ /* identity of our VBE implementation */ #define VBE_OEMVendorName "DOSEMU-Development-Team" @@ -114,7 +111,7 @@ void vbe_pre_init(void) int i; vga_mode_info *vmi = NULL; unsigned int dos_vga_bios = SEGOFF2LINEAR(0xc000,0x0000); - int bios_ptr = vgaemu_bios_end - vgaemu_bios_start; + int bios_ptr = (char *) vgaemu_bios_end - (char *) vgaemu_bios_start; static struct { unsigned char modes[3]; @@ -136,12 +133,12 @@ void vbe_pre_init(void) }; MEMSET_DOS(dos_vga_bios, 0, VBE_BIOS_MAXPAGES << 12); /* one page */ - MEMCPY_2DOS(dos_vga_bios, _binary_vesabios_o_bin_start, bios_ptr); + MEMCPY_2DOS(dos_vga_bios, vgaemu_bios_start, bios_ptr); - vgaemu_bios.prod_name = vgaemu_bios_prod_name - vgaemu_bios_start; + vgaemu_bios.prod_name = (char *) vgaemu_bios_prod_name - (char *) vgaemu_bios_start; - if (!config.term) { - i = vgaemu_bios_pm_interface_end - vgaemu_bios_pm_interface; + if (Video->setmode) { + i = (char *) vgaemu_bios_pm_interface_end - (char *) vgaemu_bios_pm_interface; if(i + bios_ptr > (VBE_BIOS_MAXPAGES << 12) - 8) { error("VBE: vbe_init: protected mode interface to large, disabling\n"); @@ -151,7 +148,7 @@ void vbe_pre_init(void) vgaemu_bios.vbe_pm_interface_len = i; vgaemu_bios.vbe_pm_interface = bios_ptr; - MEMCPY_2DOS(dos_vga_bios + bios_ptr, _binary_vesabios_pm_o_bin_start, i); + MEMCPY_2DOS(dos_vga_bios + bios_ptr, vgaemu_bios_pm_interface, i); bios_ptr += i; bios_ptr = (bios_ptr + 3) & ~3; @@ -256,7 +253,7 @@ void vbe_init(vgaemu_display_type *vedt) * DANG_END_FUNCTION */ -void do_vesa_int(void) +void do_vesa_int() { int err_code = VBE_ERROR_GENERAL_FAIL; @@ -485,7 +482,7 @@ static int vbe_mode_info(unsigned mode, unsigned int vbemodeinfo) vbemi.WinASeg = vmi->buffer_start; /* segment address */ vbemi.WinBSeg = 0; /* not supported */ - vbemi.WinFuncPtr = MK_FP16(0xc000, vgaemu_bios_win_func - vgaemu_bios_start); + vbemi.WinFuncPtr = MK_FP16(0xc000, (char *) vgaemu_bios_win_func - (char *) vgaemu_bios_start); vbemi.BytesPLine = scan_len; if(vmi->mode_class == GRAPH) { @@ -571,7 +568,7 @@ static int vbe_mode_info(unsigned mode, unsigned int vbemodeinfo) vbemi.DirectColor = 0; if(vmi->color_bits >= 8 && vga.mem.lfb_base_page) - vbemi.PhysBasePtr = VGAEMU_PHYS_LFB_BASE; /* LFB support */ + vbemi.PhysBasePtr = (uintptr_t)vga.mem.lfb_base; /* LFB support */ vbemi.OffScreenOfs = 0; vbemi.OffScreenMem = 0; @@ -635,7 +632,7 @@ static int vbe_set_mode(unsigned mode) * */ -static int vbe_get_mode(void) +static int vbe_get_mode() { #ifdef DEBUG_VBE v_printf("VBE: [0x%02x] vbe_get_mode\n", (unsigned) _AL); diff --git a/src/base/dev/vga/vesabios.S b/src/base/dev/vga/vesabios.S index 8e13bfb..83f102b 100644 --- a/src/base/dev/vga/vesabios.S +++ b/src/base/dev/vga/vesabios.S @@ -64,8 +64,8 @@ .code16 .text - .globl _start -_start: + .globl _start16 +_start16: .globl vgaemu_bios_start .globl vgaemu_bios_prod_name diff --git a/src/base/dev/vga/vesabios_offsets.h b/src/base/dev/vga/vesabios_offsets.h deleted file mode 100644 index 37c9dce..0000000 --- a/src/base/dev/vga/vesabios_offsets.h +++ /dev/null @@ -1,4 +0,0 @@ -extern const unsigned vgaemu_bios_start; -extern const unsigned vgaemu_bios_prod_name; -extern const unsigned vgaemu_bios_win_func; -extern const unsigned vgaemu_bios_end; diff --git a/src/base/dev/vga/vesabios_pm.S b/src/base/dev/vga/vesabios_pm.S index 7bc24eb..f3157dd 100644 --- a/src/base/dev/vga/vesabios_pm.S +++ b/src/base/dev/vga/vesabios_pm.S @@ -30,8 +30,6 @@ .code32 - .global _start -_start: // dummy /* * We simply call our own BIOS via int 0x10, ax = 0x4fxx but use diff --git a/src/base/dev/vga/vesabios_pm_offsets.h b/src/base/dev/vga/vesabios_pm_offsets.h deleted file mode 100644 index 3ff2b4d..0000000 --- a/src/base/dev/vga/vesabios_pm_offsets.h +++ /dev/null @@ -1,2 +0,0 @@ -extern const unsigned vgaemu_bios_pm_interface; -extern const unsigned vgaemu_bios_pm_interface_end; diff --git a/src/base/dev/vga/vgaemu.c b/src/base/dev/vga/vgaemu.c index ab66299..b5bd2d3 100644 --- a/src/base/dev/vga/vgaemu.c +++ b/src/base/dev/vga/vgaemu.c @@ -260,9 +260,7 @@ #include #include #include -#include #include "cpu.h" /* root@sjoerd: for context structure */ -#include "init.h" #include "emu.h" #include "int.h" #include "emudpmi.h" @@ -277,8 +275,6 @@ #include "utilities.h" #include "instremu.h" #include "cpu-emu.h" -#include "kvm.h" -#include "smalloc.h" /* table with video mode definitions */ #include "vgaemu_modelist.h" @@ -304,11 +300,10 @@ static void print_prot_map(void); #endif static int vga_emu_setup_mode(vga_mode_info *, int, unsigned, unsigned, unsigned); static void vga_emu_setup_mode_table(void); -static void vgaemu_adjust_instremu(int value); static Bit32u rasterop(Bit32u value); static pthread_mutex_t prot_mtx = PTHREAD_MUTEX_INITIALIZER; -static pthread_rwlock_t mode_mtx = PTHREAD_RWLOCK_INITIALIZER; +static pthread_mutex_t mode_mtx = PTHREAD_MUTEX_INITIALIZER; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* @@ -339,7 +334,7 @@ vgaemu_bios_type vgaemu_bios; * */ -int VGA_emulate_outb(ioport_t port, Bit8u value, void *arg) +int VGA_emulate_outb(ioport_t port, Bit8u value) { vga_deb2_io("VGA_emulate_outb: port[0x%03x] = 0x%02x\n", (unsigned) port, (unsigned) value); @@ -369,9 +364,9 @@ int VGA_emulate_outb(ioport_t port, Bit8u value, void *arg) break; case SEQUENCER_DATA: /* 0x3c5 */ - pthread_rwlock_wrlock(&mode_mtx); + pthread_mutex_lock(&mode_mtx); Seq_write_value(value); - pthread_rwlock_unlock(&mode_mtx); + pthread_mutex_unlock(&mode_mtx); break; case DAC_PEL_MASK: /* 0x3c6 */ @@ -415,9 +410,9 @@ int VGA_emulate_outb(ioport_t port, Bit8u value, void *arg) break; case CRTC_DATA: /* 0x3d5 */ - pthread_rwlock_wrlock(&mode_mtx); + pthread_mutex_lock(&mode_mtx); if(!vga.config.mono_port) CRTC_write_value(value); - pthread_rwlock_unlock(&mode_mtx); + pthread_mutex_unlock(&mode_mtx); break; case COLOR_SELECT: /* 0x3d9 */ @@ -433,25 +428,21 @@ int VGA_emulate_outb(ioport_t port, Bit8u value, void *arg) "VGA_emulate_outb: write access not emulated (port[0x%03x] = 0x%02x)\n", (unsigned) port, (unsigned) value ); - return -1; + return 0; } - return 0; + return 1; #if DEBUG_MAP >= 3 print_prot_map(); #endif } -static void VGA_emulate_outb_handler(ioport_t port, Bit8u value, void *arg) +int VGA_emulate_outw(ioport_t port, Bit16u value) { - VGA_emulate_outb(port, value, arg); + if (VGA_emulate_outb(port,value)==0) return 0; + return VGA_emulate_outb(port+1,value>>8); } -static void VGA_emulate_outw_handler(ioport_t port, Bit16u value, void *arg) -{ - VGA_emulate_outb_handler(port, value, arg); - VGA_emulate_outb_handler(port+1, value>>8, arg); -} /* * DANG_BEGIN_FUNCTION VGA_emulate_inb @@ -467,7 +458,7 @@ static void VGA_emulate_outw_handler(ioport_t port, Bit16u value, void *arg) * */ -int VGA_emulate_inb(ioport_t port, void *arg) +Bit8u VGA_emulate_inb(ioport_t port) { Bit8u uc = 0xff; @@ -557,7 +548,7 @@ int VGA_emulate_inb(ioport_t port, void *arg) "VGA_emulate_inb: read access not emulated (port[0x%03x] = 0x%02x)\n", (unsigned) port, (unsigned) uc ); - return -1; + break; } vga_deb2_io("VGA_emulate_inb: port[0x%03x] = 0x%02x\n", (unsigned) port, (unsigned) uc); @@ -565,15 +556,10 @@ int VGA_emulate_inb(ioport_t port, void *arg) return uc; } -static Bit8u VGA_emulate_inb_handler(ioport_t port, void *arg) +Bit16u VGA_emulate_inw(ioport_t port) { - return VGA_emulate_inb(port, arg); -} - -static Bit16u VGA_emulate_inw_handler(ioport_t port, void *arg) -{ - Bit16u v = VGA_emulate_inb_handler(port, arg); - return v | (VGA_emulate_inb_handler(port+1, arg)<<8); + Bit16u v = VGA_emulate_inb(port); + return v | (VGA_emulate_inb(port+1)<<8); } @@ -609,7 +595,6 @@ static Bit32u color2pixels[16] = {0,0xff,0xff00,0xffff,0xff0000,0xff00ff,0xffff0 static unsigned char Logical_VGA_read(unsigned offset) { - instr_emu_sim_reset_count(VGA_EMU_INST_EMU_COUNT); switch (ReadMode) { case 0: /* read mode 0 */ @@ -731,8 +716,6 @@ static void Logical_VGA_write(unsigned offset, unsigned char value) unsigned char *p; Bit32u new_val; - instr_emu_sim_reset_count(VGA_EMU_INST_EMU_COUNT); - new_val = Logical_VGA_CalcNewVal(value); vga_page = offset >> 12; @@ -767,23 +750,17 @@ static void Logical_VGA_write(unsigned offset, unsigned char value) int vga_bank_access(dosaddr_t m) { - if (config.console_video) - return 0; return (unsigned)(m - vga.mem.bank_base) < vga.mem.bank_len; } int vga_read_access(dosaddr_t m) { - if (config.console_video) - return 0; /* Using a planar mode */ return vga_bank_access(m); } int vga_write_access(dosaddr_t m) { - if (config.console_video) - return 0; /* unmapped VGA memory, VGA BIOS, or a bank. Note that * the bank can be write-protected even in non-planar mode. */ if (m >= vga.mem.graph_base && @@ -802,8 +779,6 @@ int vga_write_access(dosaddr_t m) int vga_access(dosaddr_t r, dosaddr_t w) { - if (config.console_video) - return 0; return (vga_read_access(r) | (vga_write_access(w) << 1)); } @@ -825,7 +800,7 @@ unsigned vga_read_dword(dosaddr_t addr) { if (!vga.inst_emu) return READ_DWORD(addr); - return vga_read_word(addr) | (unsigned)vga_read_word(addr + 2) << 16; + return vga_read_word(addr) | vga_read_word(addr + 2) << 16; } static dosaddr_t vga_get_mem_base_offset(dosaddr_t addr) @@ -1043,7 +1018,7 @@ void vga_memsetl(dosaddr_t dst, unsigned val, size_t len) * */ -int vga_emu_fault(dosaddr_t lin_addr, unsigned err, cpuctx_t *scp) +int vga_emu_fault(dosaddr_t lin_addr, unsigned err, sigcontext_t *scp) { int i, j, pmode = scp != NULL; unsigned page_fault, vga_page = 0, u; @@ -1118,7 +1093,8 @@ int vga_emu_fault(dosaddr_t lin_addr, unsigned err, cpuctx_t *scp) } return True; } - else if(memcheck_is_rom(page_fault << PAGE_SHIFT)) { /* ROM area */ + else if((page_fault >= 0xc0 && page_fault < (0xc0 + vgaemu_bios.pages)) || + (!config.umb_f0 && page_fault >= 0xf0 && page_fault < 0xf4)) { /* ROM area */ if (pmode) { u = instr_len((unsigned char *)SEL_ADR(_cs, _eip), dpmi_segment_is32(_cs)); @@ -1168,7 +1144,7 @@ int vga_emu_fault(dosaddr_t lin_addr, unsigned err, cpuctx_t *scp) * while we are using X. Leave the display page read/write-protected * so that each instruction that accesses it can be trapped and * simulated. */ - ret = instr_emu_sim(scp, pmode, VGA_EMU_INST_EMU_COUNT); + ret = instr_emu(scp, pmode, 0); if (!ret) { if (pmode) error_once("instruction simulation failure\n%s\n", DPMI_show_state(scp)); @@ -1228,10 +1204,6 @@ int vga_emu_protect_page(unsigned page, int prot) int i; int sys_prot; - /* don't call mprotect at all on LFB with KVM */ - if (config.cpu_vm_dpmi == CPUVM_KVM && page >= vga.mem.lfb_base_page) - return 0; - sys_prot = prot == RW ? VGA_EMU_RW_PROT : prot == RO ? VGA_EMU_RO_PROT : VGA_EMU_NONE_PROT; if(vgaemu_prot_ok(page, sys_prot)) { @@ -1252,9 +1224,9 @@ int vga_emu_protect_page(unsigned page, int prot) vga.mem.lfb_base_page && page >= vga.mem.lfb_base_page && page < vga.mem.lfb_base_page + vga.mem.pages) { - dosaddr_t p; - p = vga.mem.lfb_base + ((page - vga.mem.lfb_base_page) << 12); - i = mprotect_mapping(MAPPING_VGAEMU, p, 1 << 12, sys_prot); + unsigned char *p; + p = &vga.mem.lfb_base[(page - vga.mem.lfb_base_page) << 12]; + i = mprotect_mapping(MAPPING_VGAEMU, DOSADDR_REL(p), 1 << 12, sys_prot); } else { i = mprotect_mapping(MAPPING_VGAEMU | MAPPING_LOWMEM, page << 12, 1 << 12, sys_prot); @@ -1421,32 +1393,6 @@ int vga_emu_adjust_protection(unsigned page, unsigned mapped_page, int prot, return ret; } -static void _vga_kvm_sync_dirty_map(unsigned mapping) -{ - unsigned i; - dosaddr_t base; - - if (config.cpu_vm_dpmi != CPUVM_KVM) { - if (config.cpu_vm != CPUVM_KVM) - return; - if (mapping == VGAEMU_MAP_LFB_MODE) - return; - } - - if (vga.inst_emu) - return; - - base = mapping == VGAEMU_MAP_LFB_MODE ? VGAEMU_PHYS_LFB_BASE : - vga.mem.map[mapping].base_page << PAGE_SHIFT; - if (base == 0) - return; - - kvm_get_dirty_map(base, vga.mem.dirty_bitmap); - for (i = 0; i < vga.mem.map[mapping].pages; i++) - if (test_bit(i, vga.mem.dirty_bitmap)) - _vgaemu_dirty_page(vga.mem.map[mapping].first_page + i, 1); -} - /* * Map the VGA memory. * @@ -1485,13 +1431,11 @@ static int vga_emu_map(unsigned mapping, unsigned first_page) i = 0; pthread_mutex_lock(&prot_mtx); - _vga_kvm_sync_dirty_map(mapping); if (mapping == VGAEMU_MAP_BANK_MODE) i = alias_mapping(MAPPING_VGAEMU, vmt->base_page << 12, vmt->pages << 12, prot, vga.mem.base + (first_page << 12)); - else if (config.cpu_vm_dpmi != CPUVM_KVM) - /* LFB: mapped at init, just need to set protection */ + else /* LFB: mapped at init, just need to set protection */ i = mprotect_mapping(MAPPING_VGAEMU, vmt->base_page << 12, vmt->pages << 12, prot); @@ -1545,14 +1489,16 @@ static int vgaemu_unmap(unsigned page) /* * Put the vga memory mapping into a defined state. */ -void vgaemu_reset_mapping(void) +void vgaemu_reset_mapping() { int i; int prot, page, startpage, endpage; prot = VGA_EMU_RW_PROT; - startpage = vga.mem.graph_base >> PAGE_SHIFT; - endpage = startpage + (vga.mem.graph_size >> PAGE_SHIFT); + startpage = (config.umb_a0 ? 0xb0 : 0xa0); + endpage = (config.umb_b0 ? 0xb0 : 0xb8); + vga.mem.graph_base = startpage << 12; + vga.mem.graph_size = (endpage << 12) - vga.mem.graph_base; for(page = startpage; page < endpage; page++) { i = alias_mapping(MAPPING_VGAEMU, page << 12, 1 << 12, @@ -1582,12 +1528,14 @@ static void vgaemu_register_ports(void) emu_iodev_t io_device; /* register VGA ports */ - io_device.read_portb = VGA_emulate_inb_handler; - io_device.write_portb = VGA_emulate_outb_handler; - io_device.read_portw = VGA_emulate_inw_handler; - io_device.write_portw = VGA_emulate_outw_handler; + io_device.read_portb = VGA_emulate_inb; + io_device.write_portb = (void (*)(ioport_t, Bit8u)) VGA_emulate_outb; + io_device.read_portw = VGA_emulate_inw; + io_device.write_portw = (void (*)(ioport_t, Bit16u)) VGA_emulate_outw; io_device.read_portd = NULL; io_device.write_portd = NULL; + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; /* register VGAEmu */ io_device.handler_name = "VGAEmu VGA Controller"; @@ -1673,11 +1621,6 @@ int vga_emu_pre_init(void) int i; vga_mapping_type vmt = {0, 0, 0}; - if (config.dumb_video) { - vgaemu_register_ports(); - return 0; - } - /* clean it up - just in case */ memset(&vga, 0, sizeof vga); @@ -1693,7 +1636,10 @@ int vga_emu_pre_init(void) open_mapping(MAPPING_VGAEMU); - vga.mem.size = config.vgaemu_memsize << 10; + if(config.vgaemu_memsize) + vga.mem.size = config.vgaemu_memsize << 10; + else + vga.mem.size = 1024 << 10; /* force 256k granularity to prevent possible problems * (with 4-plane-modes, to be precise) @@ -1701,21 +1647,36 @@ int vga_emu_pre_init(void) vga.mem.size = (vga.mem.size + ((1 << 18) - 1)) & ~((1 << 18) - 1); vga.mem.pages = vga.mem.size >> 12; - vga.mem.base = alloc_mapping_huge_page_aligned(MAPPING_VGAEMU, vga.mem.size); + vga.mem.base = alloc_mapping(MAPPING_VGAEMU, vga.mem.size + PAGE_SIZE); if(vga.mem.base == MAP_FAILED) { - error("vga_emu_init: not enough memory (%u k)\n", vga.mem.size >> 10); + vga_msg("vga_emu_init: not enough memory (%u k)\n", vga.mem.size >> 10); config.exitearly = 1; return 1; } + /* create guard page to trap bad things */ + mprotect(vga.mem.base, PAGE_SIZE, PROT_NONE); + vga.mem.base += PAGE_SIZE; + + vga.mem.lfb_base = NULL; + if(config.X_lfb) { + unsigned char *p = alias_mapping_high(MAPPING_VGAEMU, + vga.mem.size, VGA_EMU_RW_PROT, vga.mem.base); + if(p == MAP_FAILED) { + vga_msg("vga_emu_init: not enough memory (%u k)\n", vga.mem.size >> 10); + config.exitearly = 1; + return 1; + } else { + vga.mem.lfb_base = p; + } + } + + if(vga.mem.lfb_base == NULL) { + vga_msg("vga_emu_init: linear frame buffer (lfb) disabled\n"); + } /* alloc more pages because vgaemu_dirty_page() does weird things */ if((vga.mem.dirty_map = (unsigned char *) malloc(vga.mem.pages | 0xff)) == NULL) { - error("vga_emu_init: not enough memory for dirty map\n"); - config.exitearly = 1; - return 1; - } - if((vga.mem.dirty_bitmap = (unsigned char *) malloc((vga.mem.pages+CHAR_BIT-1) / CHAR_BIT)) == NULL) { - error("vga_emu_init: not enough memory for dirty bit map\n"); + vga_msg("vga_emu_init: not enough memory for dirty map\n"); config.exitearly = 1; return 1; } @@ -1725,7 +1686,7 @@ int vga_emu_pre_init(void) (vga.mem.prot_map0 = malloc(vgaemu_bios.pages + 0xc0 - 0xa0)) == NULL || (vga.mem.prot_map1 = (unsigned char *) malloc(vga.mem.pages)) == NULL ) { - error("vga_emu_init: not enough memory for protection map\n"); + vga_msg("vga_emu_init: not enough memory for protection map\n"); config.exitearly = 1; return 1; } @@ -1742,44 +1703,9 @@ int vga_emu_pre_init(void) vga.mem.bank = vga.mem.bank_pages = 0; - vga.mem.graph_base = config.umb_a0 ? GRAPH_BASE + GRAPH_SIZE : GRAPH_BASE; - vga.mem.graph_size = (config.umb_b0 ? GRAPH_BASE + GRAPH_SIZE : - VGA_PHYS_TEXT_BASE) - vga.mem.graph_base; - - if (config.cpu_vm == CPUVM_KVM || config.cpu_vm_dpmi == CPUVM_KVM) { - if (vga.mem.graph_base + vga.mem.graph_size == VGA_PHYS_TEXT_BASE) { - /* contiguous */ - kvm_set_dirty_log(vga.mem.graph_base, vga.mem.graph_size + VGA_TEXT_SIZE); - } else { - if (vga.mem.graph_size) - kvm_set_dirty_log(vga.mem.graph_base, vga.mem.graph_size); - kvm_set_dirty_log(VGA_PHYS_TEXT_BASE, VGA_TEXT_SIZE); - } - } - - vga.mem.lfb_base = 0; - if (config.X_lfb && config.dpmi) { - void *addr = smalloc_aligned_topdown(&main_pool, NULL, PAGE_SIZE, vga.mem.size); - if (addr) { - vga.mem.lfb_base = DOSADDR_REL(addr); - memcheck_addtype('e', "VGAEMU LFB"); - register_hardware_ram_virtual2('e', VGAEMU_PHYS_LFB_BASE, vga.mem.size, - vga.mem.base, vga.mem.lfb_base); - if (!alias_mapping_pa(MAPPING_VGAEMU, VGAEMU_PHYS_LFB_BASE, - vga.mem.size, VGA_EMU_RW_PROT, vga.mem.base)) - addr = NULL; - } - if (addr && config.cpu_vm_dpmi == CPUVM_KVM) - kvm_set_dirty_log(VGAEMU_PHYS_LFB_BASE, vga.mem.size); - if(addr == NULL || addr == MAP_FAILED) { - error("vga_emu_init: not enough memory (%u k)\n", vga.mem.size >> 10); - config.exitearly = 1; - return 1; - } - } - - if(vga.mem.lfb_base == 0) { - vga_msg("vga_emu_init: linear frame buffer (lfb) disabled\n"); + if(vga.mem.lfb_base != NULL) { + memcheck_addtype('e', "VGAEMU LFB"); + register_hardware_ram('e', (uintptr_t)vga.mem.lfb_base, vga.mem.size); } return vga_emu_post_init(); @@ -1787,11 +1713,23 @@ int vga_emu_pre_init(void) static int vga_emu_post_init(void) { - if(vga.mem.lfb_base != 0) { - vga.mem.lfb_base_page = vga.mem.lfb_base >> 12; + int i; + + if(vga.mem.lfb_base != NULL) { + dosaddr_t lfb_base = DOSADDR_REL(vga.mem.lfb_base); + vga.mem.lfb_base_page = lfb_base >> 12; + map_hardware_ram_manual((uintptr_t)vga.mem.lfb_base, lfb_base); } vga_emu_setup_mode_table(); + /* + * Make the VGA-BIOS ROM read-only; some dirty programs try to write to the ROM! + * + * Note: Unknown instructions will cause the write protection to be removed. + */ + vga_msg("vga_emu_init: protecting ROM area 0xc0000 - 0x%05x\n", (0xc0 + vgaemu_bios.pages) << 12); + for(i = 0; i < vgaemu_bios.pages; i++) vga_emu_protect_page(0xc0 + i, RO); + vgaemu_register_ports(); SETIVEC(0x42, INT42HOOK_SEG, INT42HOOK_OFF); @@ -1808,13 +1746,9 @@ static int vga_emu_post_init(void) } -void vga_emu_done(void) +void vga_emu_done() { - if (vga.mem.lfb_base) { - unalias_mapping_pa(MAPPING_DPMI, VGAEMU_PHYS_LFB_BASE, vga.mem.size); - smfree(&main_pool, MEM_BASE32(vga.mem.lfb_base)); - vga.mem.lfb_base = 0; - } + /* We should probably do something here - but what ? -- sw */ } @@ -2002,12 +1936,12 @@ int vga_emu_update(vga_emu_update_type *veut, unsigned display_start, void vga_emu_update_lock(void) { - pthread_rwlock_rdlock(&mode_mtx); + pthread_mutex_lock(&mode_mtx); } void vga_emu_update_unlock(void) { - pthread_rwlock_unlock(&mode_mtx); + pthread_mutex_unlock(&mode_mtx); } void vga_emu_prot_lock(void) @@ -2161,7 +2095,7 @@ int vga_emu_setup_mode(vga_mode_info *vmi, int mode_index, unsigned width, unsig * */ -static void vga_emu_setup_mode_table(void) +static void vga_emu_setup_mode_table() { int vbe_modes = (sizeof vga_mode_table) / (sizeof *vga_mode_table); int vbe_num = VBE_FIRST_OEM_MODE; @@ -2296,11 +2230,7 @@ static void vga_emu_setup_mode_table(void) vga_mode_info *vga_emu_find_mode(int mode, vga_mode_info* vmi) { - vga_mode_info *vmi_end; - - if (!vgaemu_bios.vga_mode_table) - return NULL; - vmi_end = vgaemu_bios.vga_mode_table + vgaemu_bios.mode_table_length; + vga_mode_info *vmi_end = vgaemu_bios.vga_mode_table + vgaemu_bios.mode_table_length; if(mode != -1) { mode &= 0x3fff; @@ -2413,8 +2343,7 @@ static int __vga_emu_setmode(int mode, int width, int height) vga.pixel_size = (vga.pixel_size + 7) & ~7; /* assume byte alignment for these modes */ vga.scan_len *= vga.pixel_size >> 3; } - vgaemu_adjust_instremu((vga.mode_type==PL4 || vga.mode_type==PL2) - ? EMU_ALL_INST : 0); + vga.inst_emu = ((vga.mode_type==PL4 || vga.mode_type==PL2) ? EMU_ALL_INST : 0); vga_msg("vga_emu_setmode: scan_len = %d\n", vga.scan_len); i = vga.scan_len; @@ -2534,9 +2463,6 @@ static int _is_dirty(void) { int i, ret = 0; - for(i = 0; i < VGAEMU_MAX_MAPPINGS; i++) - _vga_kvm_sync_dirty_map(i); - if (vga.mem.dirty_map) { for (i = 0; i < vga.mem.pages; i++) { if (vga.mem.dirty_map[i]) { @@ -2551,14 +2477,14 @@ static int _is_dirty(void) int vga_emu_setmode(int mode, int width, int height) { int ret; - pthread_rwlock_wrlock(&mode_mtx); + pthread_mutex_lock(&mode_mtx); ret = __vga_emu_setmode(mode, width, height); - pthread_rwlock_unlock(&mode_mtx); + pthread_mutex_unlock(&mode_mtx); // render_update_vidmode(); return ret; } -int vgaemu_map_bank(void) +int vgaemu_map_bank() { int i, first; #if 0 @@ -2667,7 +2593,7 @@ int vga_emu_set_textsize(int width, int height) * */ -void dirty_all_video_pages(void) +void dirty_all_video_pages() { pthread_mutex_lock(&prot_mtx); if (vga.mem.dirty_map) @@ -2751,7 +2677,7 @@ int vgaemu_is_dirty(void) * */ -void dirty_all_vga_colors(void) +void dirty_all_vga_colors() { int i; @@ -2867,30 +2793,28 @@ int changed_vga_colors(void (*upd_func)(DAC_entry *, int, void *), void *arg) return j; } -static void vgaemu_adjust_instremu(int value) +static void vgaemu_adjust_instremu(void) { int i; - vga_mapping_type *vmt = &vga.mem.map[VGAEMU_MAP_BANK_MODE]; - if (value == EMU_ALL_INST) { + if (vga.mem.planes > 1) { if (vga.inst_emu != EMU_ALL_INST) { v_printf("Seq_write_value: instemu on\n"); pthread_mutex_lock(&prot_mtx); - for (i = 0; i < vga.mem.pages; i++) - _vga_emu_adjust_protection(i, 0, NONE, 1); + for (i = 0; i < vga.mem.pages; i++) { + if (vga.mem.dirty_map[i]) + _vga_emu_adjust_protection(i, 0, NONE, 1); + } pthread_mutex_unlock(&prot_mtx); + vga.inst_emu = EMU_ALL_INST; } } else { if (vga.inst_emu != 0) { v_printf("Seq_write_value: instemu off\n"); dirty_all_video_pages(); + vga.inst_emu = 0; } } - if (vga.inst_emu != value && - (config.cpu_vm == CPUVM_KVM || config.cpu_vm_dpmi == CPUVM_KVM)) - kvm_set_mmio(vmt->base_page << PAGE_SHIFT, vmt->pages << PAGE_SHIFT, - value != 0); - vga.inst_emu = value; } /* @@ -2922,7 +2846,7 @@ void vgaemu_adj_cfg(unsigned what, unsigned msg) vga_msg("vgaemu_adj_cfg: mem reconfig (%u planes)\n", u1); vgaemu_map_bank(); // update page protection } - vgaemu_adjust_instremu(vga.mem.planes > 1 ? EMU_ALL_INST : 0); + vgaemu_adjust_instremu(); if(msg || u != u0) vga_msg("vgaemu_adj_cfg: seq.addr_mode = %s\n", txt1[u]); if (vga.mode_class == TEXT && vga.width < 2048) { int horizontal_display_end = vga.crtc.data[0x1] + 1; @@ -3146,9 +3070,9 @@ void vgaemu_adj_cfg(unsigned what, unsigned msg) } old_color_bits = vga.color_bits; vga.color_bits = vga.pixel_size; + vga.inst_emu = (vga.mode_type==PL4 || vga.mode_type==PL2) + ? EMU_ALL_INST : 0; vgaemu_map_bank(); // update page protection - vgaemu_adjust_instremu((vga.mode_type==PL4 || vga.mode_type==PL2) - ? EMU_ALL_INST : 0); if (oldclass != vga.mode_class) { vgaemu_adj_cfg(CFG_SEQ_ADDR_MODE, 0); vgaemu_adj_cfg(CFG_CRTC_WIDTH, 0); @@ -3165,16 +3089,3 @@ void vgaemu_adj_cfg(unsigned what, unsigned msg) vga_msg("vgaemu_adj_cfg: unknown item %u\n", what); } } - -static void vgaemu_config_scrub(void) -{ - if (config.vgaemu_memsize < 1024) { - error("VGA mem size must be at least 1024k\n"); - config.vgaemu_memsize = 1024; - } -} - -CONSTRUCTOR(static void init(void)) -{ - register_config_scrub(vgaemu_config_scrub); -} diff --git a/src/base/dev/vga/vgaemu_modelist.h b/src/base/dev/vga/vgaemu_modelist.h index abc1944..27ea4e6 100644 --- a/src/base/dev/vga/vgaemu_modelist.h +++ b/src/base/dev/vga/vgaemu_modelist.h @@ -32,13 +32,9 @@ static vga_mode_info vga_mode_table[] = { {0x01, -1, TEXT, TEXT, 4, VGA_MODE_WH( 40, 25, 9, 16)}, {0x02, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 25, 9, 16)}, {0x03, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 25, 9, 16)}, - {0x03, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 25, 8, 16)}, - {0x03, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 25, 8, 14)}, - {0x03, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 25, 8, 8)}, {0x03, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 21, 9, 16)}, {0x03, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 28, 9, 16)}, {0x03, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 43, 8, 14)}, - {0x03, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 43, 8, 8)}, {0x03, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 50, 8, 8)}, {0x03, -1, TEXT, TEXT, 4, VGA_MODE_WH( 80, 60, 8, 8)}, {0x04, -1, GRAPH, CGA, 2, VGA_MODE_WH( 40, 25, 8, 8)}, diff --git a/src/base/dev/vga/vgafonts.c b/src/base/dev/vga/vgafonts.c index 0bec339..9663b20 100644 --- a/src/base/dev/vga/vgafonts.c +++ b/src/base/dev/vga/vgafonts.c @@ -4,7 +4,7 @@ * * See COPYING.DOSEMU for the copyright notice. */ -#include "vgaemu.h" + unsigned char vga_rom_08[256 * 8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, diff --git a/src/base/emu-i386/Makefile b/src/base/emu-i386/Makefile index 3d70849..6d53ed3 100644 --- a/src/base/emu-i386/Makefile +++ b/src/base/emu-i386/Makefile @@ -1,11 +1,10 @@ top_builddir=../../.. include $(top_builddir)/Makefile.conf -CFILES = cpu.c do_vm86.c cputime.c coopth_vm86.c -ifeq ($(KVM),1) -CFILES += kvm.c -SFILES = kvmmon.S -endif +CFILES=cpu.c do_vm86.c cputime.c kvm.c coopth_vm86.c + + +SFILES=kvmmon.S include $(REALTOPDIR)/src/Makefile.common diff --git a/src/base/emu-i386/coopth_vm86.c b/src/base/emu-i386/coopth_vm86.c index 5078328..2e6b46d 100644 --- a/src/base/emu-i386/coopth_vm86.c +++ b/src/base/emu-i386/coopth_vm86.c @@ -25,12 +25,10 @@ #include "hlt.h" #include "utilities.h" #include "timers.h" -#include "dos2linux.h" #include "coopth.h" #include "coopth_be.h" struct co_vm86 { - struct vm86_regs *regs; Bit16u hlt_off; void (*post)(void); }; @@ -40,56 +38,46 @@ struct co_vm86 { struct co_vm86_pth { Bit16u hlt_off; Bit16u ret_cs, ret_ip; - Bit16u owner; uint64_t dbg; - unsigned prepped:1; }; static struct co_vm86 coopth86[MAX_COOPTHREADS]; static struct co_vm86_pth coopth86_pth[COOPTH_POOL_SIZE]; -static __TLS int (*ctx_is_valid)(void); +static int (*ctx_is_valid)(void); static int do_start_custom(int tid); static int is_active(int tid, int idx) { - struct vm86_regs *regs = coopth86[tid].regs; - - return (regs->cs == BIOS_HLT_BLK_SEG && - LO_WORD(regs->eip) == coopth86_pth[idx].hlt_off); + return (SREG(cs) == BIOS_HLT_BLK_SEG && + LWORD(eip) == coopth86_pth[idx].hlt_off); } static void do_callf(int tid, int idx) { - struct vm86_regs *regs = coopth86[tid].regs; - if (ctx_is_valid) { int ok = ctx_is_valid(); if (!ok) dosemu_error("coopth: unsafe context switch\n"); } - coopth86_pth[idx].ret_cs = regs->cs; - coopth86_pth[idx].ret_ip = LO_WORD(regs->eip); - regs->cs = BIOS_HLT_BLK_SEG; + coopth86_pth[idx].ret_cs = SREG(cs); + coopth86_pth[idx].ret_ip = LWORD(eip); + SREG(cs) = BIOS_HLT_BLK_SEG; assert(coopth86[tid].hlt_off != INVALID_HLT); - LO_WORD(regs->eip) = coopth86[tid].hlt_off; + LWORD(eip) = coopth86[tid].hlt_off; } static void do_retf(int tid, int idx) { - struct vm86_regs *regs = coopth86[tid].regs; - - regs->cs = coopth86_pth[idx].ret_cs; - LO_WORD(regs->eip) = coopth86_pth[idx].ret_ip; + SREG(cs) = coopth86_pth[idx].ret_cs; + LWORD(eip) = coopth86_pth[idx].ret_ip; coopth86_pth[idx].hlt_off = INVALID_HLT; } -static int to_sleep(int tid) +static int to_sleep(void) { - struct vm86_regs *regs = coopth86[tid].regs; - - if (!(regs->eflags & VIF)) { + if (!isset_IF()) { dosemu_error("sleep with interrupts disabled\n"); return 0; } @@ -104,7 +92,6 @@ static void do_sleep(void) static void do_prep(int tid, int idx) { coopth86_pth[idx].hlt_off = INVALID_HLT; - coopth86_pth[idx].prepped = 1; } static uint64_t get_dbg_val(int tid, int idx) @@ -135,13 +122,12 @@ static void coopth_hlt(Bit16u offs, HLT_ARG(arg)) static void coopth_auto_hlt(Bit16u offs, HLT_ARG(arg)) { struct co_vm86 *thr = arg; - struct vm86_regs *regs = thr->regs; int tid = thr - coopth86; assert(tid >= 0 && tid < MAX_COOPTHREADS); switch (offs) { case 0: - LO_WORD(regs->eip)++; // skip hlt + LWORD(eip)++; // skip hlt do_start_custom(tid); break; case 1: { @@ -177,7 +163,6 @@ int coopth_create(const char *name, coopth_func_t func) return -1; thr = &coopth86[num]; thr->hlt_off = register_handler(name, coopth_hlt, thr, 1); - thr->regs = ®S; return num; } @@ -194,7 +179,6 @@ int coopth_create_multi(const char *name, int len, coopth_func_t func) for (i = 0; i < len; i++) { thr = &coopth86[num + i]; thr->hlt_off = hlt_off + i; - thr->regs = ®S; } return num; } @@ -213,7 +197,6 @@ int coopth_create_vm86(const char *name, coopth_func_t func, ret = register_handler(name, coopth_auto_hlt, thr, 2); thr->hlt_off = ret; // for some future unregister thr->post = post; - thr->regs = ®S; *hlt_off = ret; return num; } @@ -221,15 +204,13 @@ int coopth_create_vm86(const char *name, coopth_func_t func, int coopth_start(int tid, void *arg) { struct cstart_ret ret = coopth_start_internal(tid, arg, do_retf); - struct vm86_regs *regs = coopth86[tid].regs; - uint64_t dbg = ((uint64_t)regs->eax << 32) | regs->ebx; + uint64_t dbg = ((uint64_t)REG(eax) << 32) | REG(ebx); if (ret.idx == -1) return -1; if (!ret.detached) { assert(coopth86[tid].hlt_off != INVALID_HLT); coopth86_pth[ret.idx].hlt_off = coopth86[tid].hlt_off; - coopth86_pth[ret.idx].owner = sda_cur_psp(sda); coopth86_pth[ret.idx].dbg = dbg; do_callf(tid, ret.idx); } @@ -239,15 +220,13 @@ int coopth_start(int tid, void *arg) static int do_start_custom(int tid) { int idx = coopth_start_custom_internal(tid, NULL); - struct vm86_regs *regs = coopth86[tid].regs; - uint64_t dbg = ((uint64_t)regs->eax << 32) | regs->ebx; + uint64_t dbg = ((uint64_t)REG(eax) << 32) | REG(ebx); if (idx == -1) return -1; - assert(regs->cs == BIOS_HLT_BLK_SEG); + assert(SREG(cs) == BIOS_HLT_BLK_SEG); assert(coopth86_pth[idx].hlt_off == INVALID_HLT); - coopth86_pth[idx].hlt_off = LO_WORD(regs->eip); - coopth86_pth[idx].owner = sda_cur_psp(sda); + coopth86_pth[idx].hlt_off = LWORD(eip); coopth86_pth[idx].dbg = dbg; return 0; } @@ -271,24 +250,3 @@ void coopth_set_ctx_checker_vm86(int (*checker)(void)) { ctx_is_valid = checker; } - -int coopth_get_thread_count_in_process_vm86(void) -{ - int i; - int cnt = 0; - for (i = 0; i < COOPTH_POOL_SIZE; i++) { - if (!coopth86_pth[i].prepped || coopth86_pth[i].hlt_off == INVALID_HLT) - continue; - if (coopth86_pth[i].owner == sda_cur_psp(sda)) - cnt++; - } - return cnt; -} - -void coopth_leave_vm86(void) -{ - struct co_vm86 *thr = &coopth86[coopth_get_tid()]; - coopth_leave_internal(); - assert(thr->post); - thr->post(); -} diff --git a/src/base/emu-i386/cpu.c b/src/base/emu-i386/cpu.c index 49a1270..c569832 100644 --- a/src/base/emu-i386/cpu.c +++ b/src/base/emu-i386/cpu.c @@ -34,7 +34,6 @@ #include "int.h" #include "emudpmi.h" #include "priv.h" -#include "instremu.h" #include "kvm.h" #ifdef X86_EMULATOR @@ -94,7 +93,7 @@ static unsigned int TRs[2] = #endif /* fpu_state needs to be paragraph aligned for fxrstor/fxsave */ -emu_fpstate vm86_fpu_state __attribute__((aligned(16))); +fpregset_t vm86_fpu_state; fenv_t dosemu_fenv; static void fpu_reset(void); @@ -109,11 +108,9 @@ static void fpu_reset(void); * DANG_END_FUNCTION * */ -int cpu_trap_0f (unsigned char *csp, cpuctx_t *scp) +int cpu_trap_0f (unsigned char *csp, sigcontext_t *scp) { int increment_ip = 0; - uint16_t *reg16[8] = { &LWORD(eax), &LWORD(ecx), &LWORD(edx), &LWORD(ebx), - &LWORD(esp), &LWORD(ebp), &LWORD(esi), &LWORD(edi) }; g_printf("CPU: TRAP op 0F %02x %02x\n",csp[1],csp[2]); if (csp[1] == 0x06) { @@ -123,7 +120,18 @@ int cpu_trap_0f (unsigned char *csp, cpuctx_t *scp) else if (csp[1] == 0x31) { /* ref: Van Gilluwe, "The Undocumented PC". The program * 'cpurdtsc.exe' traps here */ - { +#ifdef X86_EMULATOR + if (EMU_V86() && config.rdtsc) { + REG(eax) = (unsigned long)TheCPU.EMUtime; + REG(edx) = (unsigned long)(TheCPU.EMUtime>>32); + } else +#endif + if (vm86s.cpu_type >= CPU_586) { + __asm__ __volatile__ ("rdtsc" \ + :"=a" (REG(eax)), \ + "=d" (REG(edx))); + } + else { struct timeval tv; unsigned long long t; @@ -188,29 +196,6 @@ int cpu_trap_0f (unsigned char *csp, cpuctx_t *scp) else cdt[idx] = *srg; } increment_ip = 3; - } else if (csp[1] == 0) { // SLDT, STR, ... - switch (csp[2] & 0xc0) { - case 0xc0: // register dest - *reg16[csp[2] & 7] = 0; - increment_ip = 3; - break; - default: - error("unsupported SLDT dest %x\n", csp[2]); - increment_ip = instr_len(csp, 0); - break; - } - } else if (csp[1] == 1) { // SGDT, SIDT, SMSW ... - switch (csp[2] & 0xc0) { - case 0xc0: // register dest - /* some meaningful value for smsw, 0 for rest */ - *reg16[csp[2] & 7] = ((csp[2] & 0x28) == 0x20) ? 0x31 : 0; - increment_ip = 3; - break; - default: - error("unsupported SMSW dest %x\n", csp[2]); - increment_ip = instr_len(csp, 0); - break; - } } if (increment_ip) { if (scp) @@ -267,27 +252,32 @@ static void fpu_init(void) static void fpu_reset(void) { - vm86_fpu_state.cwd = 0x0040; - vm86_fpu_state.swd = 0; -// vm86_fpu_state.ftw = 0x5555; //bochs - if (config.cpu_vm == CPUVM_KVM || config.cpu_vm_dpmi == CPUVM_KVM) - kvm_update_fpu(); +#ifdef __x86_64__ + vm86_fpu_state->cwd = 0x0040; + vm86_fpu_state->swd = 0; + vm86_fpu_state->ftw = 0x5555; //bochs +#else + vm86_fpu_state->cw = 0x40; + vm86_fpu_state->sw = 0; + vm86_fpu_state->tag = 0x5555; // bochs +#endif } -static Bit8u fpu_io_read(ioport_t port, void *arg) +static Bit8u fpu_io_read(ioport_t port) { return 0xff; } -static void fpu_io_write(ioport_t port, Bit8u val, void *arg) +static void fpu_io_write(ioport_t port, Bit8u val) { switch (port) { case 0xf0: - /* We need to check if the FPU exception is pending, and set IGNNE - * if it is, before untriggering an IRQ. But we don't (and probably - * can't) emulate IGNNE properly. So the trick is to do fnclex in - * bios.S, then untrigger IRQ unconditionally. */ - pic_untrigger(13); /* done by default via int75 handler in bios.S */ + /* not sure about this */ +#ifdef __x86_64__ + vm86_fpu_state->swd &= ~0x8000; +#else + vm86_fpu_state->sw &= ~0x8000; +#endif break; case 0xf1: fpu_reset(); @@ -295,23 +285,6 @@ static void fpu_io_write(ioport_t port, Bit8u val, void *arg) } } -static int fpu_is_masked(void) -{ - uint8_t imr[2] = { [0] = port_inb(0x21), [1] = port_inb(0xa1) }; - uint16_t real_imr = (imr[1] << 8) | imr[0]; - return ((imr[0] & 4) || !!(real_imr & (1 << 13))); -} - -void raise_fpu_irq(void) -{ - if (fpu_is_masked() || !isset_IF_async()) { - error("FPU IRQ cannot be injected (%i %i), bye\n", - fpu_is_masked(), isset_IF()); - leavedos(2); - } - pic_request(13); -} - /* * DANG_BEGIN_FUNCTION cpu_setup * @@ -333,12 +306,15 @@ void cpu_setup(void) io_dev.write_portw = NULL; io_dev.read_portd = NULL; io_dev.write_portd = NULL; + io_dev.irq = PIC_IRQ13; + io_dev.fd = -1; io_dev.start_addr = 0xf0; io_dev.end_addr = 0xff; io_dev.handler_name = "Math Coprocessor"; port_register_handler(io_dev, 0); - savefpstate(vm86_fpu_state); + vm86_fpu_state = aligned_alloc(16, sizeof(*vm86_fpu_state)); + savefpstate(*vm86_fpu_state); #ifdef FE_NOMASK_ENV feenableexcept(FE_DIVBYZERO | FE_OVERFLOW); #endif @@ -348,22 +324,14 @@ void cpu_setup(void) orig_vm_dpmi = config.cpu_vm_dpmi; if (config.cpu_vm == -1) config.cpu_vm = -#if defined(__x86_64__) +#ifdef __x86_64__ CPUVM_KVM -#elif defined(__i386__) - CPUVM_VM86 #else - CPUVM_EMU + CPUVM_VM86 #endif ; if (config.cpu_vm_dpmi == -1) - config.cpu_vm_dpmi = -#if defined(__x86_64__) || defined(__i386__) - CPUVM_KVM -#else - CPUVM_EMU -#endif - ; + config.cpu_vm_dpmi = CPUVM_KVM; if ((config.cpu_vm == CPUVM_KVM || config.cpu_vm_dpmi == CPUVM_KVM) && !init_kvm_cpu()) { @@ -413,70 +381,3 @@ void cpu_setup(void) init_emu_cpu(); #endif } - - -void fxsave_to_fsave(const struct emu_fpxstate *fxsave, struct emu_fsave *fptr) -{ - unsigned int tmp; - int i; - - fptr->cw = fxsave->cwd | 0xffff0000u; - fptr->sw = fxsave->swd | 0xffff0000u; - /* Expand the valid bits */ - tmp = fxsave->ftw; /* 00000000VVVVVVVV */ - tmp = (tmp | (tmp << 4)) & 0x0f0f; /* 0000VVVV0000VVVV */ - tmp = (tmp | (tmp << 2)) & 0x3333; /* 00VV00VV00VV00VV */ - tmp = (tmp | (tmp << 1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ - /* Transform each bit from 1 to 00 (valid) or 0 to 11 (empty). - The kernel will convert it back, so no need to worry about zero - and special states 01 and 10. */ - tmp = ~(tmp | (tmp << 1)); - fptr->tag = tmp | 0xffff0000u; - fptr->ipoff = fxsave->fip; - fptr->cssel = (uint16_t)fxsave->fcs | ((uint32_t)fxsave->fop << 16); - fptr->dataoff = fxsave->fdp; - fptr->datasel = fxsave->fds; - for (i = 0; i < 8; i++) - memcpy(&fptr->st[i], &fxsave->st[i], sizeof(fptr->st[i])); -} - -/* - * FPU tag word conversions. - */ -static unsigned short twd_i387_to_fxsr(unsigned short twd) -{ - unsigned int tmp; /* to avoid 16 bit prefixes in the code */ - - /* Transform each pair of bits into 01 (valid) or 00 (empty) */ - tmp = ~twd; - tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ - /* and move the valid bits to the lower byte. */ - tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ - tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ - tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ - - return tmp; -} - -/* NOTE: this function does NOT memset the "unused" fxsave fields. - * We preserve the previous fxsave context. */ -void fsave_to_fxsave(const struct emu_fsave *fptr, struct emu_fpxstate *fxsave) - -{ - int i; - - fxsave->cwd = fptr->cw; - fxsave->swd = fptr->sw; - fxsave->ftw = twd_i387_to_fxsr(fptr->tag); - fxsave->fop = (uint16_t) ((uint32_t) fptr->cssel >> 16); - fxsave->fip = fptr->ipoff; - fxsave->fcs = (fptr->cssel & 0xffff); - fxsave->fdp = fptr->dataoff; - fxsave->fds = fptr->datasel; - - for (i = 0; i < 8; ++i) { - /* fxsave's regs are larger so memset first */ - memset(&fxsave->st[i], 0, sizeof(fxsave->st[0])); - memcpy(&fxsave->st[i], &fptr->st[i], sizeof(fptr->st[0])); - } -} diff --git a/src/base/emu-i386/cputime.c b/src/base/emu-i386/cputime.c index 78efe7b..f1e4441 100644 --- a/src/base/emu-i386/cputime.c +++ b/src/base/emu-i386/cputime.c @@ -82,6 +82,8 @@ static hitimer_t (*RAWcpuTIME)(void); hitimer_u ZeroTimeBase = { 0 }; static hitimer_t (*GETcpuTIME)(void); +static hitimer_u ZeroTSCBase = { 0 }; +static hitimer_t C4Base = 0; static hitimer_t LastTimeRead = 0; static hitimer_t StopTimeBase = 0; int cpu_time_stop = 0; @@ -94,11 +96,7 @@ static void idle_hlt_thr(void *arg); static hitimer_t do_gettime(void) { struct timespec tv; -#ifdef CLOCK_MONOTONIC_COURSE - int err = clock_gettime(CLOCK_MONOTONIC_COARSE, &tv); -#else int err = clock_gettime(CLOCK_MONOTONIC, &tv); -#endif if (err) { error("Cannot get time!\n"); leavedos(49); @@ -133,6 +131,11 @@ void uncache_time(void) pthread_mutex_unlock(&ctime_mtx); } +static hitimer_t rawP5time(void) +{ + return CPUtoUS(); +} + /* * SIDOC_BEGIN_FUNCTION GETcpuTIME * @@ -149,6 +152,21 @@ static hitimer_t getC4time(void) return (rawC4time() - ZeroTimeBase.td); } +/* this routine is called from the sigalrm handler to + update the TSC base */ +void update_cputime_TSCBase(void) +{ + if (cpu_time_stop) return; + C4Base = getC4time(); + ZeroTSCBase.td = GETTSC(); +} + +static hitimer_t getP5time(void) +{ + if (cpu_time_stop) return LastTimeRead; + return TSCtoUS(GETTSC() - ZeroTSCBase.td) + C4Base; +} + /* * SIDOC_BEGIN_FUNCTION GETusTIME(sc) * @@ -190,12 +208,26 @@ hitimer_t GETusSYSTIME(void) } -void get_time_init(void) +void get_time_init (void) { ZeroTimeBase.td = rawC4time(); - RAWcpuTIME = rawC4time; /* in usecs */ - GETcpuTIME = getC4time; /* in usecs */ - g_printf("TIMER: using clock_gettime(CLOCK_MONOTONIC)\n"); + if ((config.realcpu > CPU_486) && config.rdtsc) { + /* we are here if: a 586/686 was detected at startup, we are not + * on a SMP machine and the user didn't say 'rdtsc off'. But + * we could have an emulated CPU < 586, this doesn't affect timing + * but only flags processing (& other features) */ + RAWcpuTIME = rawP5time; /* in usecs */ + GETcpuTIME = getP5time; /* in usecs */ + ZeroTSCBase.td = GETTSC(); + g_printf("TIMER: using pentium timing\n"); + } + else { + /* we are here on all other cases: real CPU < 586, SMP machines, + * 'rdtsc off' into config file */ + RAWcpuTIME = rawC4time; /* in usecs */ + GETcpuTIME = getC4time; /* in usecs */ + g_printf("TIMER: using clock_gettime(CLOCK_MONOTONIC)\n"); + } } void cputime_late_init(void) @@ -223,6 +255,8 @@ int restart_cputime (int quiet) if (!cpu_time_stop) return 1; if (!quiet) dbug_printf("RESTART TIME\n"); cpu_time_stop = 0; + if (ZeroTSCBase.td) + update_cputime_TSCBase(); ZeroTimeBase.td += RAWcpuTIME() - StopTimeBase; return 0; } @@ -267,6 +301,62 @@ void unfreeze_dosemu(void) Video->change_config (CHG_TITLE, NULL); } + +/* --------------------------------------------------------------------- */ + +static int getmhz(void) +{ + struct timeval tv1,tv2; + hitimer_t a,b; + unsigned long a0, a1, b0, b1; + + gettimeofday(&tv1, NULL); + __asm__ __volatile__ ("rdtsc" + :"=a" (a0), + "=d" (a1)); +/* for (j=0; j<10000000; j++);*/ /* 500ms on a P5-100 */ + usleep(50000); + gettimeofday(&tv2, NULL); + __asm__ __volatile__ ("rdtsc" + :"=a" (b0), + "=d" (b1)); + b = (((hitimer_t)b1 << 32) | b0) - (((hitimer_t)a1 << 32) | a0); + a = (tv2.tv_sec*1000000 + tv2.tv_usec) - + (tv1.tv_sec*1000000 + tv1.tv_usec); + return (int)((b*4096)/a); +} + +/* + * bogospeed is called when a CPU >486 is detected at startup, or when + * the user specifies -5 or -6 on the command line (provided (s)he HAS + * a >486 CPU). The name comes from the previous use of BogoMIPS from + * /proc/cpuinfo; the value returned must NOT be bogus... + */ +int bogospeed(unsigned long *spus, unsigned long *sptick) +{ + int mlt, dvs; + + if (config.realcpu < CPU_586) { + fprintf(stderr,"You can't access 586 features on CPU=%d\n", + config.realcpu); + exit(1); + } + + mlt = 4096; dvs = getmhz(); + + /* speed division factor to get 1us from CPU clocks - for + * details on fast division see timers.h */ + *spus = (LLF_US*mlt)/dvs; + + /* speed division factor to get 838ns from CPU clocks */ + *sptick = (LLF_TICKS*mlt)/dvs; + + config.CPUSpeedInMhz = dvs/mlt; + fprintf (stderr,"CPU speed set to %d MHz\n",(dvs/mlt)); +/* fprintf (stderr,"CPU speed factors %ld,%ld\n",*spus,*sptick); */ + return 0; +} + /* idle functions to let hogthreshold do its work .... */ static int trigger1 = 0; void reset_idle(int val) @@ -281,7 +371,8 @@ void reset_idle(int val) void alarm_idle(void) { pthread_mutex_lock(&trigger_mtx); - trigger1++; + if (trigger1 < 0) + trigger1++; pthread_mutex_unlock(&trigger_mtx); } @@ -293,14 +384,6 @@ void trigger_idle(void) pthread_mutex_unlock(&trigger_mtx); } -void untrigger_idle(void) -{ - pthread_mutex_lock(&trigger_mtx); - if (trigger1 > 0) - trigger1--; - pthread_mutex_unlock(&trigger_mtx); -} - void dosemu_sleep(void) { sigset_t mask; @@ -313,7 +396,7 @@ void dosemu_sleep(void) inner loop applies. Heuristic idlers (int16/ah=1, mouse) need the two loops -- the outer loop can be reset using reset_idle */ -static void _idle(int threshold1, int threshold, int threshold2, +static int _idle(int threshold1, int threshold, int threshold2, const char *who, int enable_ints) { static int trigger = 0; @@ -331,7 +414,6 @@ static void _idle(int threshold1, int threshold, int threshold2, coopth_wait(); if (enable_ints && !old_if) clear_IF(); - ret = 1; pthread_mutex_lock(&trigger_mtx); trigger = 0; if (debug_level('g') > 5) @@ -339,28 +421,22 @@ static void _idle(int threshold1, int threshold, int threshold2, } if (trigger1 > 0) trigger1--; + if (trigger == 0) + ret = 1; } pthread_mutex_unlock(&trigger_mtx); } - - if (!ret && enable_ints && !old_if) - int_yield(); + return ret; } -void idle(int threshold1, int threshold, int threshold2, const char *who) +int idle(int threshold1, int threshold, int threshold2, const char *who) { - _idle(threshold1, threshold, threshold2, who, 0); + return _idle(threshold1, threshold, threshold2, who, 0); } -void idle_enable2(int threshold1, int threshold, int threshold2, - const char *who) +int idle_enable(int threshold1, int threshold, int threshold2, const char *who) { - _idle(threshold1, threshold, threshold2, who, 1); -} - -void idle_enable(int threshold, int threshold2, const char *who) -{ - _idle(0, threshold, threshold2, who, 1); + return _idle(threshold1, threshold, threshold2, who, 1); } void int_yield(void) @@ -369,7 +445,8 @@ void int_yield(void) * asm volatile("sti ; nop ; rep ; nop ; cli ; cld" : : :"memory"); */ set_IF(); - coopth_yield(); + pic_run(); + coopth_sched_cond(); clear_IF(); } diff --git a/src/base/emu-i386/do_vm86.c b/src/base/emu-i386/do_vm86.c index 6495560..e48d4f0 100644 --- a/src/base/emu-i386/do_vm86.c +++ b/src/base/emu-i386/do_vm86.c @@ -1,3 +1,4 @@ +#include "mhpdbg.h" /* Define if we want graphics in X (of course we want :-) (root@zaphod) */ /* WARNING: This may not work in BSD, because it was written for Linux! */ @@ -20,7 +21,6 @@ #include #include "emu.h" -#include "mhpdbg.h" #ifdef __linux__ #include "sys_vm86.h" #endif @@ -52,8 +52,6 @@ #include "vgaemu.h" #include "sig.h" -static void pic_run(void); - int vm86_fault(unsigned trapno, unsigned err, dosaddr_t cr2) { #ifdef USE_MHPDBG @@ -70,14 +68,11 @@ int vm86_fault(unsigned trapno, unsigned err, dosaddr_t cr2) case 0x04: /* overflow */ case 0x05: /* bounds */ case 0x07: /* device_not_available */ - error_once("exception %#x occured\n", trapno); - if (!IS_REDIRECTED(trapno)) - goto sgleave; do_int(trapno); return 0; case 0x10: /* coprocessor error */ - raise_fpu_irq(); /* this is the 386 way of signalling this */ + pic_request(PIC_IRQ13); /* this is the 386 way of signalling this */ return 0; case 0x11: /* alignment check */ @@ -90,7 +85,7 @@ int vm86_fault(unsigned trapno, unsigned err, dosaddr_t cr2) case 0x06: /* invalid_op */ { unsigned char *csp; - error_once("SIGILL while in vm86(): %04x:%04x\n", SREG(cs), LWORD(eip)); + dbug_printf("SIGILL while in vm86(): %04x:%04x\n", SREG(cs), LWORD(eip)); if (config.vga && SREG(cs) == config.vbios_seg) { if (!config.vbios_post) error("Fault in VBIOS code, try setting $_vbios_post=(1)\n"); @@ -173,6 +168,9 @@ static int vm86_hlt_handle(void) dpmi_init(); } else if ((lina >= DPMI_ADD) && (lina < DPMI_ADD + (DPMI_end - DPMI_OFF))) { +#if CONFIG_HLT_TRACE > 0 + h_printf("HLT: dpmi_realmode_hlt\n"); +#endif dpmi_realmode_hlt(lina); } else { @@ -344,48 +342,48 @@ static int handle_GP_fault(void) case 0xe5: /* inw xx, ind xx */ LWORD(eip) += 2; - if (prefix66) REG(eax) = port_ind((int) csp[1]); - else LWORD(eax) = port_inw((int) csp[1]); + if (prefix66) REG(eax) = ind((int) csp[1]); + else LWORD(eax) = inw((int) csp[1]); break; case 0xe4: /* inb xx */ LWORD(eip) += 2; LWORD(eax) &= ~0xff; - LWORD(eax) |= port_inb((int) csp[1]); + LWORD(eax) |= inb((int) csp[1]); break; case 0xed: /* inw dx, ind dx */ LWORD(eip)++; - if (prefix66) REG(eax) = port_ind(LWORD(edx)); - else LWORD(eax) = port_inw(LWORD(edx)); + if (prefix66) REG(eax) = ind(LWORD(edx)); + else LWORD(eax) = inw(LWORD(edx)); break; case 0xec: /* inb dx */ LWORD(eip)++; LWORD(eax) &= ~0xff; - LWORD(eax) |= port_inb(LWORD(edx)); + LWORD(eax) |= inb(LWORD(edx)); break; case 0xe7: /* outw xx */ LWORD(eip) += 2; - if (prefix66) port_outd((int)csp[1], REG(eax)); - else port_outw((int)csp[1], LWORD(eax)); + if (prefix66) outd((int)csp[1], REG(eax)); + else outw((int)csp[1], LWORD(eax)); break; case 0xe6: /* outb xx */ LWORD(eip) += 2; - port_outb((int) csp[1], LO(ax)); + outb((int) csp[1], LO(ax)); break; case 0xef: /* outw dx, outd dx */ LWORD(eip)++; - if (prefix66) port_outd(LWORD(edx), REG(eax)); - else port_outw(LWORD(edx), LWORD(eax)); + if (prefix66) outd(LWORD(edx), REG(eax)); + else outw(LWORD(edx), LWORD(eax)); break; case 0xee: /* outb dx */ LWORD(eip)++; - port_outb(LWORD(edx), LO(ax)); + outb(LWORD(edx), LO(ax)); break; case 0xf4: /* hlt...I use it for various things, @@ -422,13 +420,9 @@ static void vm86_GP_fault(void) mhp_debug(DBG_GPF, 0, 0); #endif set_debug_level('g', 1); - error_once("general protection at %p: %x\n", lina,*lina); + error("general protection at %p: %x\n", lina,*lina); show_regs(); show_ints(0, 0x33); - if (IS_REDIRECTED(0x0d)) { - do_int(0x0d); - return; - } fatalerr = 4; leavedos(fatalerr); /* shouldn't return */ } @@ -449,7 +443,7 @@ static int true_vm86(union vm86_union *x) int ret; uint32_t old_flags = REG(eflags); - loadfpstate(vm86_fpu_state); + loadfpstate(*vm86_fpu_state); again: #if 0 ret = vm86(&x->vm86ps); @@ -467,7 +461,7 @@ again: * TODO: check kernel version */ REG(eflags) |= (old_flags & VIP); - savefpstate(vm86_fpu_state); + savefpstate(*vm86_fpu_state); /* there is no real need to save and restore the FPU state of the emulator itself: savefpstate (fnsave) also resets the current FPU state using fninit; fesetenv then restores trapping of division by @@ -477,18 +471,6 @@ again: fesetenv(&dosemu_fenv); return ret; } - -void true_vm86_fault(sigcontext_t *scp) -{ - if (_scp_trapno == 0x0e) { - /* we can get to instremu from here, so unblock SIGALRM & friends. - * It is needed to interrupt instremu when it runs for too long. */ - signal_unblock_async_sigs(); - if (vga_emu_fault(_scp_cr2, _scp_err, NULL) == True) - return; - } - vm86_fault(_scp_trapno, _scp_err, _scp_cr2); -} #endif static int do_vm86(union vm86_union *x) @@ -511,7 +493,7 @@ static void _do_vm86(void) { int retval; #ifdef USE_MHPDBG - int dret = 0; + int dret; #endif if (isset_IF() && isset_VIP()) { @@ -560,17 +542,14 @@ static void _do_vm86(void) break; case VM86_INTx: #ifdef USE_MHPDBG - if (mhpdbg.active) - dret = mhp_debug(DBG_INTx + (VM86_ARG(retval) << 8), 1, 0); + dret = mhp_debug(DBG_INTx + (VM86_ARG(retval) << 8), 1, 0); if (!dret) #endif do_int(VM86_ARG(retval)); break; case VM86_TRAP: #ifdef USE_MHPDBG - if (mhpdbg.active) - dret = mhp_debug(DBG_TRAP + (VM86_ARG(retval) << 8), 0, 0); - if (!dret) + if(!mhp_debug(DBG_TRAP + (VM86_ARG(retval) << 8), 0, 0)) #endif do_int(VM86_ARG(retval)); break; @@ -597,7 +576,7 @@ static void _do_vm86(void) * * DANG_END_FUNCTION */ -void run_vm86(void) +static void run_vm86(void) { int retval, cnt; @@ -630,14 +609,13 @@ void run_vm86(void) if (mhpdbg.active) mhp_debug(DBG_PRE_VM86, 0, 0); #endif + if (isset_IF() && isset_VIP()) + return; + if (signal_pending()) + return; /* if thread wants some sleep, we can't fuck it in a busy loop */ - if (coopth_wants_sleep_vm86()) { - pic_run(); // try to awake - if (in_dpmi_pm()) - return; - if (coopth_wants_sleep_vm86()) // not awaken? - return; - } + if (coopth_wants_sleep_vm86()) + return; /* some subsystems doesn't want this optimization loop as well */ if (retval == HLT_RET_SPECIAL) return; @@ -655,10 +633,6 @@ void run_vm86(void) _ESI, _EDI, _ES, _EFLAGS); } } - pic_run(); /* trigger any hardware interrupts requested */ - if (in_dpmi_pm()) - return; - #ifdef USE_MHPDBG if (mhpdbg.active) mhp_debug(DBG_PRE_VM86, 0, 0); @@ -671,49 +645,11 @@ void run_vm86(void) void vm86_helper(void) { assert(!in_dpmi_pm()); - clear_VIP(); _do_vm86(); handle_signals(); coopth_run(); } -static void pic_run(void) -{ - int inum; - - if (!pic_pending()) { - clear_VIP(); - return; - } - - if (!isset_IF()) { -#if 0 - /* try to detect timer flood, and not set VIP if it is there. - * See https://github.com/stsp/dosemu2/issues/918 - */ - if (pic_sys_time < pic_dos_time + - TIMER0_FLOOD_THRESHOLD || - pic_pending_masked(1 << PIC_IRQ0)) - set_VIP(); - else - r_printf("PIC: timer flood work-around\n"); -#else - /* the above work-around regresses goblins2, see - * https://github.com/dosemu2/dosemu2/issues/1300 - */ - set_VIP(); -#endif - return; /* exit if ints are disabled */ - } - clear_VIP(); - - inum = pic_get_inum(); - if (dpmi_active()) - run_pm_int(inum); - else - real_run_int(inum); -} - /* * DANG_BEGIN_FUNCTION loopstep_run_vm86 * @@ -739,6 +675,7 @@ void loopstep_run_vm86(void) if (mhpdbg_is_stopped()) return; #endif + pic_run(); /* trigger any hardware interrupts requested */ } int do_call_back(Bit16u cs, Bit16u ip) diff --git a/src/base/emu-i386/kvm.c b/src/base/emu-i386/kvm.c index 5fba745..b89ad9d 100644 --- a/src/base/emu-i386/kvm.c +++ b/src/base/emu-i386/kvm.c @@ -27,19 +27,15 @@ #include #include #include -#include #include #include #include -#include #include "kvm.h" -#include "kvmmon_offsets.h" #include "emu.h" #include "emu-ldt.h" #include "cpu-emu.h" #include "vgaemu.h" -#include "dos2linux.h" #include "mapping.h" #include "sig.h" @@ -56,8 +52,9 @@ #define RETURN_MASK ((SAFE_MASK | 0x28 | X86_EFLAGS_FIXED) & \ ~X86_EFLAGS_RF) // 0x244dff -extern char _binary_kvmmon_o_bin_end[] asm("_binary_kvmmon_o_bin_end"); -extern char _binary_kvmmon_o_bin_start[] asm("_binary_kvmmon_o_bin_start"); +extern char kvm_mon_start[]; +extern char kvm_mon_hlt[]; +extern char kvm_mon_end[]; /* V86/DPMI monitor structure to run code in V86 mode with VME enabled or DPMI clients inside KVM @@ -117,14 +114,9 @@ static struct monitor { unsigned char padding2[0x3000-0x2200 -IDT_ENTRIES*sizeof(Gatedesc) -sizeof(unsigned int) - -sizeof(unsigned int)*2 - -sizeof(struct emu_fpxstate) -sizeof(struct vm86_regs)]; /* 2308 */ - unsigned int cr2; /* Fault stack at 2DA0 */ - unsigned int cr3; /* cr3 in (no TLB flush if 0) */ + unsigned int cr2; /* Fault stack at 2FA8 */ struct vm86_regs regs; - unsigned padding[1]; - struct emu_fpxstate fpstate; /* 2e00 */ /* 3000: page directory, 4000: page table */ unsigned int pde[PAGE_SIZE/sizeof(unsigned int)]; unsigned int pte[(PAGE_SIZE*PAGE_SIZE)/sizeof(unsigned int) @@ -142,103 +134,18 @@ static struct monitor { unsigned char kvm_identity_map[20*PAGE_SIZE]; } *monitor; -/* map the monitor high in physical/linear address space with some - room to spare (top - 16MB, monitor takes a little over 4MB) */ -#define MONITOR_DOSADDR 0xff000000 - static struct kvm_cpuid2 *cpuid; /* fpu vme de pse tsc msr mce cx8 */ #define CPUID_FEATURES_EDX 0x1bf static struct kvm_run *run; static int kvmfd, vmfd, vcpufd; +static volatile int mprotected_kvm = 0; static struct kvm_sregs sregs; #define MAXSLOT 400 static struct kvm_userspace_memory_region maps[MAXSLOT]; static int init_kvm_vcpu(void); -static void kvm_set_readonly(dosaddr_t base, dosaddr_t size); - -#if !defined(DISABLE_SYSTEM_WA) || !defined(KVM_CAP_IMMEDIATE_EXIT) - -/* compat functions for older complex method of immediate exit - using a signal that is blocked outside KVM_RUN but not blocked inside it */ - -#include - -#ifndef KVM_CAP_IMMEDIATE_EXIT -#define KVM_CAP_IMMEDIATE_EXIT 136 -#define immediate_exit padding1[0] -#endif - -#define KVM_IMMEDIATE_EXIT_SIG (SIGRTMIN + 1) -#define KERNEL_SIGSET_T_SIZE 8 - -static void kvm_set_immediate_exit(int set) -{ - static int kvm_cap_immediate_exit = -1; - if (kvm_cap_immediate_exit == -1) { // setup - kvm_cap_immediate_exit = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_IMMEDIATE_EXIT) > 0; - if (!kvm_cap_immediate_exit) { - struct sigaction sa; - sigset_t sigset; - /* KVM_SET_SIGNAL_MASK expects a kernel sigset_t which is - smaller than a glibc one */ - union { - struct kvm_signal_mask mask; - unsigned char buf[sizeof(struct kvm_signal_mask) + KERNEL_SIGSET_T_SIZE]; - } maskbuf; - - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = SIG_DFL; // never called - sigaction(KVM_IMMEDIATE_EXIT_SIG, &sa, NULL); - - /* block KVM_IMMEDIATE_EXIT_SIG in main thread */ - sigemptyset(&sigset); - sigaddset(&sigset, KVM_IMMEDIATE_EXIT_SIG); - pthread_sigmask(SIG_BLOCK, &sigset, NULL); - - /* don't block any signals inside the guest */ - sigemptyset(&sigset); - maskbuf.mask.len = KERNEL_SIGSET_T_SIZE; - assert(sizeof(sigset) >= KERNEL_SIGSET_T_SIZE); - memcpy(maskbuf.mask.sigset, &sigset, KERNEL_SIGSET_T_SIZE); - if (ioctl(vcpufd, KVM_SET_SIGNAL_MASK, &maskbuf.mask) == -1) { - perror("KVM: KVM_SET_SIGNAL_MASK"); - leavedos_main(99); - } - } - } - - if (kvm_cap_immediate_exit) { - assert(run->immediate_exit == !set); - run->immediate_exit = set; - return; - } - - if (set) - pthread_kill(pthread_self(), KVM_IMMEDIATE_EXIT_SIG); - else { - // need to flush the signal after KVM_RUN - sigset_t sigset; - assert(sigpending(&sigset) == 0 && - sigismember(&sigset, KVM_IMMEDIATE_EXIT_SIG)); - sigemptyset(&sigset); - sigaddset(&sigset, KVM_IMMEDIATE_EXIT_SIG); - sigwaitinfo(&sigset, NULL); - } -} - -#else // function without workaround if kernels older than 4.13 not supported - -static inline void kvm_set_immediate_exit(int set) -{ - assert(run->immediate_exit == !set); - run->immediate_exit = set; -} - -#endif static void set_idt_default(dosaddr_t mon, int i) { @@ -261,7 +168,7 @@ void kvm_set_idt_default(int i) { if (i < 0x11) return; - set_idt_default(sregs.tr.base, i); + set_idt_default(DOSADDR_REL((unsigned char *)monitor), i); } static void set_idt(int i, uint16_t sel, uint32_t offs, int is_32, int tg) @@ -299,7 +206,7 @@ static void kvm_set_desc(Descriptor *desc, struct kvm_segment *seg) } /* initialize KVM virtual machine monitor */ -static void init_kvm_monitor(void) +void init_kvm_monitor(void) { int ret, i; @@ -307,8 +214,8 @@ static void init_kvm_monitor(void) return; /* create monitor structure in memory */ - monitor = mmap_mapping_huge_page_aligned(MAPPING_SCRATCH|MAPPING_KVM, - sizeof(*monitor), PROT_READ | PROT_WRITE); + monitor = mmap_mapping_ux(MAPPING_SCRATCH | MAPPING_KVM, (void *)-1, + sizeof(*monitor), PROT_READ | PROT_WRITE); /* trap all I/O instructions with GPF */ memset(monitor->io_bitmap, 0xff, TSS_IOPB_SIZE+1); @@ -324,7 +231,7 @@ static void init_kvm_monitor(void) return; } - sregs.tr.base = MONITOR_DOSADDR; + sregs.tr.base = DOSADDR_REL((unsigned char *)monitor); sregs.tr.limit = offsetof(struct monitor, io_bitmap) + TSS_IOPB_SIZE - 1; sregs.tr.selector = 0x18; sregs.tr.unusable = 0; @@ -337,8 +244,10 @@ static void init_kvm_monitor(void) sregs.tr.db = 0; sregs.tr.g = 0; - if (config.cpu_vm_dpmi == CPUVM_KVM) - ldt_buffer = (unsigned char *)monitor->ldt; +#ifdef X86_EMULATOR + LDT = monitor->ldt; +#endif + ldt_buffer = (unsigned char *)monitor->ldt; sregs.ldt.base = sregs.tr.base + offsetof(struct monitor, ldt); sregs.ldt.limit = LDT_ENTRIES * LDT_ENTRY_SIZE - 1; sregs.ldt.selector = 0x20; @@ -384,25 +293,20 @@ static void init_kvm_monitor(void) monitor->idt[i].present = 1; } assert(kvm_mon_end - kvm_mon_start <= sizeof(monitor->code)); - memcpy(monitor->code, _binary_kvmmon_o_bin_start, - _binary_kvmmon_o_bin_end - _binary_kvmmon_o_bin_start); + memcpy(monitor->code, kvm_mon_start, kvm_mon_end - kvm_mon_start); /* setup paging */ sregs.cr3 = sregs.tr.base + offsetof(struct monitor, pde); /* base PDE; others derive from this one */ monitor->pde[0] = (sregs.tr.base + offsetof(struct monitor, pte)) | (PG_PRESENT | PG_RW | PG_USER); - /* exclude special regions for KVM-internal TSS and identity page */ - mmap_kvm(MAPPING_SCRATCH|MAPPING_KVM, MONITOR_DOSADDR, - offsetof(struct monitor, kvm_tss), - monitor, MONITOR_DOSADDR, PROT_READ | PROT_WRITE); + mprotect_kvm(MAPPING_KVM, sregs.tr.base, offsetof(struct monitor, code), + PROT_READ | PROT_WRITE); mprotect_kvm(MAPPING_KVM, sregs.tr.base + offsetof(struct monitor, code), sizeof(monitor->code), PROT_READ | PROT_EXEC); sregs.cr0 |= X86_CR0_PE | X86_CR0_PG | X86_CR0_NE | X86_CR0_ET; sregs.cr4 |= X86_CR4_VME; - if (config.umip) - sregs.cr4 |= X86_CR4_UMIP; /* setup registers to point to VM86 monitor */ sregs.cs.base = 0; @@ -432,13 +336,13 @@ static int init_kvm_vcpu(void) the kernel needs to emulate that using V86 mode, as is necessary on Nehalem and earlier Intel CPUs */ ret = ioctl(vmfd, KVM_SET_TSS_ADDR, - MONITOR_DOSADDR + offsetof(struct monitor, kvm_tss)); + (unsigned long)DOSADDR_REL(monitor->kvm_tss)); if (ret == -1) { perror("KVM: KVM_SET_TSS_ADDR\n"); return 0; } - uint64_t addr = MONITOR_DOSADDR + offsetof(struct monitor, kvm_identity_map); + uint64_t addr = DOSADDR_REL(monitor->kvm_identity_map); ret = ioctl(vmfd, KVM_SET_IDENTITY_MAP_ADDR, &addr); if (ret == -1) { perror("KVM: KVM_SET_IDENTITY_MAP_ADDR\n"); @@ -452,16 +356,17 @@ static int init_kvm_vcpu(void) } assert(cpuid); - /* use host CPUID, adjust signature */ - for (unsigned int i = 0; i < cpuid->nent; i++) { - struct kvm_cpuid_entry2 *entry = &cpuid->entries[i]; - if (entry->function == KVM_CPUID_SIGNATURE) { - entry->eax = KVM_CPUID_FEATURES; - entry->ebx = 0x4b4d564b; // KVMK - entry->ecx = 0x564b4d56; // VMKV - entry->edx = 0x4d; // M - } - } + // Use the same values as in emu-i386/simx86/interp.c + // (Pentium 133-200MHz, "GenuineIntel") + cpuid->entries[0].eax = 1; + cpuid->entries[0].ebx = 0x756e6547; + cpuid->entries[0].ecx = 0x6c65746e; + cpuid->entries[0].edx = 0x49656e69; + // family 5, model 2, stepping 12, features see above + cpuid->entries[1].eax = 0x052c; + cpuid->entries[1].ebx = 0; + cpuid->entries[1].ecx = 0; + cpuid->entries[1].edx = CPUID_FEATURES_EDX; ret = ioctl(vcpufd, KVM_SET_CPUID2, cpuid); if (ret == -1) { perror("KVM: KVM_SET_CPUID2"); @@ -497,41 +402,6 @@ int init_kvm_cpu(void) return 0; } -#if defined(KVM_CAP_SYNC_MMU) && defined(KVM_CAP_SET_IDENTITY_MAP_ADDR) && \ - defined(KVM_CAP_SET_TSS_ADDR) && defined(KVM_CAP_XSAVE) && \ - defined(KVM_CAP_IMMEDIATE_EXIT) - ret = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_SYNC_MMU); - if (ret <= 0) { - error("KVM: SYNC_MMU unsupported %x\n", ret); - goto errcap; - } - ret = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_SET_IDENTITY_MAP_ADDR); - if (ret <= 0) { - error("KVM: SET_IDENTITY_MAP_ADDR unsupported %x\n", ret); - goto errcap; - } - ret = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_SET_TSS_ADDR); - if (ret <= 0) { - error("KVM: SET_TSS_ADDR unsupported %x\n", ret); - goto errcap; - } - ret = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_XSAVE); - if (ret <= 0) { - error("KVM: XSAVE unsupported %x\n", ret); - goto errcap; - } - ret = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_IMMEDIATE_EXIT); -#ifndef KVM_IMMEDIATE_EXIT_SIG - if (ret <= 0) { - error("KVM: IMMEDIATE_EXIT unsupported %x\n", ret); - goto errcap; - } -#endif -#else - error("kernel is too old, KVM unsupported\n"); - goto errcap; -#endif - vmfd = ioctl(kvmfd, KVM_CREATE_VM, (unsigned long)0); if (vmfd == -1) { warn("KVM: KVM_CREATE_VM: %s\n", strerror(errno)); @@ -552,45 +422,17 @@ int init_kvm_cpu(void) goto err; } - init_kvm_monitor(); return 1; err: - close(vmfd); free(cpuid); cpuid = NULL; -errcap: - close(kvmfd); return 0; } -static struct kvm_userspace_memory_region * -kvm_get_memory_region(dosaddr_t dosaddr, dosaddr_t size) -{ - int slot; - struct kvm_userspace_memory_region *p = &maps[0]; - struct kvm_userspace_memory_region *ret = NULL; - - for (slot = 0; slot < MAXSLOT; slot++, p++) { - if (p->guest_phys_addr <= dosaddr && - dosaddr + size <= p->guest_phys_addr + p->memory_size) { - ret = p; - break; - } - } - /* if we are on full kvm then there should be no missing slots */ - if (config.cpu_vm == CPUVM_KVM && config.cpu_vm_dpmi == CPUVM_KVM) - assert(slot < MAXSLOT); - return ret; -} - static void set_kvm_memory_region(struct kvm_userspace_memory_region *region) { - int ret; - Q_printf("KVM: map slot=%d flags=%d dosaddr=0x%08llx size=0x%08llx unixaddr=0x%llx\n", - region->slot, region->flags, region->guest_phys_addr, - region->memory_size, region->userspace_addr); - ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, region); + int ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, region); if (ret == -1) { perror("KVM: KVM_SET_USER_MEMORY_REGION"); leavedos_main(99); @@ -606,25 +448,25 @@ void set_kvm_memory_regions(void) for (slot = 0; slot < MAXSLOT; slot++) { struct kvm_userspace_memory_region *p = &maps[slot]; + if (p->memory_size != 0) { + if (config.cpu_vm_dpmi != CPUVM_KVM && + (void *)(uintptr_t)p->userspace_addr != monitor) { + if (p->guest_phys_addr > LOWMEM_SIZE + HMASIZE) + p->memory_size = 0; + else if (p->guest_phys_addr + p->memory_size > LOWMEM_SIZE + HMASIZE) + p->memory_size = LOWMEM_SIZE + HMASIZE - p->guest_phys_addr; + } + } if (p->memory_size != 0) set_kvm_memory_region(p); } } -static void mmap_kvm_no_overlap(unsigned targ, void *addr, size_t mapsize, int flags) +static int mmap_kvm_no_overlap(unsigned targ, void *addr, size_t mapsize) { struct kvm_userspace_memory_region *region; int slot; - if (config.cpu_vm_dpmi != CPUVM_KVM && addr != monitor) { - if (targ >= LOWMEM_SIZE + HMASIZE) - return; - if (targ + mapsize > LOWMEM_SIZE + HMASIZE) - mapsize = LOWMEM_SIZE + HMASIZE - targ; - if (mapsize == 0) - return; - } - for (slot = 0; slot < MAXSLOT; slot++) if (maps[slot].memory_size == 0) break; @@ -640,16 +482,29 @@ static void mmap_kvm_no_overlap(unsigned targ, void *addr, size_t mapsize, int f region->guest_phys_addr = targ; region->userspace_addr = (uintptr_t)addr; region->memory_size = mapsize; - region->flags = flags; - Q_printf("KVM: mapped guest %#x to host addr %p, size=%zx, LOG_DIRTY=%d\n", - targ, addr, mapsize, flags == KVM_MEM_LOG_DIRTY_PAGES ? 1 : 0); - /* NOTE: the actual EPT update is delayed to set_kvm_memory_regions */ + Q_printf("KVM: mapped guest %#x to host addr %p, size=%zx\n", + targ, addr, mapsize); + return slot; +} + +static void check_overlap_kvm(dosaddr_t targ, size_t mapsize) +{ + /* unmaps KVM regions from targ to targ+mapsize, taking care of overlaps */ + int slot; + for (slot = 0; slot < MAXSLOT; slot++) { + struct kvm_userspace_memory_region *region = &maps[slot]; + size_t sz = region->memory_size; + unsigned gpa = region->guest_phys_addr; + if (sz > 0 && targ + mapsize > gpa && targ < gpa + sz) { + error("KVM: mapping inconsistency\n"); + leavedos(99); + } + } } static void do_munmap_kvm(dosaddr_t targ, size_t mapsize) { - /* unmaps KVM regions from targ to targ+mapsize, taking care of overlaps - NOTE: the actual EPT update is delayed to set_kvm_memory_regions */ + /* unmaps KVM regions from targ to targ+mapsize, taking care of overlaps */ int slot; for (slot = 0; slot < MAXSLOT; slot++) { struct kvm_userspace_memory_region *region = &maps[slot]; @@ -658,41 +513,63 @@ static void do_munmap_kvm(dosaddr_t targ, size_t mapsize) if (sz > 0 && targ + mapsize > gpa && targ < gpa + sz) { /* overlap: first unmap this mapping */ region->memory_size = 0; + set_kvm_memory_region(region); /* may need to remap head or tail */ if (gpa < targ) { region->memory_size = targ - gpa; + set_kvm_memory_region(region); } if (gpa + sz > targ + mapsize) { - mmap_kvm_no_overlap(targ + mapsize, + int slot2 = mmap_kvm_no_overlap(targ + mapsize, (void *)((uintptr_t)region->userspace_addr + targ + mapsize - gpa), - gpa + sz - (targ + mapsize), region->flags); + gpa + sz - (targ + mapsize)); + set_kvm_memory_region(&maps[slot2]); } } } } -void mmap_kvm(int cap, unsigned phys_addr, size_t mapsize, void *addr, dosaddr_t targ, int protect) +void munmap_kvm(int cap, dosaddr_t targ, size_t mapsize) { - size_t pagesize = sysconf(_SC_PAGESIZE); - unsigned int start = targ / pagesize; - unsigned int end = start + mapsize / pagesize; - unsigned int page; + if (cap & MAPPING_IMMEDIATE) + do_munmap_kvm(targ, mapsize); + else + check_overlap_kvm(targ, mapsize); +} - assert(cap & (MAPPING_INIT_LOWRAM|MAPPING_LOWMEM|MAPPING_KVM|MAPPING_VGAEMU)); - /* with KVM we need to manually remove/shrink existing mappings */ - do_munmap_kvm(phys_addr, mapsize); - mmap_kvm_no_overlap(phys_addr, addr, mapsize, 0); - /* monitor dirty pages on regular low ram for JIT */ - if ((cap & MAPPING_LOWMEM) && IS_EMU_JIT()) - kvm_set_dirty_log(phys_addr, mapsize); - for (page = start; page < end; page++, phys_addr += pagesize) { - int pde_entry = page >> 10; - if (monitor->pde[pde_entry] == 0) - monitor->pde[pde_entry] = monitor->pde[0] + pde_entry*pagesize; - monitor->pte[page] = phys_addr; +void mmap_kvm(int cap, void *addr, size_t mapsize, int protect) +{ + dosaddr_t targ; + int slot; + + if (cap == (MAPPING_DPMI|MAPPING_SCRATCH)) { + mprotect_kvm(cap, DOSADDR_REL(addr), mapsize, protect); + return; } + if (!(cap & (MAPPING_INIT_LOWRAM|MAPPING_VGAEMU|MAPPING_KMEM|MAPPING_KVM| + MAPPING_IMMEDIATE))) + return; + if (cap & MAPPING_INIT_LOWRAM) { + targ = 0; + } + else { + targ = DOSADDR_REL(addr); + if (cap & MAPPING_KVM) { + /* exclude special regions for KVM-internal TSS and identity page */ + mapsize = offsetof(struct monitor, kvm_tss); + } + } + /* with KVM we need to manually remove/shrink existing mappings */ + if (cap & MAPPING_IMMEDIATE) + do_munmap_kvm(targ, mapsize); + else + check_overlap_kvm(targ, mapsize); + slot = mmap_kvm_no_overlap(targ, addr, mapsize); mprotect_kvm(cap, targ, mapsize, protect); + /* update EPT if needed */ + if (cap & MAPPING_IMMEDIATE) + set_kvm_memory_region(&maps[slot]); } void mprotect_kvm(int cap, dosaddr_t targ, size_t mapsize, int protect) @@ -701,98 +578,31 @@ void mprotect_kvm(int cap, dosaddr_t targ, size_t mapsize, int protect) unsigned int start = targ / pagesize; unsigned int end = start + mapsize / pagesize; unsigned int page; - struct kvm_userspace_memory_region *p; - if (!(cap & (MAPPING_LOWMEM|MAPPING_EMS|MAPPING_HMA| - MAPPING_DPMI|MAPPING_VGAEMU|MAPPING_KVM|MAPPING_CPUEMU| - MAPPING_EXTMEM))) return; - if (memcheck_is_rom(targ)) { - kvm_set_readonly(targ, mapsize); - return; - } - p = kvm_get_memory_region(monitor->pte[start] & _PAGE_MASK, PAGE_SIZE); - if (!p) return; - - /* never apply read and write protections to regions with dirty logging or - phys MMIO and r/o */ - if (!(protect & PROT_WRITE) && - (p->flags & (KVM_MEM_LOG_DIRTY_PAGES|KVM_MEM_READONLY))) - return; + if (!(cap & (MAPPING_INIT_LOWRAM|MAPPING_LOWMEM|MAPPING_EMS|MAPPING_HMA| + MAPPING_DPMI|MAPPING_VGAEMU|MAPPING_KVM|MAPPING_CPUEMU))) return; if (monitor == NULL) return; Q_printf("KVM: protecting %x:%zx with prot %x\n", targ, mapsize, protect); for (page = start; page < end; page++) { - monitor->pte[page] &= _PAGE_MASK; + int pde_entry = page >> 10; + if (monitor->pde[pde_entry] == 0) + monitor->pde[pde_entry] = monitor->pde[0] + pde_entry*pagesize; + monitor->pte[page] = page * pagesize; if (protect & PROT_WRITE) monitor->pte[page] |= PG_PRESENT | PG_RW | PG_USER; else if (protect & PROT_READ) monitor->pte[page] |= PG_PRESENT | PG_USER; - if (cap & MAPPING_KVM) + if (cap & MAPPING_KVM) { monitor->pte[page] &= ~PG_USER; - } - monitor->cr3 = sregs.cr3; /* Force TLB flush */ -} - -static void kvm_set_readonly(dosaddr_t base, dosaddr_t size) -{ - struct kvm_userspace_memory_region *p = kvm_get_memory_region(base, size); - void *addr = (void *)((uintptr_t)(p->userspace_addr + - (base - p->guest_phys_addr))); - do_munmap_kvm(base, size); - mmap_kvm_no_overlap(base, addr, size, KVM_MEM_READONLY); -} - -void kvm_set_mmio(dosaddr_t base, dosaddr_t size, int on) -{ - struct kvm_userspace_memory_region *p = kvm_get_memory_region(base, size); - assert(p->flags & KVM_MEM_LOG_DIRTY_PAGES); - if (on == (p->flags == KVM_MEM_LOG_DIRTY_PAGES)) { - uint64_t region_size = p->memory_size; - p->flags = KVM_MEM_LOG_DIRTY_PAGES; - if (on) { - p->memory_size = 0; - p->flags |= KVM_MEM_READONLY; + if (cap & MAPPING_KVM_UC) + monitor->pte[page] |= PG_DC; } - set_kvm_memory_region(p); - p->memory_size = region_size; } -} -/* Enable dirty logging from base to base+size. - * This will not change the KVM-phys->host user space mapping itself but due - * to the way KVM works the memory slot typically needs to be split in 3 parts: - * 1. part without dirty log 2. part with dirty log 3. part without dirty log. - */ -void kvm_set_dirty_log(dosaddr_t base, dosaddr_t size) -{ - struct kvm_userspace_memory_region *p = kvm_get_memory_region(base, size); - void *addr = (void *)((uintptr_t)(p->userspace_addr + - (base - p->guest_phys_addr))); - do_munmap_kvm(base, size); - mmap_kvm_no_overlap(base, addr, size, KVM_MEM_LOG_DIRTY_PAGES); -} - -/* get dirty bitmap for memory region containing base. - * If base is not at the start of that region, the bitmap is shifted. - */ -void kvm_get_dirty_map(dosaddr_t base, unsigned char *bitmap) -{ - size_t bitmap_size; - struct kvm_dirty_log dirty_log = {0}; - struct kvm_userspace_memory_region *p = - kvm_get_memory_region(base, PAGE_SIZE); - - assert(p->flags & KVM_MEM_LOG_DIRTY_PAGES); - dirty_log.slot = p->slot; - dirty_log.dirty_bitmap = bitmap; - ioctl(vmfd, KVM_GET_DIRTY_LOG, &dirty_log); - bitmap_size = ((p->memory_size >> PAGE_SHIFT)+CHAR_BIT-1) / CHAR_BIT; - if (p->guest_phys_addr < base) { - int offset = ((base - p->guest_phys_addr) >> PAGE_SHIFT) / CHAR_BIT; - memmove(bitmap, bitmap + offset, bitmap_size - offset); - } + mprotected_kvm = 1; } /* This function works like handle_vm86_fault in the Linux kernel, @@ -946,76 +756,6 @@ static void set_ldt_seg(struct kvm_segment *seg, unsigned selector) seg->unusable = !desc->present; } -void kvm_update_fpu(void) -{ - struct kvm_fpu fpu = {}; - int ret; - - memcpy(fpu.fpr, vm86_fpu_state.st, sizeof(vm86_fpu_state.st)); - fpu.fcw = vm86_fpu_state.cwd; - fpu.fsw = vm86_fpu_state.swd; - fpu.ftwx = vm86_fpu_state.ftw; - fpu.last_opcode = vm86_fpu_state.fop; - fpu.last_ip = vm86_fpu_state.fip; - fpu.last_dp = vm86_fpu_state.fdp; - memcpy(fpu.xmm, vm86_fpu_state.xmm, sizeof(vm86_fpu_state.xmm)); - fpu.mxcsr = vm86_fpu_state.mxcsr; - ret = ioctl(vcpufd, KVM_SET_FPU, &fpu); - if (ret == -1) { - perror("KVM: KVM_SET_FPU"); - leavedos_main(99); - } -} - -void kvm_get_fpu(void) -{ - struct kvm_fpu fpu; - int ret = ioctl(vcpufd, KVM_GET_FPU, &fpu); - if (ret == -1) { - perror("KVM: KVM_GET_FPU"); - leavedos_main(99); - } - memcpy(vm86_fpu_state.st, fpu.fpr, sizeof(vm86_fpu_state.st)); - vm86_fpu_state.cwd = fpu.fcw; - vm86_fpu_state.swd = fpu.fsw; - vm86_fpu_state.ftw = fpu.ftwx; - vm86_fpu_state.fop = fpu.last_opcode; - vm86_fpu_state.fip = fpu.last_ip; - vm86_fpu_state.fcs = 0; - vm86_fpu_state.fdp = fpu.last_dp; - vm86_fpu_state.fds = 0; - memcpy(vm86_fpu_state.xmm, fpu.xmm, sizeof(vm86_fpu_state.xmm)); - vm86_fpu_state.mxcsr = fpu.mxcsr; -} - -void kvm_enter(int pm) -{ - kvm_update_fpu(); -} - -void kvm_leave(int pm) -{ - kvm_get_fpu(); - - /* collect and invalidate all touched low dirty pages with JIT code */ - if (IS_EMU_JIT()) { - int slot; - struct kvm_userspace_memory_region *p = &maps[0]; - for (slot = 0; slot < MAXSLOT; slot++, p++) - if (p->memory_size && - p->guest_phys_addr + p->memory_size <= LOWMEM_SIZE+HMASIZE && - (p->flags & KVM_MEM_LOG_DIRTY_PAGES) && - memcheck_is_system_ram(p->guest_phys_addr)) { - unsigned char bitmap[(LOWMEM_SIZE+HMASIZE)/CHAR_BIT]; - int i; - kvm_get_dirty_map(p->guest_phys_addr, bitmap); - for (i = 0; i < p->memory_size >> PAGE_SHIFT; i++) - if (test_bit(i, bitmap)) - e_invalidate_page_full(p->guest_phys_addr + (i << PAGE_SHIFT)); - } - } -} - static int kvm_post_run(struct vm86_regs *regs, struct kvm_regs *kregs) { int ret = ioctl(vcpufd, KVM_GET_REGS, kregs); @@ -1067,12 +807,11 @@ static int kvm_post_run(struct vm86_regs *regs, struct kvm_regs *kregs) } /* Inner loop for KVM, runs until HLT or signal */ -static unsigned int kvm_run(void) +static unsigned int kvm_run(struct vm86_regs *regs) { unsigned int exit_reason = 0; struct kvm_regs kregs = {}; static struct vm86_regs saved_regs; - struct vm86_regs *regs = &monitor->regs; if (run->exit_reason != KVM_EXIT_HLT && memcmp(regs, &saved_regs, sizeof(*regs))) { @@ -1093,7 +832,7 @@ static unsigned int kvm_run(void) kregs.rflags = regs->eflags; ret = ioctl(vcpufd, KVM_SET_REGS, &kregs); if (ret == -1) { - perror("KVM: KVM_SET_REGS"); + perror("KVM: KVM_GET_REGS"); leavedos_main(99); } @@ -1133,8 +872,18 @@ static unsigned int kvm_run(void) KVM is re-entered asking it to exit when interrupt injection is possible, then it exits with this code. This only happens if a signal occurs during execution of the monitor code in kvmmon.S. - 4. KVM_EXIT_MMIO: when attempting to write to ROM or r/w from/to MMIO + 4. ret==-1 and errno == EFAULT: this can happen if code in vgaemu.c + calls mprotect in parallel and the TLB is out of sync with the + actual page tables; if this happen we retry and it should not happen + again since the KVM exit/entry makes everything sync'ed. */ + if (mprotected_kvm) { // case 4 + mprotected_kvm = 0; + if (ret == -1 && errn == EFAULT) { + ret = ioctl(vcpufd, KVM_RUN, NULL); + errn = errno; + } + } if (ret != 0 && ret != -1) error("KVM: strange return %i, errno=%i\n", ret, errn); if (ret == -1 && errn == EINTR) { @@ -1144,7 +893,7 @@ static unsigned int kvm_run(void) exit_reason = KVM_EXIT_INTR; break; } else if (ret != 0) { - error("KVM: KVM_RUN failed: %s\n", strerror(errn)); + error("KVM: KVM_RUN failed: %s", strerror(errn)); leavedos_main(99); } @@ -1152,46 +901,6 @@ static unsigned int kvm_run(void) case KVM_EXIT_HLT: exit_reason = KVM_EXIT_HLT; break; - case KVM_EXIT_MMIO: - /* for ROM: simply ignore the write and continue */ - if (memcheck_is_rom(run->mmio.phys_addr)) - break; - - /* from the KVM api.txt: "the corresponding operations are complete - (and guest state is consistent) only after userspace has re-entered - the kernel with KVM_RUN. The kernel side will first finish - incomplete operations and then check for pending signals." */ - kvm_set_immediate_exit(1); - do { - dosaddr_t addr = (dosaddr_t)run->mmio.phys_addr; - unsigned char *data = run->mmio.data; - if (run->mmio.is_write) { - switch(run->mmio.len) { - case 1: write_byte(addr, data[0]); break; - case 2: write_word(addr, *(uint16_t*)data); break; - case 4: write_dword(addr, *(uint32_t*)data); break; - case 8: write_qword(addr, *(uint64_t*)data); break; - } - } else { - switch(run->mmio.len) { - case 1: data[0] = read_byte(addr); break; - case 2: *(uint16_t*)data = read_word(addr); break; - case 4: *(uint32_t*)data = read_dword(addr); break; - case 8: *(uint64_t*)data = read_qword(addr); break; - } - } - ret = ioctl(vcpufd, KVM_RUN, NULL); - /* read-modify-write instructions give two KVM_EXIT_MMIO - exits in a row before the signal exit */ - } while (ret == 0 && run->exit_reason == KVM_EXIT_MMIO); - assert(ret == -1 && errno == EINTR); - kvm_set_immediate_exit(0); - /* going to emulate some instructions */ - if (!kvm_post_run(regs, &kregs)) - break; - saved_regs = *regs; - exit_reason = KVM_EXIT_MMIO; - break; case KVM_EXIT_IRQ_WINDOW_OPEN: run->request_interrupt_window = !run->ready_for_interrupt_injection; if (run->request_interrupt_window || !run->if_flag) break; @@ -1233,12 +942,8 @@ static void kvm_vme_tf_popf_fixup(struct vm86_regs *regs) * We check for popf and assume it tried to clear TF. * */ if (READ_BYTE(SEGOFF2LINEAR(regs->cs, regs->eip - 1)) == 0x9d) { - if (!config.test_mode) { - error("KVM: applying TF fixup\n"); - regs->eflags &= ~X86_EFLAGS_TF; - } else { - error("KVM: not applying TF fixup (test mode)\n"); - } + error("KVM: applying TF fixup\n"); + regs->eflags &= ~X86_EFLAGS_TF; } } @@ -1251,9 +956,6 @@ int kvm_vm86(struct vm86_struct *info) regs = &monitor->regs; *regs = info->regs; -#if 0 - memcpy(&monitor->fpstate, &vm86_fpu_state, sizeof(vm86_fpu_state)); -#endif monitor->int_revectored = info->int_revectored; monitor->tss.esp0 = offsetof(struct monitor, regs) + sizeof(monitor->regs); @@ -1261,7 +963,7 @@ int kvm_vm86(struct vm86_struct *info) regs->eflags |= X86_EFLAGS_FIXED | X86_EFLAGS_VM | X86_EFLAGS_IF; do { - exit_reason = kvm_run(); + exit_reason = kvm_run(regs); vm86_ret = VM86_SIGNAL; if (exit_reason != KVM_EXIT_HLT) break; @@ -1281,24 +983,21 @@ int kvm_vm86(struct vm86_struct *info) info->regs = *regs; info->regs.eflags |= X86_EFLAGS_IOPL; -#if 0 - /* we do not update fpstate for performance reasons */ - memcpy(&vm86_fpu_state, &monitor->fpstate, sizeof(vm86_fpu_state)); -#endif if (vm86_ret == VM86_SIGNAL && exit_reason == KVM_EXIT_HLT) { unsigned trapno = (regs->orig_eax >> 16) & 0xff; unsigned err = regs->orig_eax & 0xffff; + if (trapno == 0x0e && + (vga_emu_fault(monitor->cr2, err, NULL) == True || ( + config.cpu_vm_dpmi == CPUVM_EMU && !config.cpusim && + e_handle_pagefault(monitor->cr2, err, NULL)))) + return vm86_ret; vm86_fault(trapno, err, monitor->cr2); - } else if (exit_reason == KVM_EXIT_MMIO) { - dosaddr_t addr = (dosaddr_t)run->mmio.phys_addr; - if (vga.inst_emu && vga_access(addr, addr)) - instr_emu_sim(NULL, 0, VGA_EMU_INST_EMU_COUNT); } return vm86_ret; } /* Emulate do_dpmi_control() using KVM */ -int kvm_dpmi(cpuctx_t *scp) +int kvm_dpmi(sigcontext_t *scp) { struct vm86_regs *regs; int ret; @@ -1306,9 +1005,7 @@ int kvm_dpmi(cpuctx_t *scp) monitor->tss.esp0 = offsetof(struct monitor, regs) + offsetof(struct vm86_regs, es); -#if 0 - memcpy(&monitor->fpstate, &vm86_fpu_state, sizeof(vm86_fpu_state)); -#endif + regs = &monitor->regs; do { regs->eax = _eax; @@ -1333,7 +1030,7 @@ int kvm_dpmi(cpuctx_t *scp) X86_EFLAGS_IF); regs->eflags |= X86_EFLAGS_FIXED; - exit_reason = kvm_run(); + exit_reason = kvm_run(regs); _eax = regs->eax; _ebx = regs->ebx; @@ -1354,16 +1051,11 @@ int kvm_dpmi(cpuctx_t *scp) _eflags = regs->eflags; -#if 0 - /* we do not update fpstate for performance reasons */ - memcpy(&vm86_fpu_state, &monitor->fpstate, sizeof(vm86_fpu_state)); -#endif - ret = DPMI_RET_DOSEMU; /* mirroring sigio/sigalrm */ if (exit_reason == KVM_EXIT_HLT) { /* orig_eax >> 16 = exception number */ /* orig_eax & 0xffff = error code */ - _cr2 = monitor->cr2; + _cr2 = (uintptr_t)MEM_BASE32(monitor->cr2); _trapno = (regs->orig_eax >> 16) & 0xff; _err = regs->orig_eax & 0xffff; if (_trapno > 0x10) { @@ -1374,7 +1066,6 @@ int kvm_dpmi(cpuctx_t *scp) } if (_trapno == 0x10) { -#if 0 struct kvm_fpu fpu; ioctl(vcpufd, KVM_GET_FPU, &fpu); #ifdef __x86_64__ @@ -1395,21 +1086,20 @@ int kvm_dpmi(cpuctx_t *scp) __fpstate->cssel = _cs; __fpstate->dataoff = fpu.last_dp; __fpstate->datasel = _ds; -#endif - print_exception_info(scp); #endif dbug_printf("coprocessor exception, calling IRQ13\n"); - raise_fpu_irq(); + print_exception_info(scp); + pic_request(PIC_IRQ13); ret = DPMI_RET_DOSEMU; - } else - ret = DPMI_RET_FAULT; - } else if (exit_reason == KVM_EXIT_MMIO) { - dosaddr_t addr = (dosaddr_t)run->mmio.phys_addr; - if (vga.inst_emu && vga_access(addr, addr)) - instr_emu_sim(scp, 1, VGA_EMU_INST_EMU_COUNT); - ret = DPMI_RET_CLIENT; + } else if (_trapno == 0x0e && + (vga_emu_fault(monitor->cr2, _err, scp) == True || ( + config.cpu_vm == CPUVM_EMU && !config.cpusim && + e_handle_pagefault(monitor->cr2, _err, scp)))) + ret = dpmi_check_return(); + else + ret = dpmi_fault(scp); } - } while (!signal_pending() && ret == DPMI_RET_CLIENT); + } while (ret == DPMI_RET_CLIENT); return ret; } diff --git a/src/base/emu-i386/kvmmon.S b/src/base/emu-i386/kvmmon.S index fd3e64b..a911217 100644 --- a/src/base/emu-i386/kvmmon.S +++ b/src/base/emu-i386/kvmmon.S @@ -23,8 +23,6 @@ .section .text .code32 - .global _start -_start: // dummy .globl kvm_mon_start kvm_mon_start: @@ -57,28 +55,12 @@ kvm_mon_main: push %edx push %ecx push %ebx - /* cr3: mark as 0 to not reload by default */ - pushl $0 mov %cr2,%eax push %eax -#if 0 - subl $0x200,%esp - fxsave (%esp) -#endif .globl kvm_mon_hlt kvm_mon_hlt: hlt -#if 0 - fxrstor (%esp) - addl $0x200,%esp -#endif pop %eax - pop %eax - or %eax,%eax - jz skip_cr3 - /* flush TLB by reloading cr3 if nonzero (set by mprotect_kvm()) */ - mov %eax,%cr3 -skip_cr3: pop %ebx pop %ecx pop %edx diff --git a/src/base/emu-i386/kvmmon_offsets.h b/src/base/emu-i386/kvmmon_offsets.h deleted file mode 100644 index 29bb2ba..0000000 --- a/src/base/emu-i386/kvmmon_offsets.h +++ /dev/null @@ -1,3 +0,0 @@ -extern const unsigned kvm_mon_start; -extern const unsigned kvm_mon_hlt; -extern const unsigned kvm_mon_end; diff --git a/src/base/emu-i386/simx86/Makefile b/src/base/emu-i386/simx86/Makefile index 8db3da2..eacb759 100644 --- a/src/base/emu-i386/simx86/Makefile +++ b/src/base/emu-i386/simx86/Makefile @@ -10,13 +10,11 @@ include $(top_builddir)/Makefile.conf EM86DIR=$(REALTOPDIR)/src/emu-i386/simx86 EM86FLG=-Dlinux -DDOSEMU -ifeq ($(X86_JIT),1) -JITFILES = codegen-x86.c fp87-x86.c sigsegv.c cpatch.c trees.c -endif -CFILES = interp.c cpu-emu.c modrm-gen.c $(JITFILES) \ - codegen-sim.c fp87-sim.c modrm-sim.c protmode.c \ + +CFILES = trees.c interp.c cpu-emu.c modrm-gen.c codegen-x86.c fp87-x86.c \ + codegen-sim.c fp87-sim.c modrm-sim.c protmode.c sigsegv.c cpatch.c \ memory.c tables.c -ALL_CPPFLAGS +=-I$(EM86DIR) $(EM86FLG) +ALL_CPPFLAGS +=-I$(EM86DIR) $(EM86FLG) -mno-red-zone #ALL_CPPFLAGS +=-DNOJUMPS diff --git a/src/base/emu-i386/simx86/codegen-arch.h b/src/base/emu-i386/simx86/codegen-arch.h index 0361faa..81ed1da 100644 --- a/src/base/emu-i386/simx86/codegen-arch.h +++ b/src/base/emu-i386/simx86/codegen-arch.h @@ -4,7 +4,6 @@ * for details see file COPYING in the DOSEMU distribution */ -#include "codegen.h" #include "codegen-sim.h" #ifdef HOST_ARCH_X86 #include "codegen-x86.h" diff --git a/src/base/emu-i386/simx86/codegen-sim.c b/src/base/emu-i386/simx86/codegen-sim.c index b49ba55..b0f1dd3 100644 --- a/src/base/emu-i386/simx86/codegen-sim.c +++ b/src/base/emu-i386/simx86/codegen-sim.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ @@ -73,8 +73,8 @@ void (*Gen)(int op, int mode, ...); void (*AddrGen)(int op, int mode, ...); -unsigned int (*CloseAndExec)(unsigned int PC, int mode); -static unsigned int CloseAndExec_sim(unsigned int PC, int mode); +unsigned int (*CloseAndExec)(unsigned int PC, int mode, int ln); +static unsigned int CloseAndExec_sim(unsigned int PC, int mode, int ln); int UseLinker = 0; @@ -82,7 +82,7 @@ static unsigned int P0 = (unsigned)-1; ///////////////////////////////////////////////////////////////////////////// -#define Offs_From_Arg() (signed char)(va_arg(ap,int)) +#define Offs_From_Arg() (char)(va_arg(ap,int)) /* WARNING - these are signed char offsets, NOT pointers! */ char OVERR_DS=Ofs_XDS, OVERR_SS=Ofs_XSS; @@ -357,7 +357,7 @@ void InitGen_sim(void) void AddrGen_sim(int op, int mode, ...) { va_list ap; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; if (debug_level('e')) t0 = GETTSC(); #endif @@ -367,7 +367,7 @@ void AddrGen_sim(int op, int mode, ...) case A_DI_0: // base(32), imm case A_DI_1: { // base(32), {imm}, reg, {shift} long idsp=0; - signed char ofs; + char ofs; ofs = va_arg(ap,int); if (mode & MLEA) { // discard base reg AR1.d = 0; // ofs = Ofs_RZERO; @@ -395,7 +395,7 @@ void AddrGen_sim(int op, int mode, ...) break; case A_DI_2: { // base(32), {imm}, reg, reg, {shift} long idsp=0; - signed char ofs; + char ofs; ofs = va_arg(ap,int); if (mode & MLEA) { // discard base reg AR1.d = 0; // ofs = Ofs_RZERO; @@ -450,7 +450,7 @@ void AddrGen_sim(int op, int mode, ...) break; } va_end(ap); -#if PROFILE +#ifdef PROFILE if (debug_level('e')) GenTime += (GETTSC() - t0); #endif } @@ -459,7 +459,7 @@ void Gen_sim(int op, int mode, ...) { va_list ap; uint32_t S1, S2; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; if (debug_level('e')) t0 = GETTSC(); #endif @@ -547,7 +547,7 @@ void Gen_sim(int op, int mode, ...) int v = va_arg(ap, int); GTRACE3("L_IMM",o,0xff,v); if (mode & MBYTE) { - CPUBYTE(o) = (signed char)v; + CPUBYTE(o) = (char)v; } else if (mode & DATA16) { CPUWORD(o) = (short)v; @@ -560,7 +560,7 @@ void Gen_sim(int op, int mode, ...) int v = va_arg(ap, int); GTRACE3("L_IMM_R1",0xff,0xff,v); if (mode & MBYTE) { - DR1.b.bl = (signed char)v; + DR1.b.bl = (char)v; } else if (mode & DATA16) { DR1.w.l = (short)v; @@ -2022,7 +2022,7 @@ void Gen_sim(int op, int mode, ...) } break; case AAM: { - signed char tmp = DR1.b.bl; + char tmp = DR1.b.bl; int base = Offs_From_Arg(); DR1.b.bh = tmp / base; RFL.RES.d = DR1.bs.bl = tmp % base; @@ -2044,24 +2044,26 @@ void Gen_sim(int op, int mode, ...) break; case O_PUSH: { - unsigned long stackm = CPULONG(Ofs_STACKM); GTRACE0("O_PUSH"); if (mode & DATA16) { AR2.d = CPULONG(Ofs_XSS); SR1.d = CPULONG(Ofs_ESP) - 2; - SR1.d &= stackm; + SR1.d &= CPULONG(Ofs_STACKM); write_word(AR2.d + SR1.d, DR1.w.l); + CPULONG(Ofs_ESP) = SR1.d; } else { + long stackm = CPULONG(Ofs_STACKM); + long tesp; AR2.d = CPULONG(Ofs_XSS); - SR1.d = CPULONG(Ofs_ESP) - 4; + SR1.d = (tesp = CPULONG(Ofs_ESP)) - 4; SR1.d &= stackm; write_dword(AR2.d + SR1.d, DR1.d); - } -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - SR1.d |= (CPULONG(Ofs_ESP) & ~stackm); +#if 0 /* keep high 16-bits of ESP in small-stack mode */ + SR1.d |= (tesp & ~stackm); #endif - CPULONG(Ofs_ESP) = SR1.d; + CPULONG(Ofs_ESP) = SR1.d; + } if (debug_level('e')>3) dbug_printf("(V) %08x\n",DR1.d); } break; @@ -2074,23 +2076,19 @@ void Gen_sim(int op, int mode, ...) case O_PUSH2: { signed char o = Offs_From_Arg(); - unsigned long stackm = CPULONG(Ofs_STACKM); GTRACE1("O_PUSH2",o); if (mode & DATA16) { DR1.w.l = CPUWORD(o); SR1.d -= 2; - SR1.d &= stackm; + SR1.d &= CPULONG(Ofs_STACKM); write_word(AR2.d + SR1.d, DR1.w.l); } else { DR1.d = CPULONG(o); SR1.d -= 4; - SR1.d &= stackm; + SR1.d &= CPULONG(Ofs_STACKM); write_dword(AR2.d + SR1.d, DR1.d); } -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - SR1.d |= (CPULONG(Ofs_ESP) & ~stackm); -#endif if (debug_level('e')>3) dbug_printf("(V) %08x\n",DR1.d); } break; @@ -2100,7 +2098,6 @@ void Gen_sim(int op, int mode, ...) break; case O_PUSH2F: { - unsigned long stackm = CPULONG(Ofs_STACKM); int ftmp; GTRACE0("O_PUSHF"); FlagSync_All(); @@ -2112,42 +2109,36 @@ void Gen_sim(int op, int mode, ...) AR2.d = CPULONG(Ofs_XSS); SR1.d = CPULONG(Ofs_ESP); if (mode & DATA16) { - SR1.d = (SR1.d - 2) & stackm; + SR1.d = (SR1.d - 2) & CPULONG(Ofs_STACKM); write_word(AR2.d + SR1.d, ftmp); } else { - SR1.d = (SR1.d - 4) & stackm; + SR1.d = (SR1.d - 4) & CPULONG(Ofs_STACKM); write_dword(AR2.d + SR1.d, ftmp); } -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - SR1.d |= (CPULONG(Ofs_ESP) & ~stackm); -#endif CPULONG(Ofs_ESP) = SR1.d; if (debug_level('e')>3) dbug_printf("(V) %08x\n",ftmp); } break; case O_PUSHI: { int v = va_arg(ap, int); - unsigned long stackm = CPULONG(Ofs_STACKM); GTRACE3("O_PUSHI",0xff,0xff,v); if (mode & DATA16) { DR1.w.l = (short)v; AR2.d = CPULONG(Ofs_XSS); SR1.d = CPULONG(Ofs_ESP) - 2; - SR1.d &= stackm; + SR1.d &= CPULONG(Ofs_STACKM); write_word(AR2.d + SR1.d, DR1.w.l); + CPULONG(Ofs_ESP) = SR1.d; } else { DR1.d = v; AR2.d = CPULONG(Ofs_XSS); SR1.d = CPULONG(Ofs_ESP) - 4; - SR1.d &= stackm; + SR1.d &= CPULONG(Ofs_STACKM); write_dword(AR2.d + SR1.d, DR1.d); + CPULONG(Ofs_ESP) = SR1.d; } -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - SR1.d |= (CPULONG(Ofs_ESP) & ~stackm); -#endif - CPULONG(Ofs_ESP) = SR1.d; } break; case O_POP: { @@ -2163,21 +2154,23 @@ void Gen_sim(int op, int mode, ...) #ifdef STACK_WRAP_MP /* mask after incrementing */ SR1.d &= stackm; #endif + CPULONG(Ofs_ESP) = SR1.d; } else { + long tesp; AR2.d = CPULONG(Ofs_XSS); - SR1.d = CPULONG(Ofs_ESP); + SR1.d = tesp = CPULONG(Ofs_ESP); SR1.d &= stackm; DR1.d = read_dword(AR2.d + SR1.d); SR1.d += 4 + imm16; #ifdef STACK_WRAP_MP /* mask after incrementing */ SR1.d &= stackm; #endif - } #ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - SR1.d |= (CPULONG(Ofs_ESP) & ~stackm); + SR1.d |= (tesp & ~stackm); #endif - CPULONG(Ofs_ESP) = SR1.d; + CPULONG(Ofs_ESP) = SR1.d; + } if (debug_level('e')>3) dbug_printf("(V) %08x\n",DR1.d); } break; @@ -2205,10 +2198,10 @@ void Gen_sim(int op, int mode, ...) if (!(mode & MPOPRM)) CPULONG(o) = DR1.d; SR1.d += 4; - } #ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - SR1.d |= (CPULONG(Ofs_ESP) & ~stackm); + SR1.d |= (CPULONG(Ofs_ESP) & ~stackm); #endif + } if (debug_level('e')>3) dbug_printf("(V) %08x\n",DR1.d); } break; @@ -2230,6 +2223,7 @@ void Gen_sim(int op, int mode, ...) #ifdef STACK_WRAP_MP /* mask after incrementing */ SR1.d &= stackm; #endif + CPULONG(Ofs_ESP) = SR1.d; } else { SR1.d = CPULONG(Ofs_EBP); @@ -2241,18 +2235,17 @@ void Gen_sim(int op, int mode, ...) #ifdef STACK_WRAP_MP /* mask after incrementing */ SR1.d &= stackm; #endif - } #ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - SR1.d |= (CPULONG(Ofs_ESP) & ~stackm); + SR1.d |= (CPULONG(Ofs_ESP) & ~stackm); #endif - CPULONG(Ofs_ESP) = SR1.d; - } + CPULONG(Ofs_ESP) = SR1.d; + } } break; case O_INT: { unsigned char intno = va_arg(ap, int); // Check bitmap, GPF if revectored - if (test_bit(intno, &TheCPU.int_revectored)) { + if (is_revectored(intno, &TheCPU.int_revectored)) { P0 = va_arg(ap, dosaddr_t); TheCPU.err = EXCP0D_GPF; } @@ -2326,39 +2319,10 @@ void Gen_sim(int op, int mode, ...) TR1.d = possible; Gen_sim(O_MOVS_MovD,mode); /* emulate overflow */ - if (df == -1) { - if(SR1.d == minofs) { - AR1.d -= df*0x10000; - SR1.d = 0xffff; - DR2.d -= minofs; - if (DR2.d > 0) - DR2.d -= 1; - else - DR2.d = 0xffff; - } - if(DR2.d == minofs) { - AR2.d -= df*0x10000; - DR2.d = 0xffff; - SR1.d -= minofs; - if (SR1.d > 0) - SR1.d -= 1; - else - SR1.d = 0xffff; - } - } else { - if(SR1.d == 0x10000 - minofs) { - AR1.d -= df*0x10000; - SR1.d = 0; - DR2.d += minofs; - DR2.d &= 0xffff; - } - if(DR2.d == 0x10000 - minofs) { - AR2.d -= df*0x10000; - DR2.d = 0; - SR1.d += minofs; - SR1.d &= 0xffff; - } - } + if(SR1.d == minofs) + AR1.d -= df*0x10000; + if(DR2.d == minofs) + AR2.d -= df*0x10000; /* do the rest */ TR1.d = i - possible; @@ -2453,7 +2417,6 @@ void Gen_sim(int op, int mode, ...) possible++; TR1.d = possible; Gen_sim(O_MOVS_StoD,mode); - SR1.d = (df == -1 ? 0xffff : 0); AR1.d -= 0x10000*df; TR1.d = i - possible; Gen_sim(O_MOVS_StoD,mode); @@ -2573,7 +2536,7 @@ void Gen_sim(int op, int mode, ...) GTRACE0("O_MOVS_SavA"); if (!(mode&(MREP|MREPNE))) { // %%edx set to DF's increment - DR2.d = (signed char)CPUBYTE(Ofs_DF_INCREMENTS+OPSIZEBIT(mode)); + DR2.d = (char)CPUBYTE(Ofs_DF_INCREMENTS+OPSIZEBIT(mode)); if(mode & MOVSSRC) { if (mode & ADDR16) CPUWORD(Ofs_SI) += DR2.w.l; @@ -2734,20 +2697,20 @@ void Gen_sim(int op, int mode, ...) DR2.d &= 0x1f; } if ((mode & RM_REG) || o1 >= 0x20) { - if ((o1 & ~0x18) == 0x03 || (o1 & ~0x18) == 0x20) { - SET_CF((DR1.d >> DR2.d) & 1); - switch (o1 & 0x18) { - case 0x00: break; - case 0x08: DR1.d |= 1U << DR2.d; break; - case 0x10: DR1.d &= ~(1U << DR2.d); break; - case 0x18: DR1.d ^= 1U << DR2.d; break; - default: break; - } + switch (o1) { + case 0x03: case 0x20: flg = test_bit(DR2.d, &DR1.d); break; + case 0x0b: case 0x28: flg = set_bit(DR2.d, &DR1.d); break; + case 0x13: case 0x30: flg = clear_bit(DR2.d, &DR1.d); break; + case 0x1b: case 0x38: flg = change_bit(DR2.d, &DR1.d); break; + default: flg = 2; } } else { /* add bit offset to effective address */ AR1.d += (mode&DATA16) ? 2*(DR2.d>>4) : 4*(DR2.d>>5); + break; } + if (flg != 2) + SET_CF(flg&1); } break; case O_SHFD: { unsigned char l_r = (unsigned char)va_arg(ap,int)&8; @@ -2808,8 +2771,7 @@ void Gen_sim(int op, int mode, ...) if (shc>1) RFL.mode |= IGNOVF; } break; - case O_RDTSC: { // don't trust this one -#if 0 + case O_RDTSC: { // dont trust this one hitimer_u t0, t1; GTRACE0("O_RDTSC"); t0.td = GETTSC(); @@ -2819,9 +2781,6 @@ void Gen_sim(int op, int mode, ...) } CPULONG(Ofs_EAX) = t0.t.tl; CPULONG(Ofs_EDX) = t0.t.th; -#else - error("rdtsc not implemented\n"); -#endif } break; @@ -2968,7 +2927,7 @@ void Gen_sim(int op, int mode, ...) } } -#if PROFILE +#ifdef PROFILE if (debug_level('e')) GenTime += (GETTSC() - t0); #endif } @@ -2977,13 +2936,13 @@ void Gen_sim(int op, int mode, ...) ///////////////////////////////////////////////////////////////////////////// -static unsigned int CloseAndExec_sim(unsigned int PC, int mode) +static unsigned int CloseAndExec_sim(unsigned int PC, int mode, int ln) { unsigned int ret; if (debug_level('e')>1) { if (TheCPU.sigalrm_pending>0) e_printf("** SIGALRM is pending\n"); if (debug_level('e')>2) { - e_printf("==== Closing sequence at %08x\n", PC); + e_printf("== (%04d) == Closing sequence at %08x\n",ln,PC); } #if defined(SINGLESTEP)||defined(SINGLEBLOCK) dbug_printf("\n%s",e_print_regs()); @@ -3002,11 +2961,12 @@ static unsigned int CloseAndExec_sim(unsigned int PC, int mode) } if (!(CEmuStat & CeS_INHI)) { - if (TheCPU.sigalrm_pending) { + if (signal_pending()) CEmuStat|=CeS_SIGPEND; - TheCPU.sigalrm_pending = 0; - } + TheCPU.sigalrm_pending = 0; } + if (eTimeCorrect >= 0) + TheCPU.EMUtime = GETTSC(); if (P0 == (unsigned)-1) return PC; ret = P0; diff --git a/src/base/emu-i386/simx86/codegen-sim.h b/src/base/emu-i386/simx86/codegen-sim.h index 1b8677a..da4d517 100644 --- a/src/base/emu-i386/simx86/codegen-sim.h +++ b/src/base/emu-i386/simx86/codegen-sim.h @@ -37,6 +37,12 @@ #include "vgaemu.h" +/* If you undefine this, in 16-bit stack mode the high 16 bits of ESP + * will be zeroed after every push/pop operation. There's a small + * possibility of breaking some code, you can easily figure out how. + * For 32-bit stacks, keeping ESP is also a waste of time. */ +#undef KEEP_ESP + ///////////////////////////////////////////////////////////////////////////// typedef union { diff --git a/src/base/emu-i386/simx86/codegen-x86.c b/src/base/emu-i386/simx86/codegen-x86.c index 7dff53c..0cc36f0 100644 --- a/src/base/emu-i386/simx86/codegen-x86.c +++ b/src/base/emu-i386/simx86/codegen-x86.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ @@ -83,19 +83,17 @@ /*************************************************************************** * * Registers on enter: - * ebx/rbx pointer to SynCPU (must not be changed) - * ebp/rbp memory base address (mem_base) - * [esp/rsp] cpu->eflags + * ebx pointer to SynCPU (must not be changed) + * [esp] cpu->eflags * - * Registers used by the 32/64-bit machine: + * Registers used by the 32-bit machine: * eax scratch, data - * ebx/rbx pointer to SynCPU (must not be changed) + * ebx pointer to SynCPU (must not be changed) * ecx scratch, address/count * edx scratch, data * esi scratch, address * edi memory/register address - * ebp/rbp memory base address (mem_base) - * esp/rsp not modified + * esp not modified * flags modified * * Registers on exit: @@ -116,11 +114,10 @@ #include "mapping.h" #ifdef HOST_ARCH_X86 #include "codegen-x86.h" -#include "cpatch.h" static void Gen_x86(int op, int mode, ...); static void AddrGen_x86(int op, int mode, ...); -static unsigned int CloseAndExec_x86(unsigned int PC, int mode); +static unsigned int CloseAndExec_x86(unsigned int PC, int mode, int ln); hitimer_u TimeStartExec; static TNode *LastXNode = NULL; @@ -175,6 +172,7 @@ void InitGen_x86(void) AddrGen = AddrGen_x86; CloseAndExec = CloseAndExec_x86; UseLinker = USE_LINKER; + InitTrees(); } @@ -195,7 +193,7 @@ static unsigned char *CodeGen(unsigned char *CodePtr, unsigned char *BaseGenBuf, unsigned char * CpTemp; int mode = IG->mode; int rcod; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; if (debug_level('e')) t0 = GETTSC(); #endif @@ -291,6 +289,8 @@ static unsigned char *CodeGen(unsigned char *CodePtr, unsigned char *BaseGenBuf, G4M(0x0f,0xb7,0x43,IG->p0,Cp); // shll $4,%%eax G3M(0xc1,0xe0,0x04,Cp); + // addl Ofs_MEMBASE(%%ebx),%%eax + G3M(0x03,0x43,Ofs_MEMBASE,Cp); // movl %%eax,ofs(%%ebx) G3M(0x89,0x43,IG->p1,Cp); // addl $0xffff,%eax @@ -417,8 +417,8 @@ static unsigned char *CodeGen(unsigned char *CodePtr, unsigned char *BaseGenBuf, break; case L_LXS1: { - // mov{wl} (%%edi,%%ebp,1),%%{e}ax - Gen66(mode,Cp); G3M(0x8b,0x04,0x2f,Cp); + // mov{wl} (%%edi),%%{e}ax + Gen66(mode,Cp); G2M(0x8b,0x07,Cp); // mov{wl} %%{e}ax,offs(%%ebx) Gen66(mode,Cp); G3M(0x89,0x43,IG->p0,Cp); // leal {2|4}(%%edi),%%edi @@ -426,12 +426,14 @@ static unsigned char *CodeGen(unsigned char *CodePtr, unsigned char *BaseGenBuf, } break; case L_LXS2: { /* real mode segment base from segment value */ - // movzwl (%%edi,%%ebp,1),%%eax - G4M(0x0f,0xb7,0x04,0x2f,Cp); + // movzwl (%%edi),%%eax + G3M(0x0f,0xb7,0x07,Cp); // movw %%ax,ofs(%%ebx) G4M(0x66,0x89,0x43,IG->p0,Cp); // shll $4,%%eax G3M(0xc1,0xe0,0x04,Cp); + // addl Ofs_MEMBASE(%%ebx),%%eax + G3M(0x03,0x43,Ofs_MEMBASE,Cp); // movl %%eax,ofs(%%ebx) G3M(0x89,0x43,IG->p1,Cp); // addl $0xffff,%eax @@ -447,15 +449,15 @@ static unsigned char *CodeGen(unsigned char *CodePtr, unsigned char *BaseGenBuf, case L_DI_R1: if (mode&(MBYTE|MBYTX)) { - G3(0x2f048a,Cp); G1(0x90,Cp); + G2(0x078a,Cp); G1(0x90,Cp); } else if (mode&DATA16) { - G1(0x66,Cp); G3(0x2f048b,Cp); + G1(0x66,Cp); G2(0x078b,Cp); } else { - G3(0x2f048b,Cp); G1(0x90,Cp); + G2(0x078b,Cp); G1(0x90,Cp); } - G2(0x9090,Cp); + G3(0x909090,Cp); break; case S_DI: if (mode&MBYTE) { @@ -1126,21 +1128,9 @@ shrot0: // 16-bit stack seg w/underflow (RM) // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movw %%ax,(%%edx,%%ebp,1) - 0x66,0x89,0x04,0x2a, + // movw %%ax,(%%esi,%%ecx,1) + 0x66,0x89,0x04,0x0e, // do 16-bit PM apps exist which use a 32-bit stack seg? -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, -#endif // movl %%ecx,Ofs_ESP(%%ebx) 0x89,0x4b,Ofs_ESP }; @@ -1153,11 +1143,9 @@ shrot0: 0x8d,0x49,0xfc, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movl %%eax,(%%edx,%%ebp,1) - 0x89,0x04,0x2a, -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ + // movl %%eax,(%%esi,%%ecx,1) + 0x89,0x04,0x0e, +#if 0 /* keep high 16-bits of ESP in small-stack mode */ // movl StackMask(%%ebx),%%edx 0x8b,0x53,Ofs_STACKM, // notl %%edx @@ -1182,7 +1170,7 @@ shrot0: // movl Ofs_ESP(%%ebx),%%ecx 0x8b,0x4b,Ofs_ESP, // movl Ofs_XSS(%%ebx),%%esi - 0x8b,0x73,Ofs_XSS, + 0x8b,0x73,Ofs_XSS }; GNX(Cp, pseq, sizeof(pseq)); } break; @@ -1195,20 +1183,8 @@ shrot0: 0x8d,0x49,0xfe, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movw %%ax,(%%edx,%%ebp,1) - 0x66,0x89,0x04,0x2a, -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, -#endif + // movw %%ax,(%%esi,%%ecx,1) + 0x66,0x89,0x04,0x0e, }; const unsigned char pseq32[] = { // movl offs(%%ebx),%%eax @@ -1217,20 +1193,8 @@ shrot0: 0x8d,0x49,0xfc, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movl %%eax,(%%edx,%%ebp,1) - 0x89,0x04,0x2a, -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, -#endif + // movl %%eax,(%%esi,%%ecx,1) + 0x89,0x04,0x0e, }; const unsigned char *p; unsigned char *q; @@ -1267,20 +1231,7 @@ shrot0: // orw %%dx,%%ax 0x66,0x09,0xd0, }; -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - const unsigned char pseqpost[] = { - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, - }; -#endif - unsigned char *q=Cp; - GNX(Cp, pseqpre, sizeof(pseqpre)); + unsigned char *q=Cp; GNX(Cp, pseqpre, sizeof(pseqpre)); if (mode&DATA16) q[8] = 0xfe; /* use -2 in lea ins */ #if 0 // unused "extended PVI", if used should move to separate op if (!V86MODE() && IOPL < 3 && (TheCPU.cr[4] & CR4_PVI)) { @@ -1308,20 +1259,15 @@ shrot0: G4M(0x13,0xc1,0xd0,0x0a,Cp); } #endif - // leal (%%esi,%%ecx,1),%%edx - G3M(0x8d,0x14,0x0e,Cp); if (mode&DATA16) { - // movw %%ax,(%%edx,%%ebp,1) - G4M(0x66,0x89,0x04,0x2a,Cp); + // movw %%ax,(%%esi,%%ecx,1) + G4M(0x66,0x89,0x04,0x0e,Cp); } else { // andl RETURN_MASK|EFLAGS_IF,%%eax G1(0x25,Cp); G4(RETURN_MASK|EFLAGS_IF,Cp); - // movl %%eax,(%%edx,%%ebp,1) - G3M(0x89,0x04,0x2a,Cp); + // movl %%eax,(%%esi,%%ecx,1) + G3M(0x89,0x04,0x0e,Cp); } -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - GNX(Cp, pseqpost, sizeof(pseqpost)); -#endif // movl %%ecx,Ofs_ESP(%%ebx) G3M(0x89,0x4b,Ofs_ESP,Cp); } break; @@ -1338,20 +1284,8 @@ shrot0: 0x8d,0x49,0xfe, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movw %%ax,(%%edx,%%ebp,1) - 0x66,0x89,0x04,0x2a, -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, -#endif + // movw %%ax,(%%esi,%%ecx,1) + 0x66,0x89,0x04,0x0e, // movl %%ecx,Ofs_ESP(%%ebx) 0x89,0x4b,Ofs_ESP }; @@ -1366,20 +1300,8 @@ shrot0: 0x8d,0x49,0xfc, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movw %eax,(%%edx,%%ebp,1) - 0x89,0x04,0x2a, -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, -#endif + // movl %%eax,(%%esi,%%ecx,1) + 0x89,0x04,0x0e, // movl %%ecx,Ofs_ESP(%%ebx) 0x89,0x4b,Ofs_ESP }; @@ -1404,25 +1326,13 @@ shrot0: 0x8b,0x4b,Ofs_ESP, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movw (%%edx,%%ebp,1),%%ax, - 0x66,0x8b,0x04,0x2a, + // movw (%%esi,%%ecx,1),%%ax + 0x66,0x8b,0x04,0x0e, // leal 2(%%ecx),%%ecx -/*10*/ 0x8d,0x89,0x02,0x00,0x00,0x00, +/*0d*/ 0x8d,0x89,0x02,0x00,0x00,0x00, #ifdef STACK_WRAP_MP /* mask after incrementing */ // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, -#endif -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, #endif // movl %%ecx,Ofs_ESP(%%ebx) 0x89,0x4b,Ofs_ESP @@ -1434,12 +1344,10 @@ shrot0: 0x8b,0x4b,Ofs_ESP, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movl (%%edx,%%ebp,1),%%eax - 0x90,0x8b,0x04,0x2a, + // movl (%%esi,%%ecx,1),%%eax + 0x90,0x8b,0x04,0x0e, // leal 4(%%ecx),%%ecx -/*10*/ 0x8d,0x89,0x04,0x00,0x00,0x00, +/*0d*/ 0x8d,0x89,0x04,0x00,0x00,0x00, #ifdef STACK_WRAP_MP /* mask after incrementing */ // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, @@ -1467,7 +1375,7 @@ shrot0: q = Cp; GNX(Cp, p, sz); if (mode&MRETISP) /* adjust stack after pop */ - *(int32_t *)(q+0x12) += IG->p0; + *(int32_t *)(q+0xf) += IG->p0; } break; /* POP derived (sub-)sequences: */ @@ -1485,34 +1393,20 @@ shrot0: const unsigned char pseq16[] = { // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movw (%%edx,%%ebp,1),%%ax - 0x66,0x8b,0x04,0x2a, + // movw (%%esi,%%ecx,1),%%ax + 0x66,0x8b,0x04,0x0e, // movw %%ax,offs(%%ebx) -/*0a*/ 0x66,0x89,0x43,0x00, +/*07*/ 0x66,0x89,0x43,0x00, // leal 2(%%ecx),%%ecx - 0x8d,0x49,0x02, -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, -#endif + 0x8d,0x49,0x02 }; const unsigned char pseq32[] = { // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movl (%%edx,%%ebp,1),%%eax - 0x90,0x8b,0x04,0x2a, + // movl (%%esi,%%ecx,1),%%eax + 0x90,0x8b,0x04,0x0e, // movl %%eax,offs(%%ebx) -/*0a*/ 0x90,0x89,0x43,0x00, +/*07*/ 0x90,0x89,0x43,0x00, // leal 4(%%ecx),%%ecx 0x8d,0x49,0x04, #ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ @@ -1535,16 +1429,17 @@ shrot0: // first do address calculation, then pop, // then store data, and last adjust stack q=Cp; GNX(Cp, p, sz); - q[0x0d] = IG->p0; + q[0x0a] = IG->p0; if (mode&MPOPRM) { // NOP the register write, save ecx into esi // which is preserved in CPatches - *(uint32_t *)(q+0x0a) = 0x90909090; + *(uint32_t *)(q+7) = 0x90909090; // Use leal {2|4}(%%ecx),%%esi - q[0x0f] = 0x71; + q[0xc] = 0x71; #ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // use orl %%edx,%%esi - q[sz-1] = 0xd6; + if (!(mode&DATA16)) + // use orl %%edx,%%esi + q[sz-1] = 0xd6; #endif } } break; @@ -1562,10 +1457,8 @@ shrot0: 0x8b,0x73,Ofs_XSS, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movw (%%edx,%%ebp,1),%%ax - 0x66,0x8b,0x04,0x2a, + // movw (%%esi,%%ecx,1),%%ax + 0x66,0x8b,0x04,0x0e, // movw %%ax,Ofs_BP(%%ebx) 0x66,0x89,0x43,Ofs_BP, // leal 2(%%ecx),%%ecx @@ -1573,16 +1466,6 @@ shrot0: #ifdef STACK_WRAP_MP /* mask after incrementing */ // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, -#endif -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, #endif // movl %%ecx,Ofs_ESP(%%ebx) 0x89,0x4b,Ofs_ESP @@ -1594,10 +1477,8 @@ shrot0: 0x8b,0x73,Ofs_XSS, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edx - 0x8d,0x14,0x0e, - // movl (%%edx,%%ebp,1),%%eax - 0x8b,0x04,0x2a, + // movl (%%esi,%%ecx,1),%%eax + 0x8b,0x04,0x0e, // movl %%eax,Ofs_EBP(%%ebx) 0x89,0x43,Ofs_EBP, // leal 4(%%ecx),%%ecx @@ -1628,7 +1509,7 @@ shrot0: case O_INT: { unsigned char intno = IG->p0; int jpc = IG->p1; - // Check bitmap, GPF if revectored, else use intno*4 + // Check bitmap, GPF if revectored, else use mem_base+intno*4 // bt intno,Ofs_int_revectored(%ebx) // Code offset of TheCPU.int_revectored.__map[intno>>5] // as Ofs_int_revectored[intno>>3] aligned to 4. @@ -1643,15 +1524,14 @@ shrot0: // movl {exit_addr},%%eax; pop %%edx; ret G1(0xb8,Cp); G4(jpc,Cp); G2M(0x5a,0xc3,Cp); // address to call in edi - // movl $(inum*4), %edi - G1(0xbf,Cp); G4(intno*4, Cp); + // movl $(MEM_BASE+inum*4), %edi + G1(0xbf,Cp); G4(TheCPU.mem_base+intno*4, Cp); break; } case O_MOVS_SetA: { /* use edi for loads unless MOVSDST or REP is set */ unsigned char modrm = mode&(MREP|MREPNE|MOVSDST) ? 0x73 : 0x7b; - unsigned char modrm2 = mode&(MREP|MREPNE|MOVSDST) ? 0xee : 0xef; if (mode&ADDR16) { /* The CX load has to be before the address reloads */ if (mode&(MREP|MREPNE)) { @@ -1690,10 +1570,6 @@ shrot0: } // addl OVERR_DS(%%ebx),%%e[sd]i G3M(0x03,modrm,IG->ovds,Cp); - if (mode&(MREP|MREPNE)) { - // addl %%[re]bp,%%[re][sd]i - Gen48(Cp); G2M(0x01,modrm2,Cp); - } } if (mode&MOVSDST) { // movzwl Ofs_DI(%%ebx),%%edi @@ -1726,10 +1602,6 @@ shrot0: } // addl Ofs_XES(%%ebx),%%edi G3M(0x03,0x7b,Ofs_XES,Cp); - if (mode&(MREP|MREPNE)) { - // addl %%[re]bp,%%[re]di - Gen48(Cp); G2M(0x01,0xef,Cp); - } } if (mode&(MREP|MREPNE)) { /* Address overflow detection */ @@ -1804,14 +1676,6 @@ shrot0: if (mode&(MREP|MREPNE)) { // movl Ofs_ECX(%%ebx),%%ecx G3M(0x8b,0x4b,Ofs_ECX,Cp); - if (mode&MOVSSRC) { - // addl %%[re]bp,%%[re][sd]i - Gen48(Cp); G2M(0x01,modrm2,Cp); - } - if (mode&MOVSDST) { - // addl %%[re]bp,%%[re]di - Gen48(Cp); G2M(0x01,0xef,Cp); - } } } } break; @@ -1867,17 +1731,17 @@ shrot0: // assumes eax=(%%esi) // mov %%eax, %%edx G2M(0x89,0xc2,Cp); - // mov (%%edi,%%ebp,1), %%{e}a[xl] + // mov (%%edi), %%{e}a[xl] if (mode&MBYTE) { - G4M(0x8a,0x04,0x2f,0x90,Cp); + G2(0x078a,Cp); G1(0x90,Cp); } else if (mode&DATA16) { - G4M(0x66,0x8b,0x04,0x2f,Cp); + G1(0x66,Cp); G2(0x078b,Cp); } else { - G4M(0x8b,0x04,0x2f,0x90,Cp); + G2(0x078b,Cp); G1(0x90,Cp); } - G2(0x9090,Cp); + G3(0x909090,Cp); // cmp %%eax, %%edx if (mode&MBYTE) { G2M(0x38,0xc2,Cp); @@ -1947,8 +1811,6 @@ shrot0: } if (mode&MOVSSRC) { // esi = base1 + CPU_(e)SI +- n - // subl %%[re]bp,%%[re]si - Gen48(Cp); G2M(0x29,0xee,Cp); // subl OVERR_DS(%%ebx),%%esi G2(0x732b,Cp); G1(IG->ovds,Cp); // movw %%si,Ofs_SI(%%ebx) @@ -1956,8 +1818,6 @@ shrot0: } if (mode&MOVSDST) { // edi = base2 + CPU_(e)DI +- n - // subl %%[re]bp,%%[re]di - Gen48(Cp); G2M(0x29,0xef,Cp); // subl Ofs_XES(%%ebx),%%edi G3M(0x2b,0x7b,Ofs_XES,Cp); // movw %%di,Ofs_DI(%%ebx) @@ -1982,8 +1842,6 @@ shrot0: } if (mode&MOVSSRC) { // esi = base1 + CPU_(e)SI +- n - // subl %%[re]bp,%%[re]si - Gen48(Cp); G2M(0x29,0xee,Cp); // subl OVERR_DS(%%ebx),%%esi G2(0x732b,Cp); G1(IG->ovds,Cp); // movl %%esi,Ofs_ESI(%%ebx) @@ -1991,8 +1849,6 @@ shrot0: } if (mode&MOVSDST) { // edi = base2 + CPU_(e)DI +- n - // subl %%[re]bp,%%[re]di - Gen48(Cp); G2M(0x29,0xef,Cp); // subl Ofs_XES(%%ebx),%%edi G3M(0x2b,0x7b,Ofs_XES,Cp); // movl %%edi,Ofs_EDI(%%ebx) @@ -2144,7 +2000,6 @@ shrot0: case O_RDTSC: { // rdtsc G2(0x310f,Cp); -#if 0 if (eTimeCorrect >= 0) { // movl %%eax,%%ecx // movl %%edx,%%edi @@ -2170,7 +2025,6 @@ shrot0: G3M(0x89,0x43,Ofs_ETIME,Cp); G3M(0x89,0x53,Ofs_ETIME+4,Cp); } -#endif // movl %%eax,Ofs_EAX(%%ebx) // movl %%edx,Ofs_EDX(%%ebx) G3M(0x89,0x43,Ofs_EAX,Cp); @@ -2215,6 +2069,8 @@ shrot0: G3M(0x0f,0xb7,0xc0,Cp); // addl Ofs_XCS(%%ebx),%%eax G3M(0x03,0x43,Ofs_XCS,Cp); + // subl Ofs_MEMBASE(%%ebx),%%eax + G3M(0x2b,0x43,Ofs_MEMBASE,Cp); // pop %%edx; ret G2M(0x5a,0xc3,Cp); } @@ -2232,20 +2088,8 @@ shrot0: 0x8d,0x49,0xfe, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edi - 0x8d,0x14,0x0e, - // movw %%ax,(%%edx,%%ebp,1) - 0x66,0x89,0x04,0x2a, -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, -#endif + // movw %%ax,(%%esi,%%ecx,1) + 0x66,0x89,0x04,0x0e, // movl %%ecx,Ofs_ESP(%%ebx) 0x89,0x4b,Ofs_ESP }; @@ -2260,20 +2104,8 @@ shrot0: 0x8d,0x49,0xfc, // andl StackMask(%%ebx),%%ecx 0x23,0x4b,Ofs_STACKM, - // leal (%%esi,%%ecx,1),%%edi - 0x8d,0x14,0x0e, - // movl %%eax,(%%edx,%%ebp,1) - 0x89,0x04,0x2a, -#ifdef KEEP_ESP /* keep high 16-bits of ESP in small-stack mode */ - // movl StackMask(%%ebx),%%edx - 0x8b,0x53,Ofs_STACKM, - // notl %%edx - 0xf7,0xd2, - // andl Ofs_ESP(%%ebx),%%edx - 0x23,0x53,Ofs_ESP, - // orl %%edx,%%ecx - 0x09,0xd1, -#endif + // movl %%eax,(%%esi,%%ecx,1) + 0x89,0x04,0x0e, // movl %%ecx,Ofs_ESP(%%ebx) 0x89,0x4b,Ofs_ESP }; @@ -2446,7 +2278,7 @@ shrot0: break; } -#if PROFILE +#ifdef PROFILE if (debug_level('e')) GenTime += (GETTSC() - t0); #endif return Cp; @@ -2462,7 +2294,7 @@ static void AddrGen_x86(int op, int mode, ...) va_list ap; IMeta *I; IGen *IG; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; if (debug_level('e')) t0 = GETTSC(); #endif @@ -2528,7 +2360,7 @@ static void AddrGen_x86(int op, int mode, ...) } va_end(ap); I->ngen++; -#if PROFILE +#ifdef PROFILE if (debug_level('e')) GenTime += (GETTSC() - t0); #endif } @@ -2540,7 +2372,7 @@ static void Gen_x86(int op, int mode, ...) va_list ap; IMeta *I; IGen *IG; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; if (debug_level('e')) t0 = GETTSC(); #endif @@ -2785,7 +2617,7 @@ static void Gen_x86(int op, int mode, ...) va_end(ap); I->ngen++; -#if PROFILE +#ifdef PROFILE if (debug_level('e')) GenTime += (GETTSC() - t0); #endif } @@ -2966,7 +2798,7 @@ static void NodeLinker(TNode *LG, TNode *G) unsigned int *lp; linkdesc *T = &G->clink; backref *B; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; #endif @@ -2975,7 +2807,7 @@ static void NodeLinker(TNode *LG, TNode *G) #endif return; -#if PROFILE +#ifdef PROFILE if (debug_level('e')) t0 = GETTSC(); #endif if (debug_level('e')>8 && LG) e_printf("NodeLinker: %08x->%08x\n",LG->key,G->key); @@ -3088,7 +2920,7 @@ static void NodeLinker(TNode *LG, TNode *G) } } } -#if PROFILE +#ifdef PROFILE if (debug_level('e')) LinkTime += (GETTSC() - t0); #endif } @@ -3099,7 +2931,7 @@ void NodeUnlinker(TNode *G) unsigned int *lp; linkdesc *T = &G->clink; backref *B = T->bkr.next; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; #endif @@ -3107,7 +2939,7 @@ void NodeUnlinker(TNode *G) if (!UseLinker) #endif return; -#if PROFILE +#ifdef PROFILE if (debug_level('e')) t0 = GETTSC(); #endif // unlink backward references (from other nodes to the current @@ -3211,7 +3043,7 @@ void NodeUnlinker(TNode *G) T->nt_ref = NULL; } memset(T, 0, sizeof(linkdesc)); -#if PROFILE +#ifdef PROFILE if (debug_level('e')) LinkTime += (GETTSC() - t0); #endif } @@ -3240,7 +3072,7 @@ void NodeUnlinker(TNode *G) * */ -static unsigned int CloseAndExec_x86(unsigned int PC, int mode) +static unsigned int CloseAndExec_x86(unsigned int PC, int mode, int ln) { IMeta *I0; TNode *G; @@ -3255,7 +3087,7 @@ static unsigned int CloseAndExec_x86(unsigned int PC, int mode) I0 = &InstrMeta[0]; if (debug_level('e')>2) { - e_printf("==== Closing sequence at %08x\n", PC); + e_printf("== (%d) == Closing sequence at %08x\n",ln,PC); } GenCodeBuf = ProduceCode(PC, I0); @@ -3264,7 +3096,7 @@ static unsigned int CloseAndExec_x86(unsigned int PC, int mode) return I0->npc; NodesParsed++; -#if PROFILE +#ifdef PROFILE if (debug_level('e')) TotalNodesParsed++; #endif G = Move2Tree(I0, GenCodeBuf); /* when is G==NULL? */ @@ -3278,7 +3110,7 @@ static unsigned int CloseAndExec_x86(unsigned int PC, int mode) G->mode = mode; /* check links INSIDE current node */ NodeLinker(G, G); - return Exec_x86(G); + return Exec_x86(G, ln); } static unsigned int Exec_x86_pre(unsigned char *ecpu) @@ -3317,9 +3149,8 @@ static void Exec_x86_post(unsigned long flg, unsigned int mem_ref) #ifdef __x86_64__ #define RE_REG(r) "%%r"#r #define R_REG(r) "%r"#r -/* Generated code calls C functions which clobber r8-r11 */ -/* r12 is used to backup rsp */ -#define EXEC_CLOBBERS ,"r8","r9","r10","r11","r12" +/* Generated code calls C functions which clobber ... */ +#define EXEC_CLOBBERS ,"r8","r9","r10","r11" #else #define RE_REG(r) "%%e"#r #define R_REG(r) "%e"#r @@ -3330,30 +3161,19 @@ asm(".text\n" "do_seq_start:\n" "push "R_REG(dx)"\n" "jmp *"R_REG(ax)"\n"); -ASMLINKAGE(void,do_seq_start,(void)); +#ifdef __cplusplus +extern "C" +#endif +void do_seq_start(void); static unsigned Exec_x86_asm(unsigned *mem_ref, unsigned long *flg, unsigned char *ecpu, unsigned char *SeqStart) { unsigned ePC; InCompiledCode = 1; asm volatile ( -#ifdef __x86_64__ - "movq %%rsp,%%r12\n" - "addq $-128,%%rsp\n" /* go below red zone */ - "andq $~15,%%rsp\n" /* 16-byte stack alignment */ - "push "RE_REG(bp)"\n" -#endif - "push "RE_REG(bp)"\n" - "mov %7, "RE_REG(bp)"\n" "call *%6\n" /* call SeqStart */ - "pop "RE_REG(bp)"\n" -#ifdef __x86_64__ - "pop "RE_REG(bp)"\n" - "movq %%r12,%%rsp\n" -#endif : "=d"(*flg),"=a"(ePC),"=D"(*mem_ref) - : "b"(ecpu),"d"(*flg),"a"(SeqStart),"R"(do_seq_start), - "m"(mem_base) + : "b"(ecpu),"d"(*flg),"a"(SeqStart),"r"(do_seq_start) : "memory", "cc", "ecx", "esi" EXEC_CLOBBERS ); InCompiledCode = 0; @@ -3362,7 +3182,7 @@ static unsigned Exec_x86_asm(unsigned *mem_ref, unsigned long *flg, return ePC; } -unsigned int Exec_x86(TNode *G) +unsigned int Exec_x86(TNode *G, int ln) { unsigned long flg; unsigned char *ecpu; @@ -3370,15 +3190,17 @@ unsigned int Exec_x86(TNode *G) unsigned int ePC; unsigned short seqflg = G->flags; unsigned char *SeqStart = G->addr; -#if PROFILE - hitimer_u TimeStartExec, TimeEndExec; + hitimer_u TimeEndExec; + +#ifdef PROFILE + if (debug_level('e')) TotalNodesExecd++; #endif ecpu = CPUOFFS(0); if (debug_level('e')>1) { if (TheCPU.sigalrm_pending>0) e_printf("** SIGALRM is pending\n"); - e_printf("==== Executing code at %p flg=%04x\n", - SeqStart,seqflg); + e_printf("== (%d) == Executing code at %p flg=%04x\n", + ln,SeqStart,seqflg); } #ifdef ASM_DUMP fprintf(aLog,"%p: exec\n",G->key); @@ -3396,19 +3218,21 @@ unsigned int Exec_x86(TNode *G) } flg = Exec_x86_pre(ecpu); -#if PROFILE - __asm__ __volatile__ ( - "rdtsc\n" - : "=a"(TimeStartExec.t.tl),"=d"(TimeStartExec.t.th) - ); -#endif + + if (eTimeCorrect >= 0) + __asm__ __volatile__ ( +" rdtsc\n" + : "=a"(TimeStartExec.t.tl),"=d"(TimeStartExec.t.th) + ); + ePC = Exec_x86_asm(&mem_ref, &flg, ecpu, SeqStart); -#if PROFILE - __asm__ __volatile__ ( - "rdtsc\n" - : "=a"(TimeEndExec.t.tl),"=d"(TimeEndExec.t.th) - ); -#endif + + if (eTimeCorrect >= 0) + __asm__ __volatile__ ( +" rdtsc\n" + : "=a"(TimeEndExec.t.tl),"=d"(TimeEndExec.t.th) + ); + Exec_x86_post(flg, mem_ref); /* was there at least one FP op in the sequence? */ @@ -3426,9 +3250,13 @@ unsigned int Exec_x86(TNode *G) } } - if (debug_level('e')) { -#if PROFILE + + if (eTimeCorrect >= 0) { TimeEndExec.td -= TimeStartExec.td; + TheCPU.EMUtime += TimeEndExec.td; + } + if (debug_level('e')) { +#ifdef PROFILE ExecTime += TimeEndExec.td; #endif if (debug_level('e')>1) { @@ -3455,10 +3283,15 @@ unsigned int Exec_x86(TNode *G) CEmuStat &= ~CeS_TRAP; } else { CEmuStat &= ~(CeS_INHI|CeS_MOVSS); - if (TheCPU.sigalrm_pending) { + if (signal_pending()) { CEmuStat|=CeS_SIGPEND; - TheCPU.sigalrm_pending = 0; } + /* sigalrm_pending at this point can be: + * 0 - if there was no signal + * 1 - if there was a signal + * .. so reset it for next try + */ + TheCPU.sigalrm_pending = 0; } #if defined(SINGLESTEP) @@ -3509,7 +3342,7 @@ unsigned int Exec_x86_fast(TNode *G) NodeLinker(LastXNode, G); LastXNode = G; } - if (TheCPU.sigalrm_pending) { + if (signal_pending()) { CEmuStat|=CeS_SIGPEND; break; } diff --git a/src/base/emu-i386/simx86/codegen-x86.h b/src/base/emu-i386/simx86/codegen-x86.h index 11a07fc..b6deda7 100644 --- a/src/base/emu-i386/simx86/codegen-x86.h +++ b/src/base/emu-i386/simx86/codegen-x86.h @@ -39,19 +39,27 @@ #include "trees.h" #include "vgaemu.h" +#define HOST_ARCH_X86 + #define TAILSIZE 7 #define TAILFIX 1 +/* If you undefine this, in 16-bit stack mode the high 16 bits of ESP + * will be zeroed after every push/pop operation. There's a small + * possibility of breaking some code, you can easily figure out how. + * For 32-bit stacks, keeping ESP is also a waste of time. */ +#undef KEEP_ESP + ///////////////////////////////////////////////////////////////////////////// extern unsigned int VgaAbsBankBase; -extern unsigned int Exec_x86(TNode *G); +extern unsigned int Exec_x86(TNode *G, int ln); extern unsigned int Exec_x86_fast(TNode *G); ///////////////////////////////////////////////////////////////////////////// -#define STD_WRITE_B G3M(0x88,0x04,0x2f,Cp); -#define STD_WRITE_WL(m) Gen66(m,Cp); G3M(0x89,0x04,0x2f,Cp) +#define STD_WRITE_B G3M(0x88,0x07,0x90,Cp); +#define STD_WRITE_WL(m) G3((m)&DATA16?0x078966:0x900789,Cp) #define GenAddECX(o) if (((o) > -128) && ((o) < 128)) {\ G2(0xc183,Cp); G1((o),Cp); } else {\ @@ -86,13 +94,6 @@ extern unsigned int Exec_x86_fast(TNode *G); #define Gen66(mode, Cp) \ *(Cp)=OPERoverride; Cp+=BTA(BitDATA16, mode) -// 64-bit operand size REX byte -#ifdef __x86_64__ -#define Gen48(Cp) G1(0x48,Cp) -#else -#define Gen48(Cp) -#endif - // 'no-jump' version, tricky (depends on bit position) #define G2_4(mode, val, Cp) \ *((int *)(Cp))=(val); Cp+=BT24(BitDATA16, mode) diff --git a/src/base/emu-i386/simx86/codegen.h b/src/base/emu-i386/simx86/codegen.h index 3902aa6..f916e04 100644 --- a/src/base/emu-i386/simx86/codegen.h +++ b/src/base/emu-i386/simx86/codegen.h @@ -205,9 +205,15 @@ // returns 2(16 bit), 4(32 bit) #define BT24(bpos, mode) (4 - (((mode) << (1-(bpos))) & 2)) -static __inline__ int FastLog2(int v) +static __inline__ int FastLog2(register int v) { - return fls(v) - 1; + register int temp; + __asm__ ("bsr %1,%0\n \ + jnz 1f\n \ + xor %0,%0\n \ +1: " \ + : "=a"(temp) : "g"(v) ); + return temp; } ///////////////////////////////////////////////////////////////////////////// @@ -268,18 +274,12 @@ static __inline__ void POP_ONLY(int m) } void InitGen(void); -#ifdef X86_JIT int NewIMeta(int npc, int *rc); -#else -static inline int NewIMeta(int npc, int *rc) {return 0;} -#endif extern void (*Gen)(int op, int mode, ...); extern void (*AddrGen)(int op, int mode, ...); extern int (*Fp87_op)(int exop, int reg); -extern unsigned int (*CloseAndExec)(unsigned int PC, int mode); +extern unsigned int (*CloseAndExec)(unsigned int PC, int mode, int ln); void EndGen(void); -extern void fp87_set_rounding(void); -extern void fp87_save_except(void); // extern unsigned char InterOps[]; extern char RmIsReg[]; @@ -290,7 +290,6 @@ extern char OpSizeBit[]; #define OPSIZE(m) (OpSize[(m)&(DATA16|MBYTE)]) #define OPSIZEBIT(m) (OpSizeBit[(m)&(DATA16|MBYTE)]) -#ifdef X86_JIT int Cpatch(sigcontext_t *scp); int UnCpatch(unsigned char *eip); void stub_rep(void) asm ("stub_rep__"); @@ -302,6 +301,5 @@ void stub_wri_32(void) asm ("stub_wri_32__"); void stub_read_8 (void) asm ("stub_read_8__" ); void stub_read_16(void) asm ("stub_read_16__"); void stub_read_32(void) asm ("stub_read_32__"); -#endif #endif diff --git a/src/base/emu-i386/simx86/cpatch.c b/src/base/emu-i386/simx86/cpatch.c index bd67243..1d9c961 100644 --- a/src/base/emu-i386/simx86/cpatch.c +++ b/src/base/emu-i386/simx86/cpatch.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ @@ -53,7 +53,7 @@ void m_munprotect(unsigned int addr, unsigned int len, unsigned char *eip) e_printf("CODE %08x hit in DATA %p patch\n",addr,eip); } /* if only data in aliased low memory is hit, nothing to do */ - if (addr < LOWMEM_SIZE + HMASIZE) { + if (LINEAR2UNIX(addr) != MEM_BASE32(addr)) { if (e_querymark(addr, len)) // no need to invalidate the whole page here, // as the page does not need to be unprotected @@ -65,8 +65,8 @@ void m_munprotect(unsigned int addr, unsigned int len, unsigned char *eip) * Maybe the stub was set up before that code was parsed. * Clear that code */ /* if (UnCpatch((void *)(eip-3))) leavedos_main(0); */ - len = PAGE_ALIGN(addr+len-1) - (addr & _PAGE_MASK); - addr &= _PAGE_MASK; + len = PAGE_ALIGN(addr+len-1) - (addr & PAGE_MASK); + addr &= PAGE_MASK; InvalidateNodeRange(addr,len,eip); } @@ -92,7 +92,7 @@ struct rep_stack { } __attribute__((packed)); -void rep_movs_stos(struct rep_stack *stack) +asmlinkage void rep_movs_stos(struct rep_stack *stack) { unsigned char *paddr = stack->edi; unsigned int ecx = stack->ecx; @@ -217,36 +217,45 @@ done: /* ======================================================================= */ -void stk_16(dosaddr_t addr, Bit16u value) +asmlinkage void stk_16(unsigned char *paddr, Bit16u value) { + dosaddr_t addr; + in_cpatch++; assert(InCompiledCode); InCompiledCode--; + addr = DOSADDR_REL(paddr); e_invalidate(addr, 2); WRITE_WORD(addr, value); InCompiledCode++; in_cpatch--; } -void stk_32(dosaddr_t addr, Bit32u value) +asmlinkage void stk_32(unsigned char *paddr, Bit32u value) { + dosaddr_t addr; + in_cpatch++; assert(InCompiledCode); InCompiledCode--; + addr = DOSADDR_REL(paddr); e_invalidate(addr, 4); WRITE_DWORD(addr, value); InCompiledCode++; in_cpatch--; } -void wri_8(dosaddr_t addr, Bit8u value, unsigned char *eip) +asmlinkage void wri_8(unsigned char *paddr, Bit8u value, unsigned char *eip) { + dosaddr_t addr; + in_cpatch++; assert(InCompiledCode); InCompiledCode--; + addr = DOSADDR_REL(paddr); m_munprotect(addr, 1, eip); InCompiledCode++; - if (!emu_ldt_write(addr, value, 1)) { + if (!emu_ldt_write(paddr, value, 1)) { if (vga_write_access(addr)) vga_write(addr, value); else @@ -255,14 +264,17 @@ void wri_8(dosaddr_t addr, Bit8u value, unsigned char *eip) in_cpatch--; } -void wri_16(dosaddr_t addr, Bit16u value, unsigned char *eip) +asmlinkage void wri_16(unsigned char *paddr, Bit16u value, unsigned char *eip) { + dosaddr_t addr; + in_cpatch++; assert(InCompiledCode); InCompiledCode--; + addr = DOSADDR_REL(paddr); m_munprotect(addr, 2, eip); InCompiledCode++; - if (!emu_ldt_write(addr, value, 2)) { + if (!emu_ldt_write(paddr, value, 2)) { if (vga_write_access(addr)) vga_write_word(addr, value); else @@ -271,14 +283,17 @@ void wri_16(dosaddr_t addr, Bit16u value, unsigned char *eip) in_cpatch--; } -void wri_32(dosaddr_t addr, Bit32u value, unsigned char *eip) +asmlinkage void wri_32(unsigned char *paddr, Bit32u value, unsigned char *eip) { + dosaddr_t addr; + in_cpatch++; assert(InCompiledCode); InCompiledCode--; + addr = DOSADDR_REL(paddr); m_munprotect(addr, 4, eip); InCompiledCode++; - if (!emu_ldt_write(addr, value, 4)) { + if (!emu_ldt_write(paddr, value, 4)) { if (vga_write_access(addr)) vga_write_dword(addr, value); else @@ -287,18 +302,21 @@ void wri_32(dosaddr_t addr, Bit32u value, unsigned char *eip) in_cpatch--; } -Bit8u read_8(dosaddr_t addr) +asmlinkage Bit8u read_8(unsigned char *paddr) { + dosaddr_t addr = DOSADDR_REL(paddr); return vga_read_access(addr) ? vga_read(addr) : READ_BYTE(addr); } -Bit16u read_16(dosaddr_t addr) +asmlinkage Bit16u read_16(unsigned char *paddr) { + dosaddr_t addr = DOSADDR_REL(paddr); return vga_read_access(addr) ? vga_read_word(addr) : READ_WORD(addr); } -Bit32u read_32(dosaddr_t addr) +asmlinkage Bit32u read_32(unsigned char *paddr) { + dosaddr_t addr = DOSADDR_REL(paddr); return vga_read_access(addr) ? vga_read_dword(addr) : READ_DWORD(addr); } @@ -311,8 +329,9 @@ Bit32u read_32(dosaddr_t addr) #define STUB_STK(cfunc) \ " pushal\n \ + leal (%esi,%ecx,1),%edi\n \ pushl %eax\n \ - pushl %edx\n \ + pushl %edi\n \ call "#cfunc"\n \ addl $8,%esp\n \ popal\n \ @@ -367,7 +386,7 @@ asm ( " pushq %rdx\n" \ " pushq %rdi\n" \ " pushq %rsi\n" \ -" movl %edx,%edi\n" \ +" leal (%rsi,%rcx,1),%edi\n" \ " movl %eax,%esi\n" \ /* pass base address in %rdi */ \ " call "#cfunc"\n" \ @@ -447,7 +466,7 @@ int Cpatch(sigcontext_t *scp) unsigned char *p; int w16; unsigned int v; - unsigned char *eip = (unsigned char *)_scp_rip; + unsigned char *eip = (unsigned char *)_rip; if (in_cpatch) return 0; @@ -458,16 +477,16 @@ int Cpatch(sigcontext_t *scp) if (debug_level('e')>1) e_printf("### REP patch at %p\n",eip); p-=2; G2M(0xff,0x13,p); /* call (%ebx) */ - _scp_rip -= 2; /* make sure call (%ebx) is performed the first time */ + _rip -= 2; /* make sure call (%ebx) is performed the first time */ return 1; } if (*p==0x66) w16=1,p++; else w16=0; v = *((int *)p) & 0xffffff; - while (v==0x2a0489) { // stack: never fail - // mov %%{e}ax,(%%edx,%%ebp,1) - // we have a sequence: 66 89 04 2a - // or 89 04 2a + while (v==0x0e0489) { // stack: never fail + // mov %%{e}ax,(%%esi,%%ecx,1) + // we have a sequence: 66 89 04 0e + // or 89 04 0e if (debug_level('e')>1) e_printf("### Stack patch at %p\n",p); if (w16) { p--; JSRPATCH(p,Ofs_stub_stk_16); p[3] = 0x90; p+=4; @@ -475,48 +494,45 @@ int Cpatch(sigcontext_t *scp) else { JSRPATCH(p,Ofs_stub_stk_32); p+=3; } -#ifdef KEEP_ESP - p += 10; -#endif /* check for optimized multiple register push */ if (p[0]==0x89) return 1; //O_PUSH3 - p += 12; + p += 9; if (p[0]==0xff) return 1; // already JSRPATCH'ed if (*p==0x66) w16=1,p++; else w16=0; v = *((int *)p) & 0xffffff; /* extra check: should not fail */ - if (v!=0x2a0489) { - dbug_printf("CPUEMU: stack patch failure, fix source code! %x\n", v); + if (v!=0x0e0489) { + dbug_printf("CPUEMU: stack patch failure, fix source code!\n"); return 1; } } - if (v==0x2f0488) { // movb %%al,(%%edi,%%ebp,1) - // we have a sequence: 88 04 2f + if (v==0x900788) { // movb %%al,(%%edi) + // we have a sequence: 88 07 90 if (debug_level('e')>1) e_printf("### Byte write patch at %p\n",eip); JSRPATCH(p,Ofs_stub_wri_8); return 1; } - if (v==0x2f0489) { // mov %%{e}ax,(%%edi,%%ebp,1) - // we have a sequence: 89 04 2f - // or 66 89 04 2f + if ((v&0xffff)==0x0789) { // mov %%{e}ax,(%%edi) + // we have a sequence: 89 07 90 + // or 66 89 07 if (debug_level('e')>1) e_printf("### Word/Long write patch at %p\n",eip); if (w16) { - p--; JSRPATCH(p,Ofs_stub_wri_16); p[3] = 0x90; + p--; JSRPATCH(p,Ofs_stub_wri_16); } else { JSRPATCH(p,Ofs_stub_wri_32); } return 1; } - if (v==0x2f048a) { // movb (%%edi,%%ebp,1),%%al - // we have a sequence: 8a 04 2f 90 90 90 + if (v==0x90078a) { // movb (%%edi),%%al + // we have a sequence: 8a 07 90 90 90 90 if (debug_level('e')>1) e_printf("### Byte read patch at %p\n",eip); JSRPATCHL(p,Ofs_stub_read_8); return 1; } - if (v==0x2f048b) { // mov (%%edi,%%ebp,1),%%{e}ax - // we have a sequence: 8b 04 2f 90 90 90 - // or 66 8b 04 2f 90 90 + if ((v&0xffff)==0x078b) { // mov %%{e}ax,(%%edi) + // we have a sequence: 8b 07 90 90 90 90 + // or 66 8b 07 90 90 90 if (debug_level('e')>1) e_printf("### Word/Long read patch at %p\n",eip); if (w16) { p--; JSRPATCHL(p,Ofs_stub_read_16); @@ -545,19 +561,19 @@ int UnCpatch(unsigned char *eip) } else if (p[1] == 0x53) { if ((unsigned char)p[2] == Ofs_stub_wri_8) { - *((short *)p) = 0x0488; p[2] = 0x2f; + *((short *)p) = 0x0788; p[2] = 0x90; } else if ((unsigned char)p[2] == Ofs_stub_wri_16) { - *p++ = 0x66; *((short *)p) = 0x0488; p[3] = 0x2f; + *p++ = 0x66; *((short *)p) = 0x0789; } else if ((unsigned char)p[2] == Ofs_stub_wri_32) { - *((short *)p) = 0x0489; p[2] = 0x2f; + *((short *)p) = 0x0789; p[2] = 0x90; } else if ((unsigned char)p[2] == Ofs_stub_stk_16) { - *((int *)p) = 0x2a048966; + *((int *)p) = 0x0e048966; } else if ((unsigned char)p[2] == Ofs_stub_stk_32) { - *((short *)p) = 0x0489; p[2] = 0x2a; + *((short *)p) = 0x0489; p[2] = 0x0e; } else return 1; } diff --git a/src/base/emu-i386/simx86/cpatch.h b/src/base/emu-i386/simx86/cpatch.h index bbcf2bd..6fb08ca 100644 --- a/src/base/emu-i386/simx86/cpatch.h +++ b/src/base/emu-i386/simx86/cpatch.h @@ -4,19 +4,21 @@ #define EXTERN extern #endif #ifdef __i386__ -#define ASMLINKAGE(x,y,z) EXTERN __attribute__((cdecl)) x y z asm(#y) +#define asmlinkage EXTERN __attribute__((cdecl)) \ + __attribute__((force_align_arg_pointer)) #else -#define ASMLINKAGE(x,y,z) EXTERN x y z asm(#y) +#define asmlinkage EXTERN \ + __attribute__((force_align_arg_pointer)) #endif struct rep_stack; -ASMLINKAGE(void,rep_movs_stos,(struct rep_stack *stack)); -ASMLINKAGE(void,stk_16,(dosaddr_t addr, Bit16u value)); -ASMLINKAGE(void,stk_32,(dosaddr_t addr, Bit32u value)); -ASMLINKAGE(void,wri_8,(dosaddr_t addr, Bit8u value, unsigned char *eip)); -ASMLINKAGE(void,wri_16,(dosaddr_t addr, Bit16u value, unsigned char *eip)); -ASMLINKAGE(void,wri_32,(dosaddr_t addr, Bit32u value, unsigned char *eip)); -ASMLINKAGE(Bit8u,read_8,(dosaddr_t addr)); -ASMLINKAGE(Bit16u,read_16,(dosaddr_t addr)); -ASMLINKAGE(Bit32u,read_32,(dosaddr_t addr)); +asmlinkage void rep_movs_stos(struct rep_stack *stack); +asmlinkage void stk_16(unsigned char *paddr, Bit16u value); +asmlinkage void stk_32(unsigned char *paddr, Bit32u value); +asmlinkage void wri_8(unsigned char *paddr, Bit8u value, unsigned char *eip); +asmlinkage void wri_16(unsigned char *paddr, Bit16u value, unsigned char *eip); +asmlinkage void wri_32(unsigned char *paddr, Bit32u value, unsigned char *eip); +asmlinkage Bit8u read_8(unsigned char *paddr); +asmlinkage Bit16u read_16(unsigned char *paddr); +asmlinkage Bit32u read_32(unsigned char *paddr); diff --git a/src/base/emu-i386/simx86/cpu-emu.c b/src/base/emu-i386/simx86/cpu-emu.c index 93e713f..7bab200 100644 --- a/src/base/emu-i386/simx86/cpu-emu.c +++ b/src/base/emu-i386/simx86/cpu-emu.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ @@ -51,7 +51,7 @@ /* ======================================================================= */ -#if PROFILE +#ifdef PROFILE hitimer_t AddTime, SearchTime, ExecTime, CleanupTime; // for debug hitimer_t GenTime, LinkTime; #endif @@ -59,6 +59,11 @@ hitimer_t GenTime, LinkTime; static hitimer_t TotalTime; static int iniflag = 0; +static hitimer_t sigEMUtime = 0; +static hitimer_t lastEMUsig = 0; +static unsigned long sigEMUdelta = 0; +int eTimeCorrect; + /* This needs to be merged someday with 'mode' */ volatile int CEmuStat = 0; @@ -81,6 +86,8 @@ volatile int InCompiledCode = 0; unsigned int trans_addr, return_addr; // PC +static void e_gen_sigprof(sigcontext_t *scp, siginfo_t *si); + #ifdef DEBUG_TREE FILE *tLog = NULL; #endif @@ -138,7 +145,7 @@ FILE *aLog = NULL; * 20 unsigned short gs, __gsh; * -------------------------------------------------------------- */ -cpuctx_t e_scp; /* initialized to 0 */ +sigcontext_t e_scp; /* initialized to 0 */ /* ======================================================================= */ @@ -213,7 +220,7 @@ static inline void exprintb(unsigned char val,char *bf,unsigned int pos) char *e_print_regs(void) { - static char buf[sizeof(eregbuf) + 300]; + static char buf[300]; char *p = buf; char *q = eregbuf; @@ -227,7 +234,8 @@ char *e_print_regs(void) exprintl(rEDI,buf,(ERB_L2+ERB_LEFTM)+13); exprintl(rEBP,buf,(ERB_L2+ERB_LEFTM)+26); exprintl(rESP,buf,(ERB_L2+ERB_LEFTM)+39); - exprintl(TheCPU.eflags,buf,(ERB_L3+ERB_LEFTM)); + if (!(TheCPU.eflags&EFLAGS_VM)) + exprintl(get_FLAGS(TheCPU.eflags),buf,(ERB_L3+ERB_LEFTM)); exprintw(TheCPU.cs,buf,(ERB_L3+ERB_LEFTM)+13); exprintw(TheCPU.ds,buf,(ERB_L3+ERB_LEFTM)+26); exprintw(TheCPU.es,buf,(ERB_L3+ERB_LEFTM)+39); @@ -262,16 +270,16 @@ char *e_print_regs(void) #define GetSegmentBaseAddress(s) GetSegmentBase(s) #define IsSegment32(s) dpmi_segment_is32(s) -char *e_print_scp_regs(cpuctx_t *scp, int pmode) +char *e_print_scp_regs(sigcontext_t *scp, int pmode) { static char buf[300]; unsigned short *stk; int i, j; - i = sprintf(buf, "RAX: %08x RBX: %08x RCX: %08x RDX: %08x" + i = sprintf(buf, "RAX: %08"PRI_RG" RBX: %08"PRI_RG" RCX: %08"PRI_RG" RDX: %08"PRI_RG " VFLAGS(h): %08x\n", _rax, _rbx, _rcx, _rdx, _eflags); - i += sprintf(buf + i, "RSI: %08x RDI: %08x RBP: %08x RSP: %08x\n", + i += sprintf(buf + i, "RSI: %08"PRI_RG" RDI: %08"PRI_RG" RBP: %08"PRI_RG" RSP: %08"PRI_RG"\n", _rsi, _rdi, _rbp, _rsp); i += sprintf(buf + i, "CS: %04x DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n", _cs, _ds, _es, _fs, _gs, _ss); @@ -331,7 +339,7 @@ char *e_emu_disasm(unsigned char *org, int is32, unsigned int refseg) } #ifdef TRACE_DPMI -char *e_scp_disasm(cpuctx_t *scp, int pmode) +char *e_scp_disasm(sigcontext_t *scp, int pmode) { static char insrep = 0; static unsigned char buf[1024]; @@ -522,8 +530,6 @@ static void Reg2Cpu (int mode) SetSegReal(SREG(gs),Ofs_GS); trans_addr = LONG_CS + TheCPU.eip; - /* FPU state is loaded later on demand for JIT, not used for simulator */ - TheCPU.fpstate = &vm86_fpu_state; if (debug_level('e')>1) { if (debug_level('e')==9) e_printf("Reg2Cpu< vm86=%08x dpm=%08x emu=%08x\n%s\n", REG(eflags),get_FLAGS(TheCPU.eflags),TheCPU.eflags, @@ -568,14 +574,6 @@ void Cpu2Reg (void) clear_IF(); REG(eflags) |= EFLAGS_IF; - if (TheCPU.fpstate == NULL) { - if (!CONFIG_CPUSIM) - savefpstate(vm86_fpu_state); - else - fp87_save_except(); - fesetenv(&dosemu_fenv); - } - if (debug_level('e')>1) e_printf("Cpu2Reg< vm86=%08x dpm=%08x emu=%08x\n", REG(eflags),get_FLAGS(TheCPU.eflags),TheCPU.eflags); } @@ -583,7 +581,7 @@ void Cpu2Reg (void) /* ======================================================================= */ -static void Scp2Cpu (cpuctx_t *scp) +static void Scp2Cpu (sigcontext_t *scp) { TheCPU.eax = _eax; TheCPU.ebx = _ebx; @@ -609,13 +607,14 @@ static void Scp2Cpu (cpuctx_t *scp) TheCPU.cr2 = _cr2; TheCPU.df_increments = (TheCPU.eflags&DF)?0xfcfeff:0x040201; - TheCPU.fpstate = &vm86_fpu_state; + /* __fpstate is loaded later on demand for JIT, not used for simulator */ + TheCPU.fpstate = __fpstate; } /* * Build a sigcontext structure to enter fault handling from DPMI */ -static void Cpu2Scp (cpuctx_t *scp, int trapno) +static void Cpu2Scp (sigcontext_t *scp, int trapno) { if (debug_level('e')>1) e_printf("Cpu2Scp> scp=%08x dpm=%08x fl=%08x\n", _eflags,get_FLAGS(TheCPU.eflags),TheCPU.eflags); @@ -649,10 +648,7 @@ static void Cpu2Scp (cpuctx_t *scp, int trapno) */ if (!TheCPU.err) _err = 0; //??? if (TheCPU.fpstate == NULL) { - if (!CONFIG_CPUSIM) - savefpstate(vm86_fpu_state); - else - fp87_save_except(); + if (!CONFIG_CPUSIM) savefpstate(*__fpstate); /* there is no real need to save and restore the FPU state of the emulator itself: savefpstate (fnsave) also resets the current FPU state using fninit; fesetenv then restores trapping of division by @@ -678,7 +674,7 @@ static void Cpu2Scp (cpuctx_t *scp, int trapno) /* * Enter emulator in DPMI mode (context_switch) */ -static int Scp2CpuD(cpuctx_t *scp) +static int Scp2CpuD(sigcontext_t *scp) { unsigned char big; int mode=0; @@ -744,6 +740,17 @@ void reset_emu_cpu(void) void init_emu_cpu(void) { + struct itimerval itv; + unsigned int realdelta = config.update / TIMER_DIVISOR; + + eTimeCorrect = 0; // full backtime stretch +#ifdef HOST_ARCH_X86 + if (!CONFIG_CPUSIM) + eTimeCorrect = 1; // 1/2 backtime stretch +#endif + if (!config.rdtsc) + eTimeCorrect = -1; // if we can't trust the TSC for time keeping + // then don't use it to stretch either if (Ofs_END > 128) { error("CPUEMU: Ofs_END is too large, %i\n", Ofs_END); config.exitearly = 1; @@ -768,14 +775,16 @@ void init_emu_cpu(void) #ifdef HOST_ARCH_X86 if (config.cpusim) InitGen_sim(); - else { + else InitGen_x86(); - InitTrees(); - } #else InitGen_sim(); #endif + if (config.realcpu < CPU_586) { + fprintf(stderr,"Cannot execute CPUEMU without TSC counter\n"); + leavedos_main(0); + } IDT = NULL; if (GDT==NULL) { /* The GDT is not really used (yet?) but some instructions @@ -801,6 +810,19 @@ void init_emu_cpu(void) TheCPU.stub_read_32 = stub_read_32; #endif + /* Only set the timer (for internal debug purposes only) + if ITIMER_PROF is not already set for gprof. + */ + getitimer(ITIMER_PROF, &itv); + if (itv.it_interval.tv_sec == 0 && itv.it_interval.tv_usec == 0 && + itv.it_interval.tv_sec == 0 && itv.it_interval.tv_usec == 0) { + itv.it_interval.tv_usec = realdelta; + itv.it_value.tv_usec = realdelta; + e_printf("TIME: using %d usec for updating PROF timer\n", realdelta); + setitimer(ITIMER_VIRTUAL, &itv, NULL); + registersig(SIGVTALRM, e_gen_sigprof); + } + Running = 1; } @@ -809,24 +831,61 @@ void init_emu_cpu(void) * asynchronous signals because without it any badly-behaved pgm * can stop us forever. */ -void e_gen_sigalrm(void) +void e_gen_sigalrm(sigcontext_t *scp) { - if (!in_dpmi_emu && !in_vm86_emu) + if(!IS_EMU()) return; /* here we come from the kernel with cs==UCODESEL, as * the passed context is that of dosemu, NOT that of the * emulated CPU! */ - TheCPU.sigalrm_pending = 1; /* tested by loops */ + + e_sigpa_count += sigEMUdelta; + if (!in_vm86_emu && !in_dpmi_emu) { /* if into dosemu itself */ + if (eTimeCorrect >= 0) { + TheCPU.EMUtime = GETTSC(); /* resync emulator time */ + sigEMUtime = TheCPU.EMUtime; /* and generate signal */ + } + } + else { + TheCPU.sigalrm_pending = 1; /* tested by loops */ + } + if (eTimeCorrect < 0) + return; + else if (TheCPU.EMUtime >= sigEMUtime) { + lastEMUsig = TheCPU.EMUtime; + sigEMUtime += sigEMUdelta; + /* we can't call sigalrm() because of the way the + * context parameter is passed. */ + return; /* -> signal_save */ + } + /* here we return back to dosemu */ + return; } +static void e_gen_sigprof(sigcontext_t *scp, siginfo_t *si) +{ + e_sigpa_count -= sigEMUdelta; + TheCPU.sigprof_pending += 1; +} + + void enter_cpu_emu(void) { unsigned int realdelta = config.update / TIMER_DIVISOR; + /* The simulator uses dosaddr_t throughout, the JIT adds mem_base + to the segment bases */ + TheCPU.mem_base = CONFIG_CPUSIM ? 0 : (uintptr_t)mem_base; + + if (eTimeCorrect >= 0) { + TheCPU.EMUtime = GETTSC(); + sigEMUdelta = realdelta*config.CPUSpeedInMhz; + sigEMUtime = TheCPU.EMUtime + sigEMUdelta; + } if (debug_level('e')) { TotalTime = 0; -#if PROFILE +#ifdef PROFILE SearchTime = AddTime = ExecTime = CleanupTime = GenTime = LinkTime = 0; #endif @@ -850,7 +909,7 @@ static void print_statistics(void) { dbug_printf("Total cpuemu time %16lld us (incl.trace)\n", (long long)TotalTime/config.CPUSpeedInMhz); -#if PROFILE +#ifdef PROFILE dbug_printf("Total codgen time %16lld us\n", (long long)GenTime/config.CPUSpeedInMhz); dbug_printf("Total linker time %16lld us\n", @@ -893,9 +952,7 @@ void leave_cpu_emu(void) if (IOFF(0x10)==CPUEMU_WATCHER_OFF) IOFF(0x10)=INT10_WATCHER_OFF; #endif -#ifdef HOST_ARCH_X86 EndGen(); -#endif #ifdef DEBUG_TREE fclose(tLog); tLog = NULL; #endif @@ -953,6 +1010,7 @@ static const char *retdescs[] = int e_vm86(void) { + hitimer_t tt0 = 0; int xval,retval,mode; #ifdef SKIP_VM86_TRACE int demusav; @@ -960,11 +1018,16 @@ int e_vm86(void) int errcode; if (iniflag==0) enter_cpu_emu(); - TheCPU.sigalrm_pending = 0; +#ifdef PROFILE + if (debug_level('e')) tt0 = GETTSC(); +#endif e_sigpa_count = 0; mode = ADDR16 | DATA16 | MREALA; TheCPU.StackMask = 0x0000ffff; + /* FPU state is loaded later on demand for JIT, not used for simulator */ + TheCPU.fpstate = vm86_fpu_state; + if (eTimeCorrect >= 0) TheCPU.EMUtime = GETTSC(); #ifdef SKIP_VM86_TRACE demusav=debug_level('e'); if (debug_level('e')) set_debug_level('e', 1); #endif @@ -1007,6 +1070,7 @@ int e_vm86(void) if (debug_level('e')>1) e_printf("---------------------\n\t EMU86: EXCP %#x\n", xval-1); retval = -1; + E_TIME_STRETCH; if (xval==EXCP_SIGNAL) { /* coming here for async interruptions */ if (CEmuStat & (CeS_SIGPEND|CeS_SIGACT)) @@ -1040,7 +1104,9 @@ int e_vm86(void) } default: { /* FAULT, handled via signal callback */ - vm86_fault(xval-1, TheCPU.scp_err, TheCPU.cr2); + if (debug_level('e')) TotalTime += (GETTSC() - tt0); + vm86_fault(xval-1, TheCPU.scp_err, DOSADDR_REL(LINP(TheCPU.cr2))); + if (debug_level('e')) tt0 = GETTSC(); retval = VM86_SIGNAL; break; } @@ -1050,26 +1116,41 @@ int e_vm86(void) while (retval < 0); /* ------ OUTER LOOP -- exit to user level ---------------------- */ + if (TheCPU.fpstate == NULL) { + if (!CONFIG_CPUSIM) savefpstate(*vm86_fpu_state); + fesetenv(&dosemu_fenv); + } + if (debug_level('e')>1) e_printf("EMU86: retval=%s\n", retdescs[retval&7]); #ifdef SKIP_VM86_TRACE set_debug_level('e',demusav); #endif + if (debug_level('e')) { + TotalTime += (GETTSC() - tt0); + /* this time should become >0 only when dosemu was descheduled + * during a vm86/dpmi call. It will be necessary to subtract this + * value from ZeroBase to account for the elapsed time, maybe. */ + if (debug_level('e')>1) + dbug_printf("Sys timers d=%d\n",e_sigpa_count); + } return retval; } /* ======================================================================= */ -int e_dpmi(cpuctx_t *scp) +int e_dpmi(sigcontext_t *scp) { + volatile hitimer_t tt0 = 0; int xval,retval,mode; if (iniflag==0) enter_cpu_emu(); - TheCPU.sigalrm_pending = 0; + if (debug_level('e')) tt0 = GETTSC(); e_sigpa_count = 0; + if (eTimeCorrect >= 0) TheCPU.EMUtime = GETTSC(); /* make clear we are in PM now */ TheCPU.cr[0] |= 1; @@ -1119,51 +1200,41 @@ int e_dpmi(cpuctx_t *scp) Cpu2Scp (scp, xval-1); retval = DPMI_RET_CLIENT; + E_TIME_STRETCH; if ((xval==EXCP_SIGNAL) || (xval==EXCP_PICSIGNAL) || (xval==EXCP_STISIGNAL)) { - retval = DPMI_RET_DOSEMU; + if (debug_level('e')>2) e_printf("DPMI sigpending = %d\n",signal_pending()); + if (signal_pending()) { + retval = DPMI_RET_DOSEMU; + } } else if (xval==EXCP_GOBACK) { retval = DPMI_RET_DOSEMU; } - else if (xval == EXCP0E_PAGE && vga_emu_fault(_cr2,_err,scp)==True) { - retval = DPMI_RET_CLIENT; + else if (xval == EXCP0E_PAGE && vga_emu_fault(DOSADDR_REL(LINP(_cr2)),_err,scp)==True) { + retval = dpmi_check_return(); } else { - retval = DPMI_RET_FAULT; + if (debug_level('e')) TotalTime += (GETTSC() - tt0); + retval = dpmi_fault(scp); + if (debug_level('e')) tt0 = GETTSC(); } } while (retval == DPMI_RET_CLIENT); /* ------ OUTER LOOP -- exit to user level ---------------------- */ + if (debug_level('e')) { + dbug_printf("DPM86: retval=%#x\n", retval); + TotalTime += (GETTSC() - tt0); + dbug_printf("Sys timers d=%d\n",e_sigpa_count); + } return retval; } -/* set special SIM mode for VGAEMU faults */ -int instr_emu_sim(cpuctx_t *scp, int pmode, int cnt) -{ - instr_emu_sim_reset_count(cnt); -#ifdef HOST_ARCH_X86 - if (!config.cpusim) - InitGen_sim(); -#endif - CEmuStat |= CeS_INSTREMU; - if (pmode) - e_dpmi(scp); - else - e_vm86(); - CEmuStat &= ~CeS_INSTREMU; -#ifdef HOST_ARCH_X86 - /* back to regular JIT */ - if (!config.cpusim) - InitGen_x86(); -#endif - return True; -} /* ======================================================================= */ /* file: src/cwsdpmi/exphdlr.c */ -void e_dpmi_b0x(int op,cpuctx_t *scp) +void e_dpmi_b0x(int op,sigcontext_t *scp) { switch (op) { case 0: { /* set */ diff --git a/src/base/emu-i386/simx86/econfig.h b/src/base/emu-i386/simx86/econfig.h index f2ad24c..2aa72de 100644 --- a/src/base/emu-i386/simx86/econfig.h +++ b/src/base/emu-i386/simx86/econfig.h @@ -39,14 +39,14 @@ #undef SINGLESTEP #undef SINGLEBLOCK -#define PROFILE 0 +#undef PROFILE #undef DBG_TIME #undef SKIP_CPATCH #define FAKE_INS_TIME 20 #define MAXINODES 4096 -#define MAX_GEND_BYTES_PER_OP 76 +#define MAX_GEND_BYTES_PER_OP 70 /* NUMGENS must be large enough in !SINGLESTEP mode */ #define NUMGENS 128 #undef ASM_DUMP @@ -72,12 +72,6 @@ #undef TRAP_RETRACE -/* If you undefine this, in 16-bit stack mode the high 16 bits of ESP - * will be zeroed after every push/pop operation. There's a small - * possibility of breaking some code, you can easily figure out how. - * For 32-bit stacks, keeping ESP is also a waste of time. */ -#define KEEP_ESP 1 - ///////////////////////////////////////////////////////////////////////////// #endif diff --git a/src/base/emu-i386/simx86/emu86.h b/src/base/emu-i386/simx86/emu86.h index e41fbfc..b0f0f5f 100644 --- a/src/base/emu-i386/simx86/emu86.h +++ b/src/base/emu-i386/simx86/emu86.h @@ -45,17 +45,11 @@ #include "cpu-emu.h" #include "syncpu.h" -#if PROFILE +#ifdef PROFILE extern hitimer_t AddTime, SearchTime, ExecTime, CleanupTime; extern hitimer_t GenTime, LinkTime; #endif -#ifdef X86_JIT -#define CONFIG_CPUSIM (config.cpusim || (CEmuStat & CeS_INSTREMU)) -#else -#define CONFIG_CPUSIM 1 -#endif - /* octal digits in a byte: hhmm.mlll */ #define D_HO(b) (((b)>>6)&3) #define D_MO(b) (((b)>>3)&7) @@ -667,6 +661,19 @@ extern hitimer_t GenTime, LinkTime; ///////////////////////////////////////////////////////////////////////////// +extern int eTimeCorrect; + +/* the amount of stretching (backtracing in time) to perform must be + * empirically determined. The full backtrace is maybe too much since + * we synchronize on the slower emulated time, while not stretching + * makes the time going too fast for the emulator. 1/2 is probably a + * good compromise, but it depends on the target machine too. + */ +#define E_TIME_STRETCH if (eTimeCorrect>=0) { hitimer_t t0=GETTSC();\ + if (t0 > TheCPU.EMUtime) \ + ZeroTimeBase.td += (TSCtoUS(t0 - TheCPU.EMUtime) >> eTimeCorrect);\ + TheCPU.EMUtime = t0; } + #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif @@ -679,7 +686,9 @@ extern hitimer_t GenTime, LinkTime; #ifndef PAGE_SIZE #define PAGE_SIZE (1UL << PAGE_SHIFT) #endif -#define _PAGE_MASK (~(PAGE_SIZE-1)) +#ifndef PAGE_MASK +#define PAGE_MASK (~(PAGE_SIZE-1)) +#endif ///////////////////////////////////////////////////////////////////////////// // @@ -716,7 +725,7 @@ int ModGetReg1(unsigned int PC, int mode); // char *e_emu_disasm(unsigned char *org, int is32, unsigned int refseg); char *e_print_regs(void); -char *e_print_scp_regs(cpuctx_t *scp, int pmode); +char *e_print_scp_regs(sigcontext_t *scp, int pmode); const char *e_trace_fp(void); void GCPrint(unsigned char *cp, unsigned char *cbase, int len); char *showreg(signed char r); @@ -740,13 +749,12 @@ void CollectStat(void); // ///////////////////////////////////////////////////////////////////////////// #ifdef HOST_ARCH_X86 -int e_handle_pagefault(dosaddr_t addr, unsigned err, sigcontext_t *scp); -int e_handle_fault(sigcontext_t *scp); void init_emu_npu_x86(void); #endif void init_emu_npu(void); void e_VgaMovs(unsigned char **rdi, unsigned char **rsi, unsigned int rep, int dp, unsigned int access); +int e_vgaemu_fault(sigcontext_t *scp, unsigned page_fault); #endif // _EMU86_EMU86_H diff --git a/src/base/emu-i386/simx86/fp87-sim.c b/src/base/emu-i386/simx86/fp87-sim.c index e6d2074..257a255 100644 --- a/src/base/emu-i386/simx86/fp87-sim.c +++ b/src/base/emu-i386/simx86/fp87-sim.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ @@ -39,43 +39,12 @@ #include "emu86.h" #include "codegen.h" #include "codegen-sim.h" -#include "softfloat/softfloat.h" - -#define FPUS_IE (1 << 0) -#define FPUS_DE (1 << 1) -#define FPUS_ZE (1 << 2) -#define FPUS_OE (1 << 3) -#define FPUS_UE (1 << 4) -#define FPUS_PE (1 << 5) -#define FPUS_SF (1 << 6) -#define FPUS_ES (1 << 7) -#define FPUS_C0 (1 << 8) -#define FPUS_C1 (1 << 9) -#define FPUS_C2 (1 << 10) -#define FPUS_TOP ((1 << 11) | (1 << 12) | (1 << 13)) -#define FPUS_TOP_BIT 11 -#define FPUS_C3 (1 << 14) -#define FPUS_B (1 << 15) -#define FPUS_C (FPUS_C0 | FPUS_C1 | FPUS_C2 | FPUS_C3) - -// These are GNU extensions, so define them here if not already -#ifndef M_PIl -#define M_PIl 3.141592653589793238462643383279502884L -#endif -#ifndef M_LN2l -#define M_LN2l 0.693147180559945309417232121458176568L -#endif -#ifndef M_LN10l -#define M_LN10l 2.302585092994045684017991454684364208L -#endif -#ifndef M_LOG2El -#define M_LOG2El 1.442695040888963407359924681001892137L -#endif int (*Fp87_op)(int exop, int reg); static int Fp87_op_sim(int exop, int reg); static long double WFR0, WFR1; +static unsigned short WFRS; #define S_next(r) (((r)+1)&7) #define S_prev(r) (((r)-1)&7) @@ -87,7 +56,7 @@ static long double WFR0, WFR1; /* Note: 0 / special values for tag word are only done for FSTENV and FSAVE */ #define FREETAG(n) TheCPU.fptag |= (3 << 2*S_reg(TheCPU.fpstt,n)) #define UNFREETAG(n) TheCPU.fptag &= ~(3 << 2*S_reg(TheCPU.fpstt,n)) -#define SYNCFSP TheCPU.fpus=(TheCPU.fpus&~FPUS_TOP)|(TheCPU.fpstt<> 2*S_reg(TheCPU.fpstt,0)) & 3) == 3) - fps |= 0x4100; // empty - else if (!iscanonical(d)) - fps |= isnan(d) ? 0x0 : 0x4400; // pseudo normal/denormal - else switch(fpclassify(d)) { - case FP_NAN: - fps |= FPUS_C0; - break; - case FP_INFINITE: - fps |= FPUS_C0 | FPUS_C2; - break; - case FP_ZERO: - fps |= FPUS_C3; - break; - case FP_SUBNORMAL: - fps |= FPUS_C2 | FPUS_C3; - break; - case FP_NORMAL: - default: - fps |= FPUS_C2; - break; - } - if (signbit(d)) fps |= FPUS_C1; - TheCPU.fpus = (fps&~FPUS_TOP)|(TheCPU.fpstt< WFR1); /* do nothing */ - else /* not comparable */ - TheCPU.fpus |= FPUS_C0 | FPUS_C2 | FPUS_C3; + else /* not comparable */ TheCPU.fpus |= 0x4500; break; case 0x11: case 0x19: write_float(AR1.d, WFR0); break; @@ -432,26 +353,22 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); case 0x1b: case 0x17: case 0x1f: { - WFR0 = nearbyintl(WFR0); + round_double(); if (exop & 4) { if (isnan(WFR0) || isinf(WFR0) || WFR0 < (long double)-0x8000 || WFR0 > (long double)0x7fff) { - TheCPU.fpus |= FPUS_IE; + TheCPU.fpus |= 1; WFR0 = (long double)-0x8000; } - else if (WFR0 != *ST0) /* flag inexact */ - TheCPU.fpus |= FPUS_PE; write_word(AR1.d, (int16_t)WFR0); break; } if (isnan(WFR0) || isinf(WFR0) || WFR0 < -(long double)0x80000000 || WFR0 > (long double)0x7fffffff) { - TheCPU.fpus |= FPUS_IE; + TheCPU.fpus |= 1; WFR0 = -(long double)0x80000000; } - else if (WFR0 != *ST0) /* flag inexact */ - TheCPU.fpus |= FPUS_PE; write_dword(AR1.d, (int32_t)WFR0); break; } } if (exop&8) INCFSPP; @@ -463,20 +380,10 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); long long b; int i; WFR0 = *ST0; - WFR0 = nearbyintl(WFR0); - if (isnan(WFR0) || fabsl(WFR0) >= 1000000000000000000.0L) { - /* store packed BCD indefinite value */ - write_dword(p, 0); - write_word(p+4, 0); - write_dword(p+6, 0xffffc000u); - TheCPU.fpus |= FPUS_IE; - INCFSPP; - break; - } - else if (WFR0 != *ST0) - TheCPU.fpus |= FPUS_PE; - write_byte(p+9, signbit(WFR0) ? 0x80 : 0); - b = fabsl(WFR0); + round_double(); + b = WFR0; + write_byte(p+9, b < 0 ? 0x80 : 0); + b = llabs(b); for (i=0; i < 9; i++) { uint8_t u = b % 10; b /= 10; @@ -495,15 +402,13 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); /*3f*/ case 0x3f: { // 3F DF xx111nnn FISTP qw WFR0 = *ST0; - WFR0 = nearbyintl(WFR0); + round_double(); if (isnan(WFR0) || isinf(WFR0) || WFR0 < (long double)(long long)0x8000000000000000ULL || WFR0 > (long double)(long long)0x7fffffffffffffffULL) { - TheCPU.fpus |= FPUS_IE; + TheCPU.fpus |= 1; WFR0 = (long double)(long long)0x8000000000000000ULL; } - else if (WFR0 != *ST0) - TheCPU.fpus |= FPUS_PE; write_qword(AR1.d, (int64_t)WFR0); INCFSPP; } @@ -511,7 +416,6 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); /*29*/ case 0x29: //* 29 D9 xx101nnn FLDCW 2b TheCPU.fpuc = read_word(AR1.d) | 0x40; - fp87_set_rounding(); break; /*39*/ case 0x39: //* 39 D9 xx111nnn FSTCW 2b @@ -529,7 +433,6 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); // shll 11,ecx // orl ecx,eax SYNCFSP; - fp87_save_except(); if (exop==0x3d) { // movw ax,(edi) write_word(AR1.d, TheCPU.fpus); @@ -561,6 +464,7 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); case 0x70: WFR0 /= WFR1; break; case 0x78: WFR0 = WFR1 / WFR0; break; } + ftest(WFR0); *ST0 = WFR0; break; @@ -570,14 +474,13 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); //* 58 D8 11011nnn FCOMP st,st(n) WFR0 = *ST0; WFR1 = *STn(reg); - TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); + TheCPU.fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */ if (WFR0 < WFR1) - TheCPU.fpus |= FPUS_C0; + TheCPU.fpus |= 0x100; /* (C3,C2,C0) <-- 001 */ else if (WFR0 == WFR1) - TheCPU.fpus |= FPUS_C3; + TheCPU.fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */ else if (WFR0 > WFR1); /* do nothing */ - else /* not comparable */ - TheCPU.fpus |= FPUS_C0 | FPUS_C2 | FPUS_C3; + else /* not comparable */ TheCPU.fpus |= 0x4500; if (exop&8) INCFSPP; break; @@ -589,13 +492,13 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); // 6A.1 DA 11101001 FUCOMPP WFR0 = *ST0; WFR1 = *STn(reg); - TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); - if (isnan(WFR0) || isnan(WFR1)) /* avoids FE_INVALID for QNaN */ - TheCPU.fpus |= FPUS_C0 | FPUS_C2 | FPUS_C3; - else if (WFR0 < WFR1) - TheCPU.fpus |= FPUS_C0; + TheCPU.fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */ + if (WFR0 < WFR1) + TheCPU.fpus |= 0x100; /* (C3,C2,C0) <-- 001 */ else if (WFR0 == WFR1) - TheCPU.fpus |= FPUS_C3; + TheCPU.fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */ + else if (WFR0 > WFR1); /* do nothing */ + else /* not comparable */ TheCPU.fpus |= 0x4500; if (exop==0x6a) INCFSPP; if (exop>=0x6a) INCFSPP; break; @@ -609,14 +512,13 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); // 5E.1 DE 11011001 FCOMPP WFR0 = *ST0; WFR1 = *ST1; - TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); + TheCPU.fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */ if (WFR0 < WFR1) - TheCPU.fpus |= FPUS_C0; + TheCPU.fpus |= 0x100; /* (C3,C2,C0) <-- 001 */ else if (WFR0 == WFR1) - TheCPU.fpus |= FPUS_C3; + TheCPU.fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */ else if (WFR0 > WFR1); /* do nothing */ - else /* not comparable */ - TheCPU.fpus |= FPUS_C0 | FPUS_C2 | FPUS_C3; + else /* not comparable */ TheCPU.fpus |= 0x4500; INCFSPP; INCFSPP; } @@ -641,6 +543,7 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); } *STn(reg) = WFR1; if (exop&2) INCFSPP; + ftest(WFR1); break; /*64*/ case 0x64: @@ -673,6 +576,7 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); } *STn(reg) = WFR1; if (exop&2) INCFSPP; + ftest(WFR1); break; /*41*/ case 0x41: @@ -721,25 +625,22 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); WFR0 = *ST0; switch(reg) { case 0: /* FCHS */ - TheCPU.fpus &= ~FPUS_C1; WFR0 = -WFR0; break; case 1: /* FABS */ - TheCPU.fpus &= ~FPUS_C1; WFR0 = fabsl(WFR0); break; case 4: /* FTST */ - TheCPU.fpus &= ~FPUS_C; - if (WFR0 < 0.0) TheCPU.fpus |= FPUS_C0; - else if (WFR0 == 0.0) TheCPU.fpus |= FPUS_C3; + TheCPU.fpus &= (~0x4500); + if (WFR0 < 0.0) TheCPU.fpus |= 0x100; + else if (WFR0 == 0.0) TheCPU.fpus |= 0x4000; else if (WFR0 > 0.0); /* do nothing; */ - else /* not comparable */ - TheCPU.fpus |= FPUS_C0 | FPUS_C2 | FPUS_C3; + else /* not comparable */ TheCPU.fpus |= 0x4500; break; case 5: /* FXAM */ - fxam(WFR0); break; default: goto fp_notok; } + if (reg != 4) ftest(WFR0); *ST0 = WFR0; break; @@ -747,16 +648,15 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); // 63.2* DB 11000010 FCLEX // 63.3* DB 11000011 FINIT case 2: /* FCLEX */ - TheCPU.fpus &= (FPUS_C | FPUS_TOP); - feclearexcept(FE_ALL_EXCEPT); + TheCPU.fpus &= 0x7f00; + __asm__ __volatile__ ("fnclex"); break; case 3: /* FINIT */ TheCPU.fpus = 0; TheCPU.fpstt = 0; TheCPU.fpuc = 0x37f; TheCPU.fptag = 0xffff; - fp87_set_rounding(); - feclearexcept(FE_ALL_EXCEPT); + __asm__ __volatile__ ("fninit"); WFR0 = WFR1 = 0.0; break; default: /* FNENI,FNDISI: 8087 */ @@ -776,14 +676,15 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); DECFSPP; switch (reg) { case 0: WFR0 = 1.0; break; - case 1: WFR0 = M_LN10l/M_LN2l; break; - case 2: WFR0 = M_LOG2El; break; - case 3: WFR0 = M_PIl; break; - case 4: WFR0 = M_LN2l/M_LN10l; break; - case 5: WFR0 = M_LN2l; break; + case 1: WFR0 = M_LN10/M_LN2; break; + case 2: WFR0 = M_LOG2E; break; + case 3: WFR0 = M_PI; break; + case 4: WFR0 = M_LN2/M_LN10; break; + case 5: WFR0 = M_LN2; break; case 6: WFR0 = 0.0; break; default: goto fp_notok; } + ftest(WFR0); *ST0 = WFR0; } break; @@ -799,78 +700,75 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); // 71.7 D9 11110111 FINCSTP case 0: /* F2XM1 */ WFR0 = *ST0; - WFR0 = expm1l(WFR0*M_LN2l); + __asm__ __volatile__ ( + "fldt %2\n" + "f2xm1\n" + "fnstsw %1\n" + "fstpt %0" : "=m"(WFR0),"=g"(WFRS) : "m"(WFR0) : "memory" ); + fssync(); *ST0 = WFR0; break; case 1: /* FYL2X */ WFR0 = *ST0; WFR1 = *ST1; - if (WFR0 < 0.0) { - WFR0 = -NAN; - TheCPU.fpus |= FPUS_IE; - } else if (WFR0 == 0.0) { - WFR0 = signbit(WFR1) ? INFINITY : -INFINITY; - TheCPU.fpus |= FPUS_ZE; - } else { - WFR0 = WFR1 * log2l(WFR0); - } + __asm__ __volatile__ ( + "fldt %2\n" + "fldt %3\n" + "fyl2x\n" + "fnstsw %1\n" + "fstpt %0" : "=m"(WFR0),"=g"(WFRS) : "m"(WFR1),"m"(WFR0) : "memory" ); INCFSPP; + fssync(); *ST0 = WFR0; break; case 3: /* FPATAN */ WFR0 = *ST0; WFR1 = *ST1; - WFR0 = atan2l(WFR1, WFR0); + __asm__ __volatile__ ( + "fldt %2\n" + "fldt %3\n" + "fpatan\n" + "fnstsw %1\n" + "fstpt %0" : "=m"(WFR0),"=g"(WFRS) : "m"(WFR1),"m"(WFR0) : "memory" ); INCFSPP; + fssync(); *ST0 = WFR0; break; case 2: /* FPTAN */ WFR0 = *ST0; - if (isfinite(WFR0) && fabsl(WFR0) >= 1ULL<<63) { - TheCPU.fpus |= FPUS_C2; - break; - } - WFR0 = tanl(WFR0); + __asm__ __volatile__ ( + "fldt %3\n" + "fptan\n" + "fnstsw %2\n" + "fstpt %1\n" + "fstpt %0" : "=m"(WFR0),"=m"(WFR1),"=g"(WFRS) : "m"(WFR0) : "memory" ); *ST0 = WFR0; DECFSPP; - TheCPU.fpus &= ~FPUS_C2; - *ST0 = 1.0; + fssync(); + *ST0 = WFR1; break; case 4: /* FXTRACT */ WFR0 = *ST0; - { - int exp; - WFR1 = frexpl(WFR0, &exp) * 2; - WFR0 = logbl(WFR0); - } + __asm__ __volatile__ ( + "fldt %3\n" + "fxtract\n" + "fnstsw %2\n" + "fstpt %1\n" + "fstpt %0" : "=m"(WFR0),"=m"(WFR1),"=g"(WFRS) : "m"(WFR0) : "memory" ); *ST0 = WFR0; DECFSPP; + fssync(); *ST0 = WFR1; break; case 5: /* FPREM1 */ WFR0 = *ST0; WFR1 = *ST1; - TheCPU.fpus &= ~FPUS_C; - if (!isfinite(WFR0) || WFR0 == 0.0 || - !isfinite(WFR1) || WFR1 == 0.0) - WFR0 = remainderl(WFR0, WFR1); - else { - int d = ilogbl(WFR0) - ilogbl(WFR1); - if (d < 64) { - int iq; - /* result from remquol not exactly the - same as remainderl in some strange - edge cases */ - remquol(WFR0, WFR1, &iq); - iq = abs(iq); - WFR0 = remainderl(WFR0, WFR1); - TheCPU.fpus |= ((iq & 1) << (9-0)) | - ((iq & 2) << (14-1)) | - ((iq & 4) << (8-2)); - } else { - int n = (d & 0x1f) | 0x20; - WFR0 = fmodl(WFR0, ldexpl(WFR1, d - n)); - TheCPU.fpus |= FPUS_C2; - } - } + __asm__ __volatile__ ( + "fldt %2\n" + "fldt %3\n" + "fprem1\n" + "fnstsw %1\n" + "fstpt %0\n" + "fstp %%st(0)" : "=m"(WFR0),"=g"(WFRS) : "m"(WFR1),"m"(WFR0) : "memory" ); + fssync(); *ST0 = WFR0; break; case 6: /* FDECSTP */ @@ -892,104 +790,88 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); case 0: /* FPREM */ WFR0 = *ST0; WFR1 = *ST1; - TheCPU.fpus &= ~FPUS_C; - if (!isfinite(WFR0) || WFR0 == 0.0 || - !isfinite(WFR1) || WFR1 == 0.0) - WFR0 = fmodl(WFR0, WFR1); - else { - int d = ilogbl(WFR0) - ilogbl(WFR1); - if (d < 64) { - unsigned iq; - int roundingmode = fegetround(); - fp87_save_except(); - fesetround(FE_TOWARDZERO); - iq = (uint64_t)fabsl(nearbyintl(WFR0 / WFR1)); - fesetround(roundingmode); - feclearexcept(FE_ALL_EXCEPT); - WFR0 = fmodl(WFR0, WFR1); - TheCPU.fpus |= ((iq & 1) << (9-0)) | - ((iq & 2) << (14-1)) | - ((iq & 4) << (8-2)); - } else { - int n = (d & 0x1f) | 0x20; - WFR0 = fmodl(WFR0, ldexpl(WFR1, d - n)); - TheCPU.fpus |= FPUS_C2; - } - } + __asm__ __volatile__ ( + "fldt %2\n" + "fldt %3\n" + "fprem\n" + "fnstsw %1\n" + "fstpt %0\n" + "fstp %%st(0)" : "=m"(WFR0),"=g"(WFRS) : "m"(WFR1),"m"(WFR0) : "memory" ); + fssync(); *ST0 = WFR0; break; case 5: /* FSCALE */ WFR0 = *ST0; WFR1 = *ST1; - if (isnan(WFR1) || - (WFR0 == 0.0 && isinf(WFR1) == 1) || - (isinf(WFR0) && isinf(WFR1) == -1)) - WFR0 = WFR1 = NAN; - else if (isfinite(WFR0)) { - int inf = isinf(WFR1); - if (inf == 1) - WFR0 = WFR0 > 0 ? INFINITY : -INFINITY; - else if (inf == -1) - WFR0 = WFR0 > 0 ? 0.0 : -0.0; - } - if (WFR1 >= INT_MAX) WFR1 = INT_MAX; - if (WFR1 <= INT_MIN) WFR1 = INT_MIN; - WFR0 = ldexpl(WFR0, WFR1); + __asm__ __volatile__ ( + "fldt %2\n" + "fldt %3\n" + "fscale\n" + "fnstsw %1\n" + "fstpt %0\n" + "fstp %%st(0)" : "=m"(WFR0),"=g"(WFRS) : "m"(WFR1),"m"(WFR0) : "memory" ); + fssync(); *ST0 = WFR0; break; case 1: /* FYL2XP1 */ WFR0 = *ST0; WFR1 = *ST1; - if (WFR0 > -1.0) - WFR0 = (WFR1 / M_LN2l) * log1pl(WFR0); + __asm__ __volatile__ ( + "fldt %2\n" + "fldt %3\n" + "fyl2xp1\n" + "fnstsw %1\n" + "fstpt %0" : "=m"(WFR0),"=g"(WFRS) : "m"(WFR1),"m"(WFR0) : "memory" ); INCFSPP; + fssync(); *ST0 = WFR0; break; case 2: /* FSQRT */ WFR0 = *ST0; - if (signbit(WFR0) && WFR0 != -0.0) { - if (!isnan(WFR0)) TheCPU.fpus |= FPUS_IE; - WFR0 = -NAN; - } else { - WFR0 = sqrtl(WFR0); - } + __asm__ __volatile__ ( + "fldt %2\n" + "fsqrt\n" + "fnstsw %1\n" + "fstpt %0" : "=m"(WFR0),"=g"(WFRS) : "m"(WFR0) : "memory" ); + fssync(); *ST0 = WFR0; break; case 4: /* FRNDINT */ WFR0 = *ST0; - WFR0 = rintl(WFR0); + round_double(); + ftest(WFR0); *ST0 = WFR0; break; case 6: /* FSIN */ WFR0 = *ST0; - if (isfinite(WFR0) && fabsl(WFR0) >= 1ULL<<63) { - TheCPU.fpus |= FPUS_C2; - break; - } - WFR0 = sinl(WFR0); - TheCPU.fpus &= ~FPUS_C2; + __asm__ __volatile__ ( + "fldt %2\n" + "fsin\n" + "fnstsw %1\n" + "fstpt %0" : "=m"(WFR0),"=g"(WFRS) : "m"(WFR0) : "memory" ); + fssync(); *ST0 = WFR0; break; case 7: /* FCOS */ WFR0 = *ST0; - if (isfinite(WFR0) && fabsl(WFR0) >= 1ULL<<63) { - TheCPU.fpus |= FPUS_C2; - break; - } - WFR0 = cosl(WFR0); - TheCPU.fpus &= ~FPUS_C2; + __asm__ __volatile__ ( + "fldt %2\n" + "fcos\n" + "fnstsw %1\n" + "fstpt %0" : "=m"(WFR0),"=g"(WFRS) : "m"(WFR0) : "memory" ); + fssync(); *ST0 = WFR0; break; case 3: /* FSINCOS */ WFR0 = *ST0; - if (isfinite(WFR0) && fabsl(WFR0) >= 1ULL<<63) { - TheCPU.fpus |= FPUS_C2; - break; - } - WFR1 = cosl(WFR0); - WFR0 = sinl(WFR0); + __asm__ __volatile__ ( + "fldt %3\n" + "fsincos\n" + "fnstsw %2\n" + "fstpt %1\n" + "fstpt %0" : "=m"(WFR0),"=m"(WFR1),"=g"(WFRS) : "m"(WFR0) : "memory" ); *ST0 = WFR0; DECFSPP; - TheCPU.fpus &= ~FPUS_C2; + fssync(); *ST0 = WFR1; break; } @@ -1001,8 +883,6 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); // 25 DD xx100nnn FRSTOR 94/108byte dosaddr_t p = TheCPU.mem_ref, q; TheCPU.fpuc = read_word(p) | 0x40; - feclearexcept(FE_ALL_EXCEPT); - fp87_set_rounding(); if (reg&DATA16) { TheCPU.fpus = read_word(p+2); TheCPU.fptag = read_word(p+4); q = p+14; @@ -1011,7 +891,7 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); TheCPU.fpus = read_word(p+4); TheCPU.fptag = read_word(p+8); q = p+28; } - TheCPU.fpstt = (TheCPU.fpus>>FPUS_TOP_BIT)&7; + TheCPU.fpstt = (TheCPU.fpus>>11)&7; if (exop==0x25) { int i, k; k = TheCPU.fpstt; @@ -1073,8 +953,7 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); unsigned fptag, ntag; //* 31 D9 xx110nnn FSTENV 14/28byte // 35 DD xx110nnn FSAVE 94/108byte - fp87_save_except(); - TheCPU.fpus = (TheCPU.fpus & ~FPUS_TOP) | (TheCPU.fpstt<=0; --i) { @@ -1117,8 +996,7 @@ fcom00: TheCPU.fpus &= ~(FPUS_C0 | FPUS_C2 | FPUS_C3); TheCPU.fpstt = 0; TheCPU.fpuc = 0x37f; TheCPU.fptag = 0xffff; - fp87_set_rounding(); - feclearexcept(FE_ALL_EXCEPT); + __asm__ __volatile__ ("fninit"); WFR0 = WFR1 = 0.0; } } diff --git a/src/base/emu-i386/simx86/fp87-x86.c b/src/base/emu-i386/simx86/fp87-x86.c index 0043f76..de5db1d 100644 --- a/src/base/emu-i386/simx86/fp87-x86.c +++ b/src/base/emu-i386/simx86/fp87-x86.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ @@ -194,13 +194,13 @@ unsigned char *Fp87_op_x86(unsigned char *CodePtr, int exop, int reg) // 3B DB xx111nnn FSTP ext // 3F DF xx111nnn FISTP qw fp_mem: - G3M(0xd8+(exop&7),(exop&0x38)|4,0x2f,Cp); // Fop (edi,ebp,1) + G2M(0xd8+(exop&7),(exop&0x38)|7,Cp); // Fop (edi) break; /*29*/ case 0x29: //* 29 D9 xx101nnn FLDCW 2b - // movw (edi,ebp,1),ax - G4(0x2f048b66,Cp); + // movw (edi),ax + G3(0x078b66,Cp); // movl eax,ecx G2(0xc189,Cp); // orb 0x3f,al @@ -228,8 +228,8 @@ fp_mem: G2(0xc808,Cp); // movw ax,FPUC(ebx) G3(0x438966,Cp); G1(Ofs_FPUC,Cp); - // movw ax,(edi,ebp,1) - G4(0x2f048966,Cp); + // movw ax,(edi) + G3(0x078966,Cp); break; /*3d*/ case 0x3d: goto fp_mem; diff --git a/src/base/emu-i386/simx86/host.h b/src/base/emu-i386/simx86/host.h index 0736fb1..9a3f282 100644 --- a/src/base/emu-i386/simx86/host.h +++ b/src/base/emu-i386/simx86/host.h @@ -108,6 +108,7 @@ static __inline__ void ppc_dswap8(long addr, unsigned long long val) ///////////////////////////////////////////////////////////////////////////// +#if defined(i386)||defined(__i386)||defined(__i386__)||defined(__x86_64__) #ifdef USE_BOUND /* `Fetch` is for CODE reads, `Get`/`Put` is for DATA. * WARNING - BOUND uses SIGNED limits!! */ @@ -172,8 +173,8 @@ static __inline__ void ppc_dswap8(long addr, unsigned long long val) #define GetDLong(a) read_dword(a) #define DataGetWL_U(m,a) ((m)&DATA16? GetDWord(a):GetDLong(a)) #define DataGetWL_S(m,a) ((m)&DATA16? (short)GetDWord(a):(int)GetDLong(a)) +#endif -#if 0 #if defined(ppc)||defined(__ppc)||defined(__ppc__) #define Fetch(a) *((unsigned char *)(a)) #define FetchW(a) ppc_pswap2((int)(a)) @@ -189,6 +190,7 @@ static __inline__ void ppc_dswap8(long addr, unsigned long long val) #define DataGetWL_S(m,a) ((m)&DATA16? (short)GetDWord(a):(int)GetDLong(a)) #endif +#if 0 /* general-purpose */ //static inline unsigned short pswap2(long a) { // register unsigned char *p = (unsigned char *)a; diff --git a/src/base/emu-i386/simx86/interp.c b/src/base/emu-i386/simx86/interp.c index 6beff9d..16a60f9 100644 --- a/src/base/emu-i386/simx86/interp.c +++ b/src/base/emu-i386/simx86/interp.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ @@ -41,14 +41,10 @@ #include "mhpdbg.h" #include "video.h" -#if PROFILE +#ifdef PROFILE int EmuSignals = 0; #endif -/* countdown to exit after handling VGAEMU faults, reset by - planar VGA reads and writes */ -static int interp_inst_emu_count; - static int ArOpsR[] = { O_ADD_R, O_OR_R, O_ADC_R, O_SBB_R, O_AND_R, O_SUB_R, O_XOR_R, O_CMP_R }; static int ArOpsFR[] = @@ -64,28 +60,16 @@ static char R1Tab_l[14] = #define INC_WL_PCA(m,i) PC=(PC+(i)+BT24(BitADDR16, m)) #define INC_WL_PC(m,i) PC=(PC+(i)+BT24(BitDATA16, m)) -static __inline__ unsigned long GetCPU_WL(int m, signed char o) +static __inline__ unsigned long GetCPU_WL(int m, char o) { if (m&DATA16) return CPUWORD(o); else return CPULONG(o); } -static __inline__ void SetCPU_WL(int m, signed char o, unsigned long v) +static __inline__ void SetCPU_WL(int m, char o, unsigned long v) { if (m&DATA16) CPUWORD(o)=v; else CPULONG(o)=v; } -static unsigned int DoCloseAndExec(unsigned int PC, int mode) -{ -#ifdef HOST_ARCH_X86 - if (!CONFIG_CPUSIM) { - unsigned P0 = InstrMeta[0].npc; - if (e_querymark(P0, PC - P0)) - InvalidateNodeRange(P0, PC - P0, NULL); - } -#endif - return CloseAndExec(PC, mode); -} - /* * close any pending instruction in the code cache and execute the * current sequence. @@ -95,26 +79,11 @@ static unsigned int DoCloseAndExec(unsigned int PC, int mode) * from P0, abort the current instruction and resume the parsing * loop at P2. */ -#ifdef HOST_ARCH_X86 -#define CODE_FLUSH2(m) { if (CONFIG_CPUSIM || CurrIMeta>0) {\ - unsigned int P2 = DoCloseAndExec(P0, m);\ +#define CODE_FLUSH() { if (CONFIG_CPUSIM || CurrIMeta>0) {\ + unsigned int P2 = CloseAndExec(P0, mode, __LINE__);\ if (TheCPU.err) return P2;\ - PC = P0 = P2;\ + if (!CONFIG_CPUSIM && P2 != P0) { PC=P2; continue; }\ } NewNode=0; } -#else -#define CODE_FLUSH2(m) { \ - unsigned int P2 = CloseAndExec(P0, m);\ - if (TheCPU.err) return P2;\ - NewNode=0; } -#endif -#ifdef HOST_ARCH_X86 -#define CODE_FLUSH() { if (CONFIG_CPUSIM || CurrIMeta>0) {\ - unsigned int P2 = DoCloseAndExec(P0, _mode);\ - if (TheCPU.err || P0 != P2) return P2;\ - } NewNode=0; } -#else -#define CODE_FLUSH() CODE_FLUSH2(_mode) -#endif #define UNPREFIX(m) ((m)&~(DATA16|ADDR16))|(basemode&(DATA16|ADDR16)) @@ -264,10 +233,8 @@ static unsigned int _JumpGen(unsigned int P2, int mode, int opc, } if (CONFIG_CPUSIM) Gen(JB_LINK, mode, opc, P2, j_t, j_nt); -#ifdef HOST_ARCH_X86 else Gen(JB_LINK, mode, opc, P2, j_t, j_nt, &InstrMeta[0].clink); -#endif } else { if (dsp == pskip) { @@ -283,10 +250,8 @@ static unsigned int _JumpGen(unsigned int P2, int mode, int opc, /* forward jump or backward jump >=256 bytes */ if (CONFIG_CPUSIM) Gen(JF_LINK, mode, opc, P2, j_t, j_nt); -#ifdef HOST_ARCH_X86 else Gen(JF_LINK, mode, opc, P2, j_t, j_nt, &InstrMeta[0].clink); -#endif } break; case JMPld: { /* uncond jmp far */ @@ -311,10 +276,8 @@ static unsigned int _JumpGen(unsigned int P2, int mode, int opc, if (dsp < 0) mode |= CKSIGN; if (CONFIG_CPUSIM) Gen(JMP_LINK, mode, opc, j_t, d_nt); -#ifdef HOST_ARCH_X86 else Gen(JMP_LINK, mode, opc, j_t, d_nt, &InstrMeta[0].clink); -#endif break; case CALLl: { /* call far */ unsigned short jcs = FetchW(P2 + pskip - 2); @@ -327,10 +290,8 @@ static unsigned int _JumpGen(unsigned int P2, int mode, int opc, case CALLd: /* call, unfortunately also uses JMP_LINK */ if (CONFIG_CPUSIM) Gen(JMP_LINK, mode, opc, j_t, d_nt); -#ifdef HOST_ARCH_X86 else Gen(JMP_LINK, mode, opc, j_t, d_nt, &InstrMeta[0].clink); -#endif break; case LOOP: case LOOPZ_LOOPE: case LOOPNZ_LOOPNE: if (dsp == 0) { @@ -347,10 +308,8 @@ static unsigned int _JumpGen(unsigned int P2, int mode, int opc, } if (CONFIG_CPUSIM) Gen(JLOOP_LINK, mode, opc, j_t, j_nt); -#ifdef HOST_ARCH_X86 else Gen(JLOOP_LINK, mode, opc, j_t, j_nt, &InstrMeta[0].clink); -#endif break; case RETl: case RETlisp: case JMPli: case CALLli: // far ret, indirect case INT: @@ -361,10 +320,8 @@ static unsigned int _JumpGen(unsigned int P2, int mode, int opc, case RET: case RETisp: case JMPi: case CALLi: // ret, indirect if (CONFIG_CPUSIM) Gen(JMP_INDIRECT, mode); -#ifdef HOST_ARCH_X86 else Gen(JMP_INDIRECT, mode, &InstrMeta[0].clink); -#endif break; default: dbug_printf("JumpGen: unknown condition\n"); break; @@ -380,12 +337,13 @@ static unsigned int _JumpGen(unsigned int P2, int mode, int opc, if (_P1 == (unsigned)-1) { \ if (!CONFIG_CPUSIM) \ NewIMeta(P0, &_rc); \ - _P1 = DoCloseAndExec(_P0, mode); \ + _P1 = CloseAndExec(_P0, mode, __LINE__); \ NewNode=0; \ } \ _P1; \ }) + ///////////////////////////////////////////////////////////////////////////// #if !defined(SINGLESTEP)&&defined(HOST_ARCH_X86) @@ -394,6 +352,12 @@ static unsigned int FindExecCode(unsigned int PC) int mode = TheCPU.mode; TNode *G; + if (CurrIMeta > 0) { // open code? + if (debug_level('e') > 2) + e_printf("============ Closing open sequence at %08x\n",PC); + PC = CloseAndExec(PC, mode, __LINE__); + if (TheCPU.err) return PC; + } /* for a sequence to be found, it must begin with * an allowable opcode. Look into table. * NOTE - this while can loop forever and stop @@ -428,17 +392,17 @@ static unsigned int FindExecCode(unsigned int PC) } /* ---- this is the MAIN EXECUTE point ---- */ NodesExecd++; -#if PROFILE +#ifdef PROFILE TotalNodesExecd++; #elif !defined(ASM_DUMP) /* try fast inner loop if nothing special is going on */ if (!(CEmuStat & (CeS_INHI|CeS_MOVSS)) && - !debug_level('e') && + !debug_level('e') && eTimeCorrect < 0 && GoodNode(G, mode) && !(G->flags & (F_FPOP|F_INHI))) PC = Exec_x86_fast(G); else #endif - PC = Exec_x86(G); + PC = Exec_x86(G, __LINE__); if (G->seqlen == 0) { error("CPU-EMU: Zero-len code node?\n"); break; @@ -451,7 +415,7 @@ static unsigned int FindExecCode(unsigned int PC) static void HandleEmuSignals(void) { -#if PROFILE +#ifdef PROFILE if (debug_level('e')) EmuSignals++; #endif if (CEmuStat & CeS_TRAP) { @@ -486,8 +450,6 @@ static void HandleEmuSignals(void) } static unsigned int _Interp86(unsigned int PC, int mod0); -static unsigned int InterpOne(unsigned int PC, int *_basemode, int *__mode, - int *_NewNode); unsigned int Interp86(unsigned int PC, int mod0) { @@ -501,13 +463,28 @@ unsigned int Interp86(unsigned int PC, int mod0) return ret; } -static unsigned int interp_pre(unsigned int PC, const int mode, int *_NewNode, - unsigned *_P0) +static unsigned int _Interp86(unsigned int PC, int basemode) { -#define NewNode (*_NewNode) -#define P0 (*_P0) + volatile unsigned int P0 = PC; /* volatile because of setjmp */ + unsigned char opc; + unsigned short ocs = TheCPU.cs; + unsigned int temp; + register int mode; + int NewNode; + + if (PROTMODE() && setjmp(jmp_env)) { + /* long jump to here from simulated page fault */ + return P0; + } + + NewNode = 0; + TheCPU.err = 0; + CEmuStat &= ~CeS_TRAP; + + while (Running) { OVERR_DS = Ofs_XDS; OVERR_SS = Ofs_XSS; + TheCPU.mode = mode = basemode; if (!NewNode) { if (CEmuStat & (CeS_TRAP|CeS_DRTRAP|CeS_SIGPEND|CeS_RPIC|CeS_STI)) { @@ -522,9 +499,8 @@ static unsigned int interp_pre(unsigned int PC, const int mode, int *_NewNode, unsigned int P2 = PC; if (NewNode) { P0 = PC; - CODE_FLUSH2(mode); + CODE_FLUSH(); } - assert(!NewNode); // don't exec with open node #ifndef SINGLESTEP if (!(EFLAGS & TF)) { P2 = FindExecCode(PC); @@ -558,124 +534,18 @@ static unsigned int interp_pre(unsigned int PC, const int mode, int *_NewNode, } else if (CONFIG_CPUSIM && debug_level('e') == 9) dbug_printf("\n%s",e_print_regs()); if (debug_level('e')>2) { - char *ds; - unsigned short ocs = TheCPU.cs; - ds = e_emu_disasm(MEM_BASE32(P0),(~mode&3),ocs); - if (debug_level('e')>2) e_printf(" %s\n", ds); + char *ds = e_emu_disasm(MEM_BASE32(P0),(~basemode&3),ocs); + ocs = TheCPU.cs; + if (debug_level('e')>2) e_printf(" %s\n", ds); } - return PC; -} - -static unsigned int interp_post(unsigned int PC, const int mode, - int *_NewNode, unsigned *_P0) -{ -#ifdef HOST_ARCH_X86 - if (NewNode) { - int rc=0; - if (!CONFIG_CPUSIM && !(TheCPU.mode&SKIPOP)) { - NewIMeta(P0, &rc); - if (rc < 0) { - if (debug_level('e')>2) - e_printf("============ Tab full:cannot close sequence\n"); - CODE_FLUSH2(mode); - NewIMeta(P0, &rc); - NewNode = 1; - } - } - } -#endif - -#ifdef SINGLEBLOCK - if (!CONFIG_CPUSIM && NewNode && CurrIMeta > 0) { - P0 = PC; - CODE_FLUSH2(mode); - } -#endif - - if (NewNode && (CEmuStat & CeS_TRAP)) { - P0 = PC; - CODE_FLUSH2(mode); - } - if (CEmuStat & (CeS_MOVSS|CeS_INSTREMU)) { - if (CEmuStat & CeS_MOVSS) { - /* following non-compiled (sim or protected mode) - mov ss / pop ss only */ - if (!(CEmuStat & CeS_INHI)) { - // directly following mov ss / pop ss - CEmuStat |= CeS_INHI; - CEmuStat &= ~CeS_TRAP; - } else { - // instruction after clear unconditionally - // even if it's another mov ss / pop ss - CEmuStat &= ~(CeS_INHI|CeS_MOVSS); - } - } - if ((CEmuStat & (CeS_INSTREMU|CeS_INHI)) == CeS_INSTREMU) { - if (debug_level('e')>1) - dbug_printf("CeS_INSTREMU, count=%d\n", - interp_inst_emu_count); - if (interp_inst_emu_count-- == 0) { - TheCPU.err = EXCP_GOBACK; - return PC; - } - } - } - return PC; -#undef P0 -#undef NewNode -} - -static unsigned int _Interp86(unsigned int PC, int basemode) -{ - volatile unsigned int P0 = PC; /* volatile because of setjmp */ - int mode; - int NewNode; - - if (PROTMODE() && setjmp(jmp_env)) { - /* long jump to here from simulated page fault */ - return P0; - } - - NewNode = 0; - TheCPU.err = 0; - CEmuStat &= ~CeS_TRAP; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" - while (Running) { - TheCPU.mode = mode = basemode; - PC = interp_pre(PC, mode, &NewNode, &P0); - if (TheCPU.err) - return PC; - PC = InterpOne(PC, &basemode, &mode, &NewNode); - if (TheCPU.err) - return PC; - PC = interp_post(PC, mode, &NewNode, &P0); - if (TheCPU.err) - return PC; - } -#pragma GCC diagnostic pop - return 0; -} - -static unsigned int InterpOne(unsigned int PC, int *_basemode, int *__mode, - int *_NewNode) -{ - unsigned int P0 = PC; - unsigned char opc; - unsigned int temp; - unsigned short ocs; - #define _mode (*__mode) - #define basemode (*_basemode) - #define NewNode (*_NewNode) override: - switch ((opc=Fetch(PC))) { + switch ((opc=Fetch(PC))) { /*28*/ case SUBbfrm: /*2a*/ case SUBbtrm: /*30*/ case XORbfrm: /*32*/ case XORbtrm: if (RmIsReg[Fetch(PC+1)]&2) { // same reg - Gen(O_CLEAR, _mode|MBYTE, R1Tab_b[Fetch(PC+1)&7]); + Gen(O_CLEAR, mode|MBYTE, R1Tab_b[Fetch(PC+1)&7]); PC+=2; break; } if (opc & 2) goto intop3a; else goto intop28; @@ -684,7 +554,7 @@ override: /*20*/ case ANDbfrm: /*22*/ case ANDbtrm: /*84*/ case TESTbrm: - { int m = _mode | MBYTE; + { int m = mode | MBYTE; if (RmIsReg[Fetch(PC+1)]&2) { // same reg Gen(O_TEST, m, R1Tab_b[Fetch(PC+1)&7]); PC+=2; break; @@ -698,14 +568,14 @@ override: break; /*18*/ case SBBbfrm: /*1a*/ case SBBbtrm: if (RmIsReg[Fetch(PC+1)]&2) { // same reg - Gen(O_SBSELF, _mode|MBYTE, R1Tab_b[Fetch(PC+1)&7]); + Gen(O_SBSELF, mode|MBYTE, R1Tab_b[Fetch(PC+1)&7]); PC+=2; break; } if (opc & 2) goto intop3a; /*00*/ case ADDbfrm: /*10*/ case ADCbfrm: /*38*/ case CMPbfrm: -intop28: { int m = _mode | MBYTE; +intop28: { int m = mode | MBYTE; PC += ModRM(opc, PC, m); // DI=mem if (TheCPU.mode & RM_REG) { int op = ArOpsFR[D_MO(opc)]; @@ -724,7 +594,7 @@ intop28: { int m = _mode | MBYTE; /*02*/ case ADDbtrm: /*12*/ case ADCbtrm: /*3a*/ case CMPbtrm: -intop3a: { int m = _mode | MBYTE; +intop3a: { int m = mode | MBYTE; int op = ArOpsFR[D_MO(opc)]; PC += ModRM(opc, PC, m|MLOAD); // al=[rm] Gen(op, m, REG1); // op [ebx+reg], al @@ -734,7 +604,7 @@ intop3a: { int m = _mode | MBYTE; /*2b*/ case SUBwtrm: /*31*/ case XORwfrm: /*33*/ case XORwtrm: if (RmIsReg[Fetch(PC+1)]&2) { // same reg - Gen(O_CLEAR, _mode, R1Tab_l[Fetch(PC+1)&7]); + Gen(O_CLEAR, mode, R1Tab_l[Fetch(PC+1)&7]); PC+=2; break; } if (opc & 2) goto intop3b; else goto intop29; @@ -743,36 +613,36 @@ intop3a: { int m = _mode | MBYTE; /*21*/ case ANDwfrm: /*23*/ case ANDwtrm: /*85*/ case TESTwrm: if (RmIsReg[Fetch(PC+1)]&2) { // same reg - Gen(O_TEST, _mode, R1Tab_l[Fetch(PC+1)&7]); + Gen(O_TEST, mode, R1Tab_l[Fetch(PC+1)&7]); PC+=2; break; } if (opc != TESTwrm) { if (opc & 2) goto intop3b; else goto intop29; } - PC += ModRM(opc, PC, _mode|MLOAD); // (e)ax=[rm] - Gen(O_AND_R, _mode, REG1); // op (e)ax,[ebx+reg] + PC += ModRM(opc, PC, mode|MLOAD); // (e)ax=[rm] + Gen(O_AND_R, mode, REG1); // op (e)ax,[ebx+reg] break; /*19*/ case SBBwfrm: /*1b*/ case SBBwtrm: if (RmIsReg[Fetch(PC+1)]&2) { // same reg - Gen(O_SBSELF, _mode, R1Tab_l[Fetch(PC+1)&7]); + Gen(O_SBSELF, mode, R1Tab_l[Fetch(PC+1)&7]); PC+=2; break; } if (opc & 2) goto intop3b; /*01*/ case ADDwfrm: /*11*/ case ADCwfrm: /*39*/ case CMPwfrm: -intop29: PC += ModRM(opc, PC, _mode); // DI=mem +intop29: PC += ModRM(opc, PC, mode); // DI=mem if (TheCPU.mode & RM_REG) { int op = ArOpsFR[D_MO(opc)]; - Gen(L_REG, _mode, REG1); // mov (e)ax,[ebx+reg] - Gen(op, _mode, REG3); // op [ebx+rmreg],(e)ax rmreg=rmreg op reg + Gen(L_REG, mode, REG1); // mov (e)ax,[ebx+reg] + Gen(op, mode, REG3); // op [ebx+rmreg],(e)ax rmreg=rmreg op reg } else { int op = ArOpsR[D_MO(opc)]; - Gen(L_DI_R1, _mode); // mov (e)ax,[edi] - Gen(op, _mode, REG1); // op (e)ax,[ebx+reg] + Gen(L_DI_R1, mode); // mov (e)ax,[edi] + Gen(op, mode, REG1); // op (e)ax,[ebx+reg] if (opc!=CMPwfrm) { - Gen(S_DI, _mode); // mov [edi],(e)ax mem=mem op reg + Gen(S_DI, mode); // mov [edi],(e)ax mem=mem op reg } } break; @@ -780,12 +650,12 @@ intop29: PC += ModRM(opc, PC, _mode); // DI=mem /*13*/ case ADCwtrm: /*3b*/ case CMPwtrm: intop3b: { int op = ArOpsFR[D_MO(opc)]; - PC += ModRM(opc, PC, _mode|MLOAD); // (e)ax=[rm] - Gen(op, _mode, REG1); // op [ebx+reg], (e)ax + PC += ModRM(opc, PC, mode|MLOAD); // (e)ax=[rm] + Gen(op, mode, REG1); // op [ebx+reg], (e)ax } break; /*a8*/ case TESTbi: { - int m = _mode | MBYTE; + int m = mode | MBYTE; Gen(L_IMM_R1, m, Fetch(PC+1)); PC+=2; // mov al,#imm Gen(O_AND_R, m, Ofs_AL); // op al,[ebx+reg] } @@ -798,16 +668,16 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*2c*/ case SUBbi: /*34*/ case XORbi: /*3c*/ case CMPbi: { - int m = _mode | MBYTE; + int m = mode | MBYTE; int op = ArOpsFR[D_MO(opc)]; // op [ebx+Ofs_EAX],#imm Gen(op, m|IMMED, Ofs_EAX, Fetch(PC+1)); PC+=2; } break; /*a9*/ case TESTwi: - Gen(L_IMM_R1, _mode|IMMED, DataFetchWL_U(_mode,PC+1)); - INC_WL_PC(_mode,1); - Gen(O_AND_R, _mode, Ofs_EAX); + Gen(L_IMM_R1, mode|IMMED, DataFetchWL_U(mode,PC+1)); + INC_WL_PC(mode,1); + Gen(O_AND_R, mode, Ofs_EAX); break; /*05*/ case ADDwia: /*0d*/ case ORwi: @@ -817,21 +687,21 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*2d*/ case SUBwi: /*35*/ case XORwi: /*3d*/ case CMPwi: { - int m = _mode; + int m = mode; int op = ArOpsFR[D_MO(opc)]; // op [ebx+Ofs_EAX],#imm - Gen(op, m|IMMED, Ofs_EAX, DataFetchWL_U(_mode,PC+1)); - INC_WL_PC(_mode,1); + Gen(op, m|IMMED, Ofs_EAX, DataFetchWL_U(mode,PC+1)); + INC_WL_PC(mode,1); } break; /*69*/ case IMULwrm: - PC += ModRM(opc, PC, _mode|MLOAD); // mov (e)ax,[rm] - Gen(O_IMUL,_mode|IMMED,DataFetchWL_S(_mode,PC),REG1); - INC_WL_PC(_mode, 0); + PC += ModRM(opc, PC, mode|MLOAD); // mov (e)ax,[rm] + Gen(O_IMUL,mode|IMMED,DataFetchWL_S(mode,PC),REG1); + INC_WL_PC(mode, 0); break; /*6b*/ case IMULbrm: - PC += ModRM(opc, PC, _mode|MLOAD); // mov (e)ax,[rm] - Gen(O_IMUL,_mode|MBYTE|IMMED,(signed char)Fetch(PC),REG1); + PC += ModRM(opc, PC, mode|MLOAD); // mov (e)ax,[rm] + Gen(O_IMUL,mode|MBYTE|IMMED,(signed char)Fetch(PC),REG1); PC++; break; @@ -846,35 +716,35 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; goto not_permitted; /* GPF */ temp = (EFLAGS|IOPL_MASK) & RETURN_MASK; if (EFLAGS & VIF) temp |= EFLAGS_IF; - PUSH(_mode, temp); + PUSH(mode, temp); if (debug_level('e')>1) e_printf("Pushed flags %08x fl=%08x\n", temp,EFLAGS); } else { - Gen(O_PUSH2F, _mode); + Gen(O_PUSH2F, mode); } PC++; } break; /*9e*/ case SAHF: - Gen(O_SLAHF, _mode, 1); + Gen(O_SLAHF, mode, 1); PC++; break; /*9f*/ case LAHF: - Gen(O_SLAHF, _mode, 0); + Gen(O_SLAHF, mode, 0); PC++; break; /*27*/ case DAA: - Gen(O_OPAX, _mode, 1, DAA); PC++; break; + Gen(O_OPAX, mode, 1, DAA); PC++; break; /*2f*/ case DAS: - Gen(O_OPAX, _mode, 1, DAS); PC++; break; + Gen(O_OPAX, mode, 1, DAS); PC++; break; /*37*/ case AAA: - Gen(O_OPAX, _mode, 1, AAA); PC++; break; + Gen(O_OPAX, mode, 1, AAA); PC++; break; /*3f*/ case AAS: - Gen(O_OPAX, _mode, 1, AAS); PC++; break; + Gen(O_OPAX, mode, 1, AAS); PC++; break; /*d4*/ case AAM: - Gen(O_OPAX, _mode, 2, AAM, Fetch(PC+1)); PC+=2; break; + Gen(O_OPAX, mode, 2, AAM, Fetch(PC+1)); PC+=2; break; /*d5*/ case AAD: - Gen(O_OPAX, _mode, 2, AAD, Fetch(PC+1)); PC+=2; break; + Gen(O_OPAX, mode, 2, AAD, Fetch(PC+1)); PC+=2; break; /*d6*/ case 0xd6: /* Undocumented */ CODE_FLUSH(); @@ -887,11 +757,11 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; if (Fetch(PC+1) >= 0xc0) { goto not_permitted; } - PC += ModRMSim(PC, _mode); - r = GetCPU_WL(_mode, REG1); - lo = DataGetWL_S(_mode,TheCPU.mem_ref); - TheCPU.mem_ref += BT24(BitDATA16, _mode); - hi = DataGetWL_S(_mode,TheCPU.mem_ref); + PC += ModRMSim(PC, mode); + r = GetCPU_WL(mode, REG1); + lo = DataGetWL_S(mode,TheCPU.mem_ref); + TheCPU.mem_ref += BT24(BitDATA16, mode); + hi = DataGetWL_S(mode,TheCPU.mem_ref); if(r < lo || r > hi) { e_printf("Bound interrupt 05\n"); @@ -903,13 +773,13 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*63*/ case ARPL: { unsigned short dest, src; CODE_FLUSH(); - PC += ModRMSim(PC, _mode); + PC += ModRMSim(PC, mode); if (TheCPU.mode & RM_REG) { dest = CPUWORD(REG3); } else { dest = GetDWord(TheCPU.mem_ref); } - src = GetCPU_WL(_mode, REG1); + src = GetCPU_WL(mode, REG1); if ((dest & 3) < (src & 3)) { EFLAGS |= EFLAGS_ZF; dest = (dest & ~3) | (src & 3); @@ -925,57 +795,57 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; break; } /*d7*/ case XLAT: - Gen(O_XLAT, _mode); - Gen(L_DI_R1, _mode|MBYTE); - Gen(S_REG, _mode|MBYTE, Ofs_AL); + Gen(O_XLAT, mode); + Gen(L_DI_R1, mode|MBYTE); + Gen(S_REG, mode|MBYTE, Ofs_AL); PC++; break; /*98*/ case CBW: - Gen(O_CBWD, _mode|MBYTE); PC++; break; + Gen(O_CBWD, mode|MBYTE); PC++; break; /*99*/ case CWD: - Gen(O_CBWD, _mode); PC++; break; + Gen(O_CBWD, mode); PC++; break; /*07*/ case POPes: if (REALADDR()) { - Gen(O_POP, _mode); - Gen(S_REG, _mode, Ofs_ES); - AddrGen(A_SR_SH4, _mode, Ofs_ES, Ofs_XES); + Gen(O_POP, mode); + Gen(S_REG, mode, Ofs_ES); + AddrGen(A_SR_SH4, mode, Ofs_ES, Ofs_XES); } else { /* restartable */ unsigned short sv = 0; CODE_FLUSH(); - TOS_WORD(_mode, &sv); - TheCPU.err = MAKESEG(_mode, Ofs_ES, sv); + TOS_WORD(mode, &sv); + TheCPU.err = MAKESEG(mode, Ofs_ES, sv); if (TheCPU.err) return P0; - POP_ONLY(_mode); + POP_ONLY(mode); TheCPU.es = sv; } PC++; break; /*17*/ case POPss: if (REALADDR()) { - Gen(O_POP, _mode); - Gen(S_REG, _mode, Ofs_SS); - AddrGen(A_SR_SH4, _mode, Ofs_SS, Ofs_XSS); + Gen(O_POP, mode); + Gen(S_REG, mode, Ofs_SS); + AddrGen(A_SR_SH4, mode, Ofs_SS, Ofs_XSS); } else { /* restartable */ unsigned short sv = 0; CODE_FLUSH(); - TOS_WORD(_mode, &sv); - TheCPU.err = MAKESEG(_mode, Ofs_SS, sv); + TOS_WORD(mode, &sv); + TheCPU.err = MAKESEG(mode, Ofs_SS, sv); if (TheCPU.err) return P0; - POP_ONLY(_mode); + POP_ONLY(mode); TheCPU.ss = sv; CEmuStat |= CeS_MOVSS; } PC++; break; /*1f*/ case POPds: if (REALADDR()) { - Gen(O_POP, _mode); - Gen(S_REG, _mode, Ofs_DS); - AddrGen(A_SR_SH4, _mode, Ofs_DS, Ofs_XDS); + Gen(O_POP, mode); + Gen(S_REG, mode, Ofs_DS); + AddrGen(A_SR_SH4, mode, Ofs_DS, Ofs_XDS); } else { /* restartable */ unsigned short sv = 0; CODE_FLUSH(); - TOS_WORD(_mode, &sv); - TheCPU.err = MAKESEG(_mode, Ofs_DS, sv); + TOS_WORD(mode, &sv); + TheCPU.err = MAKESEG(mode, Ofs_DS, sv); if (TheCPU.err) return P0; - POP_ONLY(_mode); + POP_ONLY(mode); TheCPU.ds = sv; } PC++; @@ -994,14 +864,14 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*65*/ case SEGgs: OVERR_DS = OVERR_SS = Ofs_XGS; PC++; goto override; /*66*/ case OPERoverride: /* 0x66: 32 bit operand, 16 bit addressing */ - _mode = (_mode & ~DATA16) | (~basemode & DATA16); + mode = (mode & ~DATA16) | (~basemode & DATA16); if (debug_level('e')>4) - e_printf("OPERoverride: new _mode %04x\n",_mode); + e_printf("OPERoverride: new mode %04x\n",mode); PC++; goto override; /*67*/ case ADDRoverride: /* 0x67: 16 bit operand, 32 bit addressing */ - _mode = (_mode & ~ADDR16) | (~basemode & ADDR16); + mode = (mode & ~ADDR16) | (~basemode & ADDR16); if (debug_level('e')>4) - e_printf("ADDRoverride: new _mode %04x\n",_mode); + e_printf("ADDRoverride: new mode %04x\n",mode); PC++; goto override; /*f0*/ case LOCK: { int i = 1; unsigned char op; @@ -1041,12 +911,6 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; op == 0x86 || op == 0x87) { /*XCHG, not NOP*/ PC++; goto override; } - else if (op >= 0x80 && op <= 0x83) { /*ADD..XOR*/ - op = Fetch(PC+i); - if ((op & 0x38) < 0x38) { - PC++; goto override; - } - } CODE_FLUSH(); goto illegal_op; } @@ -1058,7 +922,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*45*/ case INCbp: /*46*/ case INCsi: /*47*/ case INCdi: - Gen(O_INC_R, _mode, R1Tab_l[D_LO(opc)]); PC++; break; + Gen(O_INC_R, mode, R1Tab_l[D_LO(opc)]); PC++; break; /*48*/ case DECax: /*49*/ case DECcx: /*4a*/ case DECdx: @@ -1067,7 +931,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*4d*/ case DECbp: /*4e*/ case DECsi: /*4f*/ case DECdi: - Gen(O_DEC_R, _mode, R1Tab_l[D_LO(opc)]); PC++; break; + Gen(O_DEC_R, mode, R1Tab_l[D_LO(opc)]); PC++; break; /*06*/ case PUSHes: /*0e*/ case PUSHcs: @@ -1083,7 +947,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*57*/ case PUSHdi: opc = OpIsPush[opc]; #ifndef SINGLESTEP if (!(EFLAGS & TF)) { - int m = _mode; // enter with prefix + int m = mode; // enter with prefix int cnt = 2; int is_66; Gen(O_PUSH1, m); @@ -1109,39 +973,39 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; Gen(O_PUSH3, m); } else #endif { - Gen(L_REG, _mode, R1Tab_l[opc-1]); - Gen(O_PUSH, _mode); PC++; + Gen(L_REG, mode, R1Tab_l[opc-1]); + Gen(O_PUSH, mode); PC++; } break; /*68*/ case PUSHwi: - Gen(O_PUSHI, _mode, DataFetchWL_U(_mode,(PC+1))); - INC_WL_PC(_mode,1); + Gen(O_PUSHI, mode, DataFetchWL_U(mode,(PC+1))); + INC_WL_PC(mode,1); break; /*6a*/ case PUSHbi: - Gen(O_PUSHI, _mode, (signed char)Fetch(PC+1)); PC+=2; break; + Gen(O_PUSHI, mode, (signed char)Fetch(PC+1)); PC+=2; break; /*60*/ case PUSHA: /* push order: eax ecx edx ebx esp ebp esi edi */ - Gen(O_PUSH1, _mode); - Gen(O_PUSH2, _mode, Ofs_EAX); - Gen(O_PUSH2, _mode, Ofs_ECX); - Gen(O_PUSH2, _mode, Ofs_EDX); - Gen(O_PUSH2, _mode, Ofs_EBX); - Gen(O_PUSH2, _mode, Ofs_ESP); - Gen(O_PUSH2, _mode, Ofs_EBP); - Gen(O_PUSH2, _mode, Ofs_ESI); - Gen(O_PUSH2, _mode, Ofs_EDI); - Gen(O_PUSH3, _mode); PC++; break; + Gen(O_PUSH1, mode); + Gen(O_PUSH2, mode, Ofs_EAX); + Gen(O_PUSH2, mode, Ofs_ECX); + Gen(O_PUSH2, mode, Ofs_EDX); + Gen(O_PUSH2, mode, Ofs_EBX); + Gen(O_PUSH2, mode, Ofs_ESP); + Gen(O_PUSH2, mode, Ofs_EBP); + Gen(O_PUSH2, mode, Ofs_ESI); + Gen(O_PUSH2, mode, Ofs_EDI); + Gen(O_PUSH3, mode); PC++; break; /*61*/ case POPA: - Gen(O_POP1, _mode); - Gen(O_POP2, _mode, Ofs_EDI); - Gen(O_POP2, _mode, Ofs_ESI); - Gen(O_POP2, _mode, Ofs_EBP); - Gen(O_POP2, _mode, Ofs_ESP); // overwritten in O_POP3 - Gen(O_POP2, _mode, Ofs_EBX); - Gen(O_POP2, _mode, Ofs_EDX); - Gen(O_POP2, _mode, Ofs_ECX); - Gen(O_POP2, _mode, Ofs_EAX); - Gen(O_POP3, _mode); PC++; break; + Gen(O_POP1, mode); + Gen(O_POP2, mode, Ofs_EDI); + Gen(O_POP2, mode, Ofs_ESI); + Gen(O_POP2, mode, Ofs_EBP); + Gen(O_POP2, mode, Ofs_ESP); // overwritten in O_POP3 + Gen(O_POP2, mode, Ofs_EBX); + Gen(O_POP2, mode, Ofs_EDX); + Gen(O_POP2, mode, Ofs_ECX); + Gen(O_POP2, mode, Ofs_EAX); + Gen(O_POP3, mode); PC++; break; /*58*/ case POPax: /*59*/ case POPcx: @@ -1153,7 +1017,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*5f*/ case POPdi: #ifndef SINGLESTEP if (!(EFLAGS & TF)) { - int m = _mode; + int m = mode; int cnt = 2; Gen(O_POP1, m); do { @@ -1170,29 +1034,29 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; } else #endif { - Gen(O_POP, _mode); - Gen(S_REG, _mode, R1Tab_l[D_LO(opc)]); PC++; + Gen(O_POP, mode); + Gen(S_REG, mode, R1Tab_l[D_LO(opc)]); PC++; } break; /*8f*/ case POPrm: // now calculate address. This way when using %esp // as index we use the value AFTER the pop - PC += ModRM(opc, PC, _mode|MPOPRM); + PC += ModRM(opc, PC, mode|MPOPRM); if (TheCPU.mode & RM_REG) { // pop data into temporary storage and adjust esp - Gen(O_POP, _mode); + Gen(O_POP, mode); // store data - Gen(S_REG, _mode, REG3); + Gen(S_REG, mode, REG3); } else { // read data into temporary storage - Gen(O_POP1, _mode); - Gen(O_POP2, _mode|MPOPRM, 0); + Gen(O_POP1, mode); + Gen(O_POP2, mode|MPOPRM, 0); // store data // S_DI may fault, in which case the instruction // may need to be restarted with the original // value of ESP! - Gen(S_DI, _mode); // mov [edi],{e}ax - Gen(O_POP3, _mode|MPOPRM); + Gen(S_DI, mode); // mov [edi],{e}ax + Gen(O_POP3, mode|MPOPRM); } break; @@ -1217,14 +1081,14 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*e1*/ case LOOPZ_LOOPE: /*e2*/ case LOOP: /*e3*/ case JCXZ: { - PC = JumpGen(PC, _mode, opc, 2); + PC = JumpGen(PC, mode, opc, 2); if (TheCPU.err) return PC; } break; /*82*/ case IMMEDbrm2: // add mem8,signed imm8: no AND,OR,XOR /*80*/ case IMMEDbrm: { - int m = _mode | MBYTE; + int m = mode | MBYTE; int op = D_MO(Fetch(PC+1)); PC += ModRM(opc, PC, m); if (TheCPU.mode & RM_REG) { @@ -1243,70 +1107,70 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; break; /*81*/ case IMMEDwrm: { int op = D_MO(Fetch(PC+1)); - PC += ModRM(opc, PC, _mode); + PC += ModRM(opc, PC, mode); if (TheCPU.mode & RM_REG) { op = ArOpsFR[op]; // op [ebx+reg],#imm - Gen(op, _mode|IMMED, REG3, DataFetchWL_U(_mode,PC)); + Gen(op, mode|IMMED, REG3, DataFetchWL_U(mode,PC)); } else { op = ArOpsR[op]; - Gen(L_DI_R1, _mode); // mov ax,[edi] - Gen(op, _mode|IMMED, DataFetchWL_U(_mode,PC)); // op ax,#imm + Gen(L_DI_R1, mode); // mov ax,[edi] + Gen(op, mode|IMMED, DataFetchWL_U(mode,PC)); // op ax,#imm if (op!=O_CMP_R) - Gen(S_DI, _mode);// mov [edi],ax mem=mem op #imm + Gen(S_DI, mode);// mov [edi],ax mem=mem op #imm } - INC_WL_PC(_mode,0); + INC_WL_PC(mode,0); } break; /*83*/ case IMMEDisrm: { int op = D_MO(Fetch(PC+1)); long v; - PC += ModRM(opc, PC, _mode); + PC += ModRM(opc, PC, mode); v = (signed char)Fetch(PC); if (TheCPU.mode & RM_REG) { op = ArOpsFR[op]; // op [ebx+reg],#imm - Gen(op, _mode|IMMED, REG3, v); + Gen(op, mode|IMMED, REG3, v); } else { op = ArOpsR[op]; - Gen(L_DI_R1, _mode); // mov ax,[edi] - Gen(op, _mode|IMMED, v); // op ax,#imm + Gen(L_DI_R1, mode); // mov ax,[edi] + Gen(op, mode|IMMED, v); // op ax,#imm if (op != O_CMP_R) - Gen(S_DI, _mode);// mov [edi],ax mem=mem op #imm + Gen(S_DI, mode);// mov [edi],ax mem=mem op #imm } PC++; } break; /*86*/ case XCHGbrm: if (RmIsReg[Fetch(PC+1)]&2) { - Gen(L_NOP, _mode); PC+=2; + Gen(L_NOP, mode); PC+=2; } else { - PC += ModRM(opc, PC, _mode|MBYTE|MLOAD);// al=[rm] + PC += ModRM(opc, PC, mode|MBYTE|MLOAD);// al=[rm] if (TheCPU.mode & RM_REG) { - Gen(O_XCHG, _mode|MBYTE, REG1); - Gen(S_REG, _mode|MBYTE, REG3); + Gen(O_XCHG, mode|MBYTE, REG1); + Gen(S_REG, mode|MBYTE, REG3); } else { - Gen(O_XCHG, _mode|MBYTE, REG1); - Gen(S_DI, _mode|MBYTE); + Gen(O_XCHG, mode|MBYTE, REG1); + Gen(S_DI, mode|MBYTE); } } break; /*87*/ case XCHGwrm: if (RmIsReg[Fetch(PC+1)]&2) { - Gen(L_NOP, _mode); PC+=2; + Gen(L_NOP, mode); PC+=2; } else { - PC += ModRM(opc, PC, _mode|MLOAD); // (e)ax=[rm] + PC += ModRM(opc, PC, mode|MLOAD); // (e)ax=[rm] if (TheCPU.mode & RM_REG) { - Gen(O_XCHG, _mode, REG1); - Gen(S_REG, _mode, REG3); + Gen(O_XCHG, mode, REG1); + Gen(S_REG, mode, REG3); } else { - Gen(O_XCHG, _mode, REG1); - Gen(S_DI, _mode); + Gen(O_XCHG, mode, REG1); + Gen(S_DI, mode); } } break; @@ -1314,50 +1178,50 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; if (ModGetReg1(PC, MBYTE)==3) { Gen(L_REG2REG, MBYTE, REG1, REG3); PC+=2; } else { - Gen(L_REG, _mode|MBYTE, REG1); - PC += ModRM(opc, PC, _mode|MBYTE|MSTORE); // [rm]=al + Gen(L_REG, mode|MBYTE, REG1); + PC += ModRM(opc, PC, mode|MBYTE|MSTORE); // [rm]=al } break; /*89*/ case MOVwfrm: - if (ModGetReg1(PC, _mode)==3) { - Gen(L_REG2REG, _mode, REG1, REG3); PC+=2; + if (ModGetReg1(PC, mode)==3) { + Gen(L_REG2REG, mode, REG1, REG3); PC+=2; } else { - Gen(L_REG, _mode, REG1); - PC += ModRM(opc, PC, _mode|MSTORE); // [rm]=(e)ax + Gen(L_REG, mode, REG1); + PC += ModRM(opc, PC, mode|MSTORE); // [rm]=(e)ax } break; /*8a*/ case MOVbtrm: if (ModGetReg1(PC, MBYTE)==3) { Gen(L_REG2REG, MBYTE, REG3, REG1); PC+=2; } else { - PC += ModRM(opc, PC, _mode|MBYTE|MLOAD); // al=[rm] - Gen(S_REG, _mode|MBYTE, REG1); + PC += ModRM(opc, PC, mode|MBYTE|MLOAD); // al=[rm] + Gen(S_REG, mode|MBYTE, REG1); } break; /*8b*/ case MOVwtrm: - if (ModGetReg1(PC, _mode)==3) { - Gen(L_REG2REG, _mode, REG3, REG1); PC+=2; + if (ModGetReg1(PC, mode)==3) { + Gen(L_REG2REG, mode, REG3, REG1); PC+=2; } else { - PC += ModRM(opc, PC, _mode|MLOAD); // (e)ax=[rm] - Gen(S_REG, _mode, REG1); + PC += ModRM(opc, PC, mode|MLOAD); // (e)ax=[rm] + Gen(S_REG, mode, REG1); } break; /*8c*/ case MOVsrtrm: - PC += ModRM(opc, PC, _mode|SEGREG); - Gen(L_REG, _mode|DATA16, REG1); - //Gen(L_ZXAX, _mode); + PC += ModRM(opc, PC, mode|SEGREG); + Gen(L_REG, mode|DATA16, REG1); + //Gen(L_ZXAX, mode); if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode|DATA16, REG3); + Gen(S_REG, mode|DATA16, REG3); else - Gen(S_DI, _mode|DATA16); + Gen(S_DI, mode|DATA16); break; /*8d*/ case LEA: if (Fetch(PC+1) >= 0xc0) { CODE_FLUSH(); goto not_permitted; } - PC += ModRM(opc, PC, _mode|MLEA); - Gen(S_DI_R, _mode, REG1); + PC += ModRM(opc, PC, mode|MLEA); + Gen(S_DI_R, mode, REG1); break; /*c4*/ case LES: @@ -1366,21 +1230,21 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; goto not_permitted; } if (REALADDR()) { - PC += ModRM(opc, PC, _mode); - Gen(L_LXS1, _mode, REG1); - Gen(L_LXS2, _mode, Ofs_ES, Ofs_XES); + PC += ModRM(opc, PC, mode); + Gen(L_LXS1, mode, REG1); + Gen(L_LXS2, mode, Ofs_ES, Ofs_XES); } else { unsigned short sv = 0; unsigned long rv; CODE_FLUSH(); - PC += ModRMSim(PC, _mode); - rv = DataGetWL_U(_mode,TheCPU.mem_ref); - TheCPU.mem_ref += BT24(BitDATA16, _mode); + PC += ModRMSim(PC, mode); + rv = DataGetWL_U(mode,TheCPU.mem_ref); + TheCPU.mem_ref += BT24(BitDATA16, mode); sv = GetDWord(TheCPU.mem_ref); - TheCPU.err = MAKESEG(_mode, Ofs_ES, sv); + TheCPU.err = MAKESEG(mode, Ofs_ES, sv); if (TheCPU.err) return P0; - SetCPU_WL(_mode, REG1, rv); + SetCPU_WL(mode, REG1, rv); TheCPU.es = sv; } break; @@ -1390,40 +1254,40 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; goto not_permitted; } if (REALADDR()) { - PC += ModRM(opc, PC, _mode); - Gen(L_LXS1, _mode, REG1); - Gen(L_LXS2, _mode, Ofs_DS, Ofs_XDS); + PC += ModRM(opc, PC, mode); + Gen(L_LXS1, mode, REG1); + Gen(L_LXS2, mode, Ofs_DS, Ofs_XDS); } else { unsigned short sv = 0; unsigned long rv; CODE_FLUSH(); - PC += ModRMSim(PC, _mode); - rv = DataGetWL_U(_mode,TheCPU.mem_ref); - TheCPU.mem_ref += BT24(BitDATA16, _mode); + PC += ModRMSim(PC, mode); + rv = DataGetWL_U(mode,TheCPU.mem_ref); + TheCPU.mem_ref += BT24(BitDATA16, mode); sv = GetDWord(TheCPU.mem_ref); - TheCPU.err = MAKESEG(_mode, Ofs_DS, sv); + TheCPU.err = MAKESEG(mode, Ofs_DS, sv); if (TheCPU.err) return P0; - SetCPU_WL(_mode, REG1, rv); + SetCPU_WL(mode, REG1, rv); TheCPU.ds = sv; } break; /*8e*/ case MOVsrfrm: if (REALADDR()) { - PC += ModRM(opc, PC, _mode|SEGREG|DATA16|MLOAD); - Gen(S_REG, _mode|DATA16, REG1); - AddrGen(A_SR_SH4, _mode, REG1, e_ofsseg[REG1>>2]); + PC += ModRM(opc, PC, mode|SEGREG|DATA16|MLOAD); + Gen(S_REG, mode|DATA16, REG1); + AddrGen(A_SR_SH4, mode, REG1, e_ofsseg[REG1>>2]); } else { unsigned short sv = 0; CODE_FLUSH(); - PC += ModRMSim(PC, _mode|SEGREG); + PC += ModRMSim(PC, mode|SEGREG); if (TheCPU.mode & RM_REG) { sv = CPUWORD(REG3); } else { sv = GetDWord(TheCPU.mem_ref); } - TheCPU.err = MAKESEG(_mode, REG1, sv); + TheCPU.err = MAKESEG(mode, REG1, sv); if (TheCPU.err) return P0; switch (REG1) { case Ofs_DS: TheCPU.ds=sv; break; @@ -1439,12 +1303,8 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; break; /*9b*/ case oWAIT: -/*90*/ case NOP: //if (!IsCodeInBuf()) Gen(L_NOP, _mode); -#if 1 - Gen(L_NOP, _mode); -#else - TheCPU.mode|=SKIPOP; -#endif +/*90*/ case NOP: //if (!IsCodeInBuf()) Gen(L_NOP, mode); + if (CurrIMeta<0) Gen(L_NOP, mode); else TheCPU.mode|=SKIPOP; PC++; if (!(EFLAGS & TF)) while (Fetch(PC)==NOP) PC++; @@ -1456,35 +1316,35 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*95*/ case XCHGbp: /*96*/ case XCHGsi: /*97*/ case XCHGdi: - Gen(O_XCHG_R, _mode, Ofs_EAX, R1Tab_l[D_LO(opc)]); + Gen(O_XCHG_R, mode, Ofs_EAX, R1Tab_l[D_LO(opc)]); PC++; break; /*a0*/ case MOVmal: - AddrGen(A_DI_0, _mode|IMMED, OVERR_DS, AddrFetchWL_U(_mode,PC+1)); - Gen(L_DI_R1, _mode|MBYTE); - Gen(S_REG, _mode|MBYTE, Ofs_AL); - INC_WL_PCA(_mode,1); + AddrGen(A_DI_0, mode|IMMED, OVERR_DS, AddrFetchWL_U(mode,PC+1)); + Gen(L_DI_R1, mode|MBYTE); + Gen(S_REG, mode|MBYTE, Ofs_AL); + INC_WL_PCA(mode,1); break; /*a1*/ case MOVmax: - AddrGen(A_DI_0, _mode|IMMED, OVERR_DS, AddrFetchWL_U(_mode,PC+1)); - Gen(L_DI_R1, _mode); - Gen(S_REG, _mode, Ofs_EAX); - INC_WL_PCA(_mode,1); + AddrGen(A_DI_0, mode|IMMED, OVERR_DS, AddrFetchWL_U(mode,PC+1)); + Gen(L_DI_R1, mode); + Gen(S_REG, mode, Ofs_EAX); + INC_WL_PCA(mode,1); break; /*a2*/ case MOValm: - AddrGen(A_DI_0, _mode|IMMED, OVERR_DS, AddrFetchWL_U(_mode,PC+1)); - Gen(L_REG, _mode|MBYTE, Ofs_AL); - Gen(S_DI, _mode|MBYTE); - INC_WL_PCA(_mode,1); + AddrGen(A_DI_0, mode|IMMED, OVERR_DS, AddrFetchWL_U(mode,PC+1)); + Gen(L_REG, mode|MBYTE, Ofs_AL); + Gen(S_DI, mode|MBYTE); + INC_WL_PCA(mode,1); break; /*a3*/ case MOVaxm: - AddrGen(A_DI_0, _mode|IMMED, OVERR_DS, AddrFetchWL_U(_mode,PC+1)); - Gen(L_REG, _mode, Ofs_EAX); - Gen(S_DI, _mode); - INC_WL_PCA(_mode,1); + AddrGen(A_DI_0, mode|IMMED, OVERR_DS, AddrFetchWL_U(mode,PC+1)); + Gen(L_REG, mode, Ofs_EAX); + Gen(S_DI, mode); + INC_WL_PCA(mode,1); break; -/*a4*/ case MOVSb: { int m = _mode|(MBYTE|MOVSSRC|MOVSDST); +/*a4*/ case MOVSb: { int m = mode|(MBYTE|MOVSSRC|MOVSDST); Gen(O_MOVS_SetA, m&~MOVSDST); Gen(L_DI_R1, m); Gen(O_MOVS_SetA, m&~MOVSSRC); @@ -1492,7 +1352,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; Gen(O_MOVS_SavA, m); PC++; } break; -/*a5*/ case MOVSw: { int m = _mode|(MOVSSRC|MOVSDST); +/*a5*/ case MOVSw: { int m = mode|(MOVSSRC|MOVSDST); Gen(O_MOVS_SetA, m&~MOVSDST); Gen(L_DI_R1, m); Gen(O_MOVS_SetA, m&~MOVSSRC); @@ -1525,27 +1385,27 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; } #endif } break; -/*a6*/ case CMPSb: { int m = _mode|(MBYTE|MOVSSRC|MOVSDST); +/*a6*/ case CMPSb: { int m = mode|(MBYTE|MOVSSRC|MOVSDST); Gen(O_MOVS_SetA, m&~MOVSDST); Gen(L_DI_R1, m); Gen(O_MOVS_SetA, m&~MOVSSRC); Gen(O_MOVS_CmpD, m); Gen(O_MOVS_SavA, m); PC++; } break; -/*a7*/ case CMPSw: { int m = _mode|(MOVSSRC|MOVSDST); +/*a7*/ case CMPSw: { int m = mode|(MOVSSRC|MOVSDST); Gen(O_MOVS_SetA, m&~MOVSDST); Gen(L_DI_R1, m); Gen(O_MOVS_SetA, m&~MOVSSRC); Gen(O_MOVS_CmpD, m); Gen(O_MOVS_SavA, m); PC++; } break; -/*aa*/ case STOSb: { int m = _mode|(MBYTE|MOVSDST); +/*aa*/ case STOSb: { int m = mode|(MBYTE|MOVSDST); Gen(O_MOVS_SetA, m); Gen(L_REG, m, Ofs_AL); Gen(S_DI, m); Gen(O_MOVS_SavA, m); PC++; } break; -/*ab*/ case STOSw: { int m = _mode|MOVSDST; +/*ab*/ case STOSw: { int m = mode|MOVSDST; Gen(O_MOVS_SetA, m); Gen(L_REG, m, Ofs_EAX); Gen(S_DI, m); PC++; @@ -1564,7 +1424,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; } #endif } break; -/*ac*/ case LODSb: { int m = _mode|(MBYTE|MOVSSRC); +/*ac*/ case LODSb: { int m = mode|(MBYTE|MOVSSRC); Gen(O_MOVS_SetA, m); Gen(L_DI_R1, m); Gen(S_REG, m, Ofs_AL); PC++; @@ -1580,7 +1440,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; #endif Gen(O_MOVS_SavA, m); } break; -/*ad*/ case LODSw: { int m = _mode|MOVSSRC; +/*ad*/ case LODSw: { int m = mode|MOVSSRC; Gen(O_MOVS_SetA, m); Gen(L_DI_R1, m); Gen(S_REG, m, Ofs_EAX); PC++; @@ -1596,13 +1456,13 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; #endif Gen(O_MOVS_SavA, m); } break; -/*ae*/ case SCASb: { int m = _mode|(MBYTE|MOVSDST); +/*ae*/ case SCASb: { int m = mode|(MBYTE|MOVSDST); Gen(O_MOVS_SetA, m); Gen(L_DI_R1, m); // mov al,[edi] Gen(O_CMP_FR, m, Ofs_AL); // cmp [ebx+reg],al Gen(O_MOVS_SavA, m); PC++; } break; -/*af*/ case SCASw: { int m = _mode|MOVSDST; +/*af*/ case SCASw: { int m = mode|MOVSDST; Gen(O_MOVS_SetA, m); Gen(L_DI_R1, m); // mov ax,[edi] Gen(O_CMP_FR, m, Ofs_EAX); // cmp [ebx+reg],ax @@ -1617,7 +1477,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*b5*/ case MOVich: /*b6*/ case MOVidh: /*b7*/ case MOVibh: - Gen(L_IMM, _mode|MBYTE, SEL_B_X(D_LO(opc)), Fetch(PC+1)); + Gen(L_IMM, mode|MBYTE, SEL_B_X(D_LO(opc)), Fetch(PC+1)); PC += 2; break; /*b8*/ case MOViax: /*b9*/ case MOVicx: @@ -1627,13 +1487,13 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*bd*/ case MOVibp: /*be*/ case MOVisi: /*bf*/ case MOVidi: - Gen(L_IMM, _mode, R1Tab_l[D_LO(opc)], DataFetchWL_U(_mode,PC+1)); - INC_WL_PC(_mode, 1); break; + Gen(L_IMM, mode, R1Tab_l[D_LO(opc)], DataFetchWL_U(mode,PC+1)); + INC_WL_PC(mode, 1); break; /*d0*/ case SHIFTb: /*d2*/ case SHIFTbv: /*c0*/ case SHIFTbi: { - int m = _mode | MBYTE; + int m = mode | MBYTE; unsigned char count = 0; PC += ModRM(opc, PC, m|MLOAD); if (opc==SHIFTb) { m |= IMMED; count = 1; } @@ -1677,7 +1537,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*d1*/ case SHIFTw: /*d3*/ case SHIFTwv: /*c1*/ case SHIFTwi: { - int m = _mode; + int m = mode; unsigned char count = 0; PC += ModRM(opc, PC, m|MLOAD); if (opc==SHIFTw) { m |= IMMED; count = 1; } @@ -1721,17 +1581,17 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*e9*/ case JMPd: /*e8*/ case CALLd: - PC = JumpGen(PC, _mode, opc, 1 + BT24(BitDATA16,_mode)); + PC = JumpGen(PC, mode, opc, 1 + BT24(BitDATA16,mode)); if (TheCPU.err) return PC; break; /*9a*/ case CALLl: /*ea*/ case JMPld: if (REALADDR()) { - int len = 3 + BT24(BitDATA16,_mode); + int len = 3 + BT24(BitDATA16,mode); dosaddr_t oip = PC + len - LONG_CS; ocs = TheCPU.cs; - PC = JumpGen(PC, _mode, opc, len); + PC = JumpGen(PC, mode, opc, len); if (debug_level('e')>2) { if (opc==CALLl) e_printf("CALL_FAR: ret=%04x:%08x\n calling: %04x:%08x\n", @@ -1746,25 +1606,25 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; unsigned long oip,xcs,jip=0; CODE_FLUSH(); /* get new cs:ip */ - jip = DataFetchWL_U(_mode, PC+1); - INC_WL_PC(_mode,1); + jip = DataFetchWL_U(mode, PC+1); + INC_WL_PC(mode,1); jcs = FetchW(PC); PC+=2; /* check if new cs is valid, save old for error */ ocs = TheCPU.cs; xcs = LONG_CS; - TheCPU.err = MAKESEG(_mode, Ofs_CS, jcs); + TheCPU.err = MAKESEG(mode, Ofs_CS, jcs); if (TheCPU.err) { TheCPU.cs = ocs; - TheCPU.cs_cache.BoundL = xcs; + TheCPU.cs_cache.BoundL = TheCPU.mem_base + xcs; // should not change return P0; } if (opc==CALLl) { /* ok, now push old cs:eip */ oip = PC - xcs; - PUSH(_mode, ocs); - PUSH(_mode, oip); + PUSH(mode, ocs); + PUSH(mode, oip); if (debug_level('e')>2) e_printf("CALL_FAR: ret=%04x:%08lx\n calling: %04x:%08lx\n", ocs,oip,jcs,jip); @@ -1786,32 +1646,32 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*c2*/ case RETisp: { int dr = (signed short)FetchW(PC+1); - Gen(O_POP, _mode|MRETISP, dr); - PC = JumpGen(PC, _mode, opc, 3); + Gen(O_POP, mode|MRETISP, dr); + PC = JumpGen(PC, mode, opc, 3); if (debug_level('e')>2) e_printf("RET: ret=%08x inc_sp=%d\n",PC-LONG_CS,dr); if (TheCPU.err) return PC; } break; /*c3*/ case RET: - Gen(O_POP, _mode); - PC = JumpGen(PC, _mode, opc, 1); + Gen(O_POP, mode); + PC = JumpGen(PC, mode, opc, 1); if (debug_level('e')>2) e_printf("RET: ret=%08x\n",PC-LONG_CS); if (TheCPU.err) return PC; break; /*c6*/ case MOVbirm: - PC += ModRM(opc, PC, _mode|MBYTE); + PC += ModRM(opc, PC, mode|MBYTE); if (TheCPU.mode & RM_REG) - Gen(L_IMM, _mode|MBYTE, REG3, Fetch(PC)); + Gen(L_IMM, mode|MBYTE, REG3, Fetch(PC)); else - Gen(S_DI_IMM, _mode|MBYTE, Fetch(PC)); + Gen(S_DI_IMM, mode|MBYTE, Fetch(PC)); PC++; break; /*c7*/ case MOVwirm: - PC += ModRM(opc, PC, _mode); + PC += ModRM(opc, PC, mode); if (TheCPU.mode & RM_REG) - Gen(L_IMM, _mode, REG3, DataFetchWL_U(_mode,PC)); + Gen(L_IMM, mode, REG3, DataFetchWL_U(mode,PC)); else - Gen(S_DI_IMM, _mode, DataFetchWL_U(_mode,PC)); - INC_WL_PC(_mode,0); + Gen(S_DI_IMM, mode, DataFetchWL_U(mode,PC)); + INC_WL_PC(mode,0); break; /*c8*/ case ENTER: { unsigned int sp, bp, frm; @@ -1819,40 +1679,40 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; level = Fetch(PC+3) & 0x1f; if (level <= 1) { int allocsize = FetchW(PC+1); - Gen(L_REG, _mode, Ofs_EBP); - Gen(O_PUSH, _mode); + Gen(L_REG, mode, Ofs_EBP); + Gen(O_PUSH, mode); if (level == 1) { - Gen(L_REG, _mode, Ofs_ESP); - Gen(O_PUSH, _mode); - Gen(S_REG, _mode, Ofs_EBP); + Gen(L_REG, mode, Ofs_ESP); + Gen(O_PUSH, mode); + Gen(S_REG, mode, Ofs_EBP); } else { - Gen(L_REG2REG, _mode, Ofs_ESP, Ofs_EBP); + Gen(L_REG2REG, mode, Ofs_ESP, Ofs_EBP); } // subtract AllocSize from ESP via // "lea -allocsize(%esp), %esp" if (allocsize) { - AddrGen(A_DI_1, - _mode|MLEA|((_mode&DATA16)?ADDR16:0)|IMMED, - 0, -allocsize, Ofs_ESP); - Gen(S_DI_R, _mode, Ofs_ESP); + AddrGen(A_DI_1, 0, + mode|MLEA|((mode&DATA16)?ADDR16:0)|IMMED, + -allocsize, Ofs_ESP); + Gen(S_DI_R, mode, Ofs_ESP); } } else { CODE_FLUSH(); - ds = BT24(BitDATA16, _mode); + ds = BT24(BitDATA16, mode); sp = LONG_SS + ((rESP - ds) & TheCPU.StackMask); bp = LONG_SS + (rEBP & TheCPU.StackMask); - PUSH(_mode, rEBP); + PUSH(mode, rEBP); frm = sp - LONG_SS; sp -= ds*level; while (--level) { bp -= ds; - PUSH(_mode, (_mode&DATA16) ? + PUSH(mode, (mode&DATA16) ? READ_WORD(bp) : READ_DWORD(bp)); } - PUSH(_mode, frm); - if (_mode&DATA16) rBP = frm; else rEBP = frm; + PUSH(mode, frm); + if (mode&DATA16) rBP = frm; else rEBP = frm; sp -= FetchW(PC+1); temp = sp - LONG_SS; rESP = (temp&TheCPU.StackMask) | (rESP&~TheCPU.StackMask); @@ -1860,15 +1720,15 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; PC += 4; } break; /*c9*/ case LEAVE: - Gen(O_LEAVE, _mode); PC++; + Gen(O_LEAVE, mode); PC++; break; /*ca*/ case RETlisp: if (REALADDR()) { int dr = (signed short)FetchW(PC+1); - Gen(O_POP, _mode); - Gen(S_REG, _mode, Ofs_EIP); - Gen(O_POP, _mode|MRETISP, dr); - PC = JumpGen(PC, _mode, opc, 3); + Gen(O_POP, mode); + Gen(S_REG, mode, Ofs_EIP); + Gen(O_POP, mode|MRETISP, dr); + PC = JumpGen(PC, mode, opc, 3); if (debug_level('e')>2) e_printf("RET_%d: ret=%08x\n",dr,TheCPU.eip); if (TheCPU.err) return PC; @@ -1877,12 +1737,12 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; unsigned long dr; uint16_t sv=0; CODE_FLUSH(); - NOS_WORD(_mode, &sv); - dr = AddrFetchWL_U(_mode,PC+1); - TheCPU.err = MAKESEG(_mode, Ofs_CS, sv); + NOS_WORD(mode, &sv); + dr = AddrFetchWL_U(mode,PC+1); + TheCPU.err = MAKESEG(mode, Ofs_CS, sv); if (TheCPU.err) return P0; - TheCPU.eip=0; POP(_mode, &TheCPU.eip); - POP_ONLY(_mode); + TheCPU.eip=0; POP(mode, &TheCPU.eip); + POP_ONLY(mode); if (debug_level('e')>2) e_printf("RET_%ld: ret=%08x\n",dr,TheCPU.eip); PC = LONG_CS + TheCPU.eip; @@ -1913,16 +1773,16 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; #endif CEmuStat &= ~CeS_TRAP; // INT suppresses trap if (V86MODE() && (TheCPU.cr[4] & CR4_VME) && IOPL == 3) { - Gen(O_INT, _mode, inum, P0); + Gen(O_INT, mode, inum, P0); if (TheCPU.err) return P0; - Gen(O_PUSH2F, _mode); - Gen(L_REG, _mode, Ofs_CS); - Gen(O_PUSH, _mode); - Gen(O_PUSHI, _mode, PC + 2 - LONG_CS); - Gen(O_SETFL, _mode, INT); - Gen(L_LXS1, _mode, Ofs_EIP); - Gen(L_DI_R1, _mode); - PC = JumpGen(PC, _mode, opc, 2); + Gen(O_PUSH2F, mode); + Gen(L_REG, mode, Ofs_CS); + Gen(O_PUSH, mode); + Gen(O_PUSHI, mode, PC + 2 - LONG_CS); + Gen(O_SETFL, mode, INT); + Gen(L_LXS1, mode, Ofs_EIP); + Gen(L_DI_R1, mode); + PC = JumpGen(PC, mode, opc, 2); if (debug_level('e')>1) dbug_printf("EMU86: directly called int %#x ax=%#x at %#x:%#x\n", inum, TheCPU.eax, TheCPU.cs, PC - LONG_CS); @@ -1933,7 +1793,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; if (V86MODE() && !(TheCPU.cr[4] & CR4_VME) && IOPL<3) goto not_permitted; if (V86MODE() && (TheCPU.cr[4] & CR4_VME) && - !test_bit(inum, &vm86s.int_revectored)) { + !is_revectored(inum, &vm86s.int_revectored)) { uint32_t segoffs; segoffs = read_dword(inum << 2); if (CONFIG_CPUSIM) FlagSync_All(); @@ -1943,10 +1803,10 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; if (EFLAGS & VIF) temp |= EFLAGS_IF; } - PUSH(_mode, temp); - PUSH(_mode, TheCPU.cs); - PUSH(_mode, PC + 2 - LONG_CS); - TheCPU.err = MAKESEG(_mode, Ofs_CS, segoffs >> 16); + PUSH(mode, temp); + PUSH(mode, TheCPU.cs); + PUSH(mode, PC + 2 - LONG_CS); + TheCPU.err = MAKESEG(mode, Ofs_CS, segoffs >> 16); if (TheCPU.err) return P0; TheCPU.eip = segoffs & 0xffff; PC = LONG_CS + TheCPU.eip; @@ -1957,7 +1817,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; inum, _AX, _CS, _IP); break; } - /* protected _mode INT or revectored V86 with IOPL=3 */ + /* protected mode INT or revectored V86 with IOPL=3 */ if (PROTMODE()) switch(inum) { case 0x03: TheCPU.err=EXCP03_INT3; @@ -1975,10 +1835,10 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*cb*/ case RETl: if (REALADDR()) { - Gen(O_POP, _mode); - Gen(S_REG, _mode, Ofs_EIP); - Gen(O_POP, _mode); - PC = JumpGen(PC, _mode, opc, 1); + Gen(O_POP, mode); + Gen(S_REG, mode, Ofs_EIP); + Gen(O_POP, mode); + PC = JumpGen(PC, mode, opc, 1); if (debug_level('e')>1) e_printf("RET_FAR: ret=%04x:%08x\n",TheCPU.cs,TheCPU.eip); if (TheCPU.err) return PC; @@ -1987,7 +1847,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /* fall through */ /*cf*/ case IRET: { /* restartable */ uint16_t sv=0; - int m = _mode; + int m = mode; CODE_FLUSH(); NOS_WORD(m, &sv); /* get segment */ TheCPU.err = MAKESEG(m, Ofs_CS, sv); @@ -2016,7 +1876,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /* else stack_return */ int amask = (CPL==0? 0:(EFLAGS_IOPL_MASK|VIF|VIP)) | (CPL<=IOPL? 0:EFLAGS_IF) | 2; - if (_mode & DATA16) + if (mode & DATA16) FLAGS = (FLAGS&amask) | ((temp&0x7fd7)&~amask); else /* should use eTSSMASK */ EFLAGS = (EFLAGS&amask) | @@ -2029,7 +1889,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; /*9d*/ case POPF: { CODE_FLUSH(); - temp=0; POP(_mode, &temp); + temp=0; POP(mode, &temp); if (CONFIG_CPUSIM) RFL.valid = V_INVALID; if (V86MODE()) { int is_tf; @@ -2040,7 +1900,7 @@ stack_return_from_vm86: is_tf = !!(EFLAGS & TF); if (IOPL==3) { /* Intel manual */ /* keep reserved bits + IOPL,VIP,VIF,VM,RF */ - if (_mode & DATA16) + if (mode & DATA16) FLAGS &= ~(SAFE_MASK|EFLAGS_IF); else EFLAGS &= ~(SAFE_MASK|EFLAGS_IF); @@ -2051,7 +1911,7 @@ stack_return_from_vm86: if (!(TheCPU.cr[4] & CR4_VME)) goto not_permitted; /* GPF */ /* move mask from pop{e}flags to regs->eflags */ - if (_mode & DATA16) + if (mode & DATA16) FLAGS &= ~SAFE_MASK; else EFLAGS &= ~SAFE_MASK; @@ -2073,7 +1933,7 @@ stack_return_from_vm86: int amask = (CPL==0? 0:EFLAGS_IOPL_MASK) | (CPL<=IOPL? 0:EFLAGS_IF) | (EFLAGS_VM|EFLAGS_RF) | 2; - if (_mode & DATA16) + if (mode & DATA16) FLAGS = (FLAGS&amask) | ((temp&0x7fd7)&~amask); else EFLAGS = (EFLAGS&amask) | @@ -2097,7 +1957,7 @@ stack_return_from_vm86: /*f3*/ case REP: /* also is REPE */ { unsigned char repop; int repmod, realrepmod; PC++; - repmod = _mode | (opc==REPNE? MREPNE:MREP); + repmod = mode | (opc==REPNE? MREPNE:MREP); repag0: realrepmod = repmod; if ((EFLAGS & TF) && @@ -2257,19 +2117,19 @@ repag0: case OPERoverride: repmod = (repmod & ~DATA16) | (~basemode & DATA16); if (debug_level('e')>4) - e_printf("OPERoverride: new _mode %04x\n",repmod); + e_printf("OPERoverride: new mode %04x\n",repmod); PC++; goto repag0; case ADDRoverride: repmod = (repmod & ~ADDR16) | (~basemode & ADDR16); if (debug_level('e')>4) - e_printf("ADDRoverride: new _mode %04x\n",repmod); + e_printf("ADDRoverride: new mode %04x\n",repmod); PC++; goto repag0; } if ((EFLAGS & TF) && !(repmod & (MREP|MREPNE))) { /* with TF set, we simulate REP and maybe back up IP */ -#ifdef HOST_ARCH_X86 int rc = 0; +#ifdef HOST_ARCH_X86 if (!CONFIG_CPUSIM) { NewIMeta(P0, &rc); CODE_FLUSH(); @@ -2297,108 +2157,102 @@ repag0: CODE_FLUSH(); goto not_permitted; /*f5*/ case CMC: PC++; -#if 0 if ((CurrIMeta<0)&&(InterOps[Fetch(PC)]&1)) EFLAGS ^= EFLAGS_CF; else -#endif - Gen(O_SETFL, _mode, CMC); + Gen(O_SETFL, mode, CMC); break; /*f6*/ case GRP1brm: { - PC += ModRM(opc, PC, _mode|MBYTE|MLOAD); // al=[rm] + PC += ModRM(opc, PC, mode|MBYTE|MLOAD); // al=[rm] switch(REG1) { case Ofs_AL: /*0*/ /* TEST */ case Ofs_CL: /*1*/ /* undocumented */ - Gen(O_AND_R, _mode|MBYTE|IMMED, Fetch(PC)); // op al,#imm + Gen(O_AND_R, mode|MBYTE|IMMED, Fetch(PC)); // op al,#imm PC++; break; case Ofs_DL: /*2*/ /* NOT */ - Gen(O_NOT, _mode|MBYTE); // not al + Gen(O_NOT, mode|MBYTE); // not al if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode|MBYTE, REG3); + Gen(S_REG, mode|MBYTE, REG3); else - Gen(S_DI, _mode|MBYTE); + Gen(S_DI, mode|MBYTE); break; case Ofs_BL: /*3*/ /* NEG */ - Gen(O_NEG, _mode|MBYTE); // neg al + Gen(O_NEG, mode|MBYTE); // neg al if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode|MBYTE, REG3); + Gen(S_REG, mode|MBYTE, REG3); else - Gen(S_DI, _mode|MBYTE); + Gen(S_DI, mode|MBYTE); break; case Ofs_AH: /*4*/ /* MUL AL */ - Gen(O_MUL, _mode|MBYTE); // al*[edi]->AX unsigned + Gen(O_MUL, mode|MBYTE); // al*[edi]->AX unsigned break; case Ofs_CH: /*5*/ /* IMUL AL */ - Gen(O_IMUL, _mode|MBYTE); // al*[edi]->AX signed + Gen(O_IMUL, mode|MBYTE); // al*[edi]->AX signed break; case Ofs_DH: /*6*/ /* DIV AL */ - Gen(O_DIV, _mode|MBYTE, P0); // ah:al/[edi]->AH:AL unsigned + Gen(O_DIV, mode|MBYTE, P0); // ah:al/[edi]->AH:AL unsigned if (CONFIG_CPUSIM && TheCPU.err) return P0; break; case Ofs_BH: /*7*/ /* IDIV AL */ - Gen(O_IDIV, _mode|MBYTE, P0); // ah:al/[edi]->AH:AL signed + Gen(O_IDIV, mode|MBYTE, P0); // ah:al/[edi]->AH:AL signed if (CONFIG_CPUSIM && TheCPU.err) return P0; break; } } break; /*f7*/ case GRP1wrm: { - PC += ModRM(opc, PC, _mode|MLOAD); // (e)ax=[rm] + PC += ModRM(opc, PC, mode|MLOAD); // (e)ax=[rm] switch(REG1) { case Ofs_AX: /*0*/ /* TEST */ case Ofs_CX: /*1*/ /* undocumented */ - Gen(O_AND_R, _mode|IMMED, DataFetchWL_U(_mode,PC)); // op al,#imm - INC_WL_PC(_mode,0); + Gen(O_AND_R, mode|IMMED, DataFetchWL_U(mode,PC)); // op al,#imm + INC_WL_PC(mode,0); break; case Ofs_DX: /*2*/ /* NOT */ - Gen(O_NOT, _mode); // not (e)ax + Gen(O_NOT, mode); // not (e)ax if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode, REG3); + Gen(S_REG, mode, REG3); else - Gen(S_DI, _mode); + Gen(S_DI, mode); break; case Ofs_BX: /*3*/ /* NEG */ - Gen(O_NEG, _mode); // neg (e)ax + Gen(O_NEG, mode); // neg (e)ax if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode, REG3); + Gen(S_REG, mode, REG3); else - Gen(S_DI, _mode); + Gen(S_DI, mode); break; case Ofs_SP: /*4*/ /* MUL AX */ - Gen(O_MUL, _mode); // (e)ax*[edi]->(E)DX:(E)AX unsigned + Gen(O_MUL, mode); // (e)ax*[edi]->(E)DX:(E)AX unsigned break; case Ofs_BP: /*5*/ /* IMUL AX */ - Gen(O_IMUL, _mode); // (e)ax*[edi]->(E)DX:(E)AX signed + Gen(O_IMUL, mode); // (e)ax*[edi]->(E)DX:(E)AX signed break; case Ofs_SI: /*6*/ /* DIV AX+DX */ - Gen(O_DIV, _mode, P0); // (e)ax:(e)dx/[edi]->(E)AX:(E)DX unsigned + Gen(O_DIV, mode, P0); // (e)ax:(e)dx/[edi]->(E)AX:(E)DX unsigned if (CONFIG_CPUSIM && TheCPU.err) return P0; break; case Ofs_DI: /*7*/ /* IDIV AX+DX */ - Gen(O_IDIV, _mode, P0); // (e)ax:(e)dx/[edi]->(E)AX:(E)DX signed + Gen(O_IDIV, mode, P0); // (e)ax:(e)dx/[edi]->(E)AX:(E)DX signed if (CONFIG_CPUSIM && TheCPU.err) return P0; break; } } break; /*f8*/ case CLC: PC++; -#if 0 if ((CurrIMeta<0)&&(InterOps[Fetch(PC)]&1)) EFLAGS &= ~EFLAGS_CF; else -#endif - Gen(O_SETFL, _mode, CLC); + Gen(O_SETFL, mode, CLC); break; /*f9*/ case STC: PC++; -#if 0 if ((CurrIMeta<0)&&(InterOps[Fetch(PC)]&1)) EFLAGS |= EFLAGS_CF; else -#endif - Gen(O_SETFL, _mode, STC); + Gen(O_SETFL, mode, STC); break; /*fa*/ case CLI: if (REALMODE() || (CPL <= IOPL) || (IOPL==3)) { - Gen(O_SETFL, _mode, CLI); + Gen(O_SETFL, mode, CLI); } else { CODE_FLUSH(); @@ -2452,49 +2306,45 @@ repag0: PC++; break; /*fc*/ case CLD: PC++; -#if 0 if ((CurrIMeta<0)&&(InterOps[Fetch(PC)]&1)) { EFLAGS &= ~EFLAGS_DF; TheCPU.df_increments = 0x040201; } else -#endif - Gen(O_SETFL, _mode, CLD); + Gen(O_SETFL, mode, CLD); break; /*fd*/ case STD: PC++; -#if 0 if ((CurrIMeta<0)&&(InterOps[Fetch(PC)]&1)) { EFLAGS |= EFLAGS_DF; TheCPU.df_increments = 0xfcfeff; } else -#endif - Gen(O_SETFL, _mode, STD); + Gen(O_SETFL, mode, STD); break; /*fe*/ case GRP2brm: /* only INC and DEC are legal on bytes */ - ModGetReg1(PC, _mode); + ModGetReg1(PC, mode); switch(REG1) { case Ofs_AL: /*0*/ if (Fetch(PC+1) >= 0xc0) { - Gen(O_INC_R, _mode|MBYTE, + Gen(O_INC_R, mode|MBYTE, R1Tab_b[Fetch(PC+1) & 7]); PC += 2; break; } - PC += ModRM(opc, PC, _mode|MBYTE|MLOAD);//al=[rm] - Gen(O_INC, _mode|MBYTE); - Gen(S_DI, _mode|MBYTE); + PC += ModRM(opc, PC, mode|MBYTE|MLOAD);//al=[rm] + Gen(O_INC, mode|MBYTE); + Gen(S_DI, mode|MBYTE); break; case Ofs_CL: /*1*/ if (Fetch(PC+1) >= 0xc8) { - Gen(O_DEC_R, _mode|MBYTE, + Gen(O_DEC_R, mode|MBYTE, R1Tab_b[Fetch(PC+1) & 7]); PC += 2; break; } - PC += ModRM(opc, PC, _mode|MBYTE|MLOAD);//al=[rm] - Gen(O_DEC, _mode|MBYTE); - Gen(S_DI, _mode|MBYTE); + PC += ModRM(opc, PC, mode|MBYTE|MLOAD);//al=[rm] + Gen(O_DEC, mode|MBYTE); + Gen(S_DI, mode|MBYTE); break; default: CODE_FLUSH(); @@ -2502,7 +2352,7 @@ repag0: } break; /*ff*/ case GRP2wrm: - ModGetReg1(PC, _mode); + ModGetReg1(PC, mode); switch (REG1) { case Ofs_AX: /*0*/ /* it's not worth optimizing for registers @@ -2510,41 +2360,41 @@ repag0: it for consistency anyway. */ if (Fetch(PC+1) >= 0xc0) { - Gen(O_INC_R, _mode, + Gen(O_INC_R, mode, R1Tab_l[Fetch(PC+1) & 7]); PC += 2; break; } - PC += ModRM(opc, PC, _mode|MLOAD); - Gen(O_INC, _mode); - Gen(S_DI, _mode); + PC += ModRM(opc, PC, mode|MLOAD); + Gen(O_INC, mode); + Gen(S_DI, mode); break; case Ofs_CX: /*1*/ if (Fetch(PC+1) >= 0xc8) { - Gen(O_DEC_R, _mode, + Gen(O_DEC_R, mode, R1Tab_l[Fetch(PC+1) & 7]); PC += 2; break; } - PC += ModRM(opc, PC, _mode|MLOAD); - Gen(O_DEC, _mode); - Gen(S_DI, _mode); + PC += ModRM(opc, PC, mode|MLOAD); + Gen(O_DEC, mode); + Gen(S_DI, mode); break; case Ofs_SP: /*4*/ // JMP near indirect - PC = JumpGen(PC, _mode, (opc<<8)|REG1, - ModRM(opc, PC, _mode|NOFLDR|MLOAD)); + PC = JumpGen(PC, mode, (opc<<8)|REG1, + ModRM(opc, PC, mode|NOFLDR|MLOAD)); if (TheCPU.err) return PC; break; case Ofs_DX: { /*2*/ // CALL near indirect /* don't use MLOAD as O_PUSHI clobbers eax */ - int len = ModRM(opc, PC, _mode|NOFLDR); + int len = ModRM(opc, PC, mode|NOFLDR); dosaddr_t ret = PC + len - LONG_CS; - Gen(O_PUSHI, _mode, ret); + Gen(O_PUSHI, mode, ret); if (TheCPU.mode & RM_REG) - Gen(L_REG, _mode, REG3); + Gen(L_REG, mode, REG3); else - Gen(L_DI_R1, _mode); - PC = JumpGen(PC, _mode, (opc<<8)|REG1, len); + Gen(L_DI_R1, mode); + PC = JumpGen(PC, mode, (opc<<8)|REG1, len); if (debug_level('e')>2) e_printf("CALL indirect: ret=%08x\n\tcalling: %08x\n", ret,PC-LONG_CS); @@ -2559,18 +2409,18 @@ repag0: } if (REALADDR()) { dosaddr_t oip = 0; - int len = ModRM(opc, PC, _mode|NOFLDR); - ocs = TheCPU.cs; + int len = ModRM(opc, PC, mode|NOFLDR); if (REG1==Ofs_BX) { /* ok, now push old cs:eip */ + ocs = TheCPU.cs; oip = PC + len - LONG_CS; - Gen(L_REG, _mode, Ofs_CS); - Gen(O_PUSH, _mode); - Gen(O_PUSHI, _mode, oip); + Gen(L_REG, mode, Ofs_CS); + Gen(O_PUSH, mode); + Gen(O_PUSHI, mode, oip); } - Gen(L_LXS1, _mode, Ofs_EIP); - Gen(L_DI_R1, _mode); - PC = JumpGen(PC, _mode, (opc<<8)|REG1, len); + Gen(L_LXS1, mode, Ofs_EIP); + Gen(L_DI_R1, mode); + PC = JumpGen(PC, mode, (opc<<8)|REG1, len); if (debug_level('e')>2) { unsigned short jcs = TheCPU.cs; dosaddr_t jip = PC - LONG_CS; @@ -2592,26 +2442,26 @@ repag0: unsigned short jcs; unsigned long oip,xcs,jip=0; CODE_FLUSH(); - PC += ModRMSim(PC, _mode|NOFLDR); + PC += ModRMSim(PC, mode|NOFLDR); TheCPU.eip = PC - LONG_CS; /* get new cs:ip */ - jip = DataGetWL_U(_mode, TheCPU.mem_ref); - jcs = GetDWord(TheCPU.mem_ref+BT24(BitDATA16,_mode)); + jip = DataGetWL_U(mode, TheCPU.mem_ref); + jcs = GetDWord(TheCPU.mem_ref+BT24(BitDATA16,mode)); /* check if new cs is valid, save old for error */ ocs = TheCPU.cs; xcs = LONG_CS; - TheCPU.err = MAKESEG(_mode, Ofs_CS, jcs); + TheCPU.err = MAKESEG(mode, Ofs_CS, jcs); if (TheCPU.err) { TheCPU.cs = ocs; - TheCPU.cs_cache.BoundL = xcs; + TheCPU.cs_cache.BoundL = TheCPU.mem_base + xcs; // should not change return P0; } if (REG1==Ofs_BX) { /* ok, now push old cs:eip */ oip = PC - xcs; - PUSH(_mode, ocs); - PUSH(_mode, oip); + PUSH(mode, ocs); + PUSH(mode, oip); if (debug_level('e')>2) e_printf("CALL_FAR indirect: ret=%04x:%08lx\n\tcalling: %04x:%08lx\n", ocs,oip,jcs,jip); @@ -2625,8 +2475,8 @@ repag0: } break; case Ofs_SI: /*6*/ // PUSH - PC += ModRM(opc, PC, _mode|MLOAD); - Gen(O_PUSH, _mode); break; // push [rm] + PC += ModRM(opc, PC, mode|MLOAD); + Gen(O_PUSH, mode); break; // push [rm] break; default: CODE_FLUSH(); @@ -2640,22 +2490,15 @@ repag0: CODE_FLUSH(); a = rDX; if (!test_ioperm(a)) goto not_permitted; - rd = (_mode&ADDR16? rDI:rEDI); + rd = (mode&ADDR16? rDI:rEDI); WRITE_BYTE(LONG_ES+rd, port_inb(a)); if (EFLAGS & EFLAGS_DF) rd--; else rd++; - if (_mode&ADDR16) rDI=rd; else rEDI=rd; + if (mode&ADDR16) rDI=rd; else rEDI=rd; PC++; } break; /*ec*/ case INvb: { unsigned short a; - int uc; CODE_FLUSH(); a = rDX; - if ((CEmuStat & CeS_INSTREMU) && - (uc=VGA_emulate_inb(a, NULL)) != -1) { - rAL = uc; - PC++; - break; - } #ifdef TRAP_RETRACE if (a==0x3da) { // video retrace bits /* bit 0 = DE bit 3 = VR @@ -2676,22 +2519,22 @@ repag0: //} //else if (c1==0xfbe008a8) { // e0 fb = loop while VR==1 - //unsigned int rcx = _mode&DATA16? rCX:rECX; + //unsigned int rcx = mode&DATA16? rCX:rECX; //if (tp==0) set_ioperm(a,1,1); //while ((((rAL=port_inb(a))&8)!=0) && rcx) // rcx--; //if (tp==0) set_ioperm(a,1,0); - //if (_mode&DATA16) rCX=rcx; else rECX=rcx; + //if (mode&DATA16) rCX=rcx; else rECX=rcx; //PC+=5; break; //} else if (c1==0xfbe108a8) { // e1 fb = loop while VR==0 - unsigned int rcx = _mode&DATA16? rCX:rECX; + unsigned int rcx = mode&DATA16? rCX:rECX; if (tp==0) set_ioperm(a,1,1); while ((((rAL=port_inb(a))&8)==0) && rcx) rcx--; if (tp==0) set_ioperm(a,1,0); - if (_mode&DATA16) rCX=rcx; else rECX=rcx; + if (mode&DATA16) rCX=rcx; else rECX=rcx; PC+=5; break; } else if (((c1&0xfffff6ff)==0xc0080024) && @@ -2715,7 +2558,7 @@ repag0: #endif if (!test_ioperm(a)) goto not_permitted; #ifdef CPUEMU_DIRECT_IO - Gen(O_INPDX, _mode|MBYTE); NewNode=1; + Gen(O_INPDX, mode|MBYTE); NewNode=1; #else rAL = port_inb(a); #endif @@ -2724,6 +2567,7 @@ repag0: /*e4*/ case INb: { unsigned short a; CODE_FLUSH(); + E_TIME_STRETCH; // for PIT /* there's no reason to compile this, as most of * the ports under 0x100 are emulated by dosemu */ a = Fetch(PC+1); @@ -2735,20 +2579,20 @@ repag0: int dp; CODE_FLUSH(); if (!test_ioperm(rDX)) goto not_permitted; - rd = (_mode&ADDR16? rDI:rEDI); - if (_mode&DATA16) { + rd = (mode&ADDR16? rDI:rEDI); + if (mode&DATA16) { WRITE_WORD(LONG_ES+rd, port_inw(rDX)); dp=2; } else { WRITE_DWORD(LONG_ES+rd, port_ind(rDX)); dp=4; } if (EFLAGS & EFLAGS_DF) rd-=dp; else rd+=dp; - if (_mode&ADDR16) rDI=rd; else rEDI=rd; + if (mode&ADDR16) rDI=rd; else rEDI=rd; PC++; } break; /*ed*/ case INvw: { CODE_FLUSH(); if (!test_ioperm(rDX)) goto not_permitted; - if (_mode&DATA16) rAX = port_inw(rDX); + if (mode&DATA16) rAX = port_inw(rDX); else rEAX = port_ind(rDX); } PC++; break; /*e5*/ case INw: { @@ -2756,7 +2600,7 @@ repag0: CODE_FLUSH(); a = Fetch(PC+1); if (!test_ioperm(a)) goto not_permitted; - if (_mode&DATA16) rAX = port_inw(a); + if (mode&DATA16) rAX = port_inw(a); else rEAX = port_ind(a); PC += 2; } break; @@ -2766,27 +2610,21 @@ repag0: CODE_FLUSH(); a = rDX; if (!test_ioperm(a)) goto not_permitted; - rs = (_mode&ADDR16? rSI:rESI); + rs = (mode&ADDR16? rSI:rESI); do { port_outb(a,Fetch(LONG_DS+rs)); if (EFLAGS & EFLAGS_DF) rs--; else rs++; PC++; } while (Fetch(PC)==OUTSb); - if (_mode&ADDR16) rSI=rs; else rESI=rs; + if (mode&ADDR16) rSI=rs; else rESI=rs; } break; /*ee*/ case OUTvb: { unsigned short a; CODE_FLUSH(); a = rDX; - /* Note that we short circuit for vgaemu planar */ - if ((CEmuStat & CeS_INSTREMU) && - VGA_emulate_outb(a, rAL, NULL) != -1) { - PC++; - break; - } if (!test_ioperm(a)) goto not_permitted; #ifdef CPUEMU_DIRECT_IO - Gen(O_OUTPDX, _mode|MBYTE); NewNode=1; + Gen(O_OUTPDX, mode|MBYTE); NewNode=1; #else port_outb(a,rAL); #endif @@ -2796,6 +2634,7 @@ repag0: unsigned short a; CODE_FLUSH(); a = Fetch(PC+1); + if ((a&0xfc)==0x40) E_TIME_STRETCH; // for PIT /* there's no reason to compile this, as most of * the ports under 0x100 are emulated by dosemu */ if (!test_ioperm(a)) goto not_permitted; @@ -2808,17 +2647,11 @@ repag0: unsigned short a; CODE_FLUSH(); a = rDX; - if ((CEmuStat & CeS_INSTREMU) && - VGA_emulate_outb(a, rAL, NULL) != -1 && - VGA_emulate_outb(a+1, rAH, NULL) != -1) { - PC++; - break; - } if (!test_ioperm(a)) goto not_permitted; #ifdef CPUEMU_DIRECT_IO - Gen(O_OUTPDX, _mode); NewNode=1; + Gen(O_OUTPDX, mode); NewNode=1; #else - if (_mode&DATA16) port_outw(a,rAX); else port_outd(a,rEAX); + if (mode&DATA16) port_outw(a,rAX); else port_outd(a,rEAX); #endif } PC++; break; @@ -2828,7 +2661,7 @@ repag0: CODE_FLUSH(); a = Fetch(PC+1); if (!test_ioperm(a)) goto not_permitted; - if (_mode&DATA16) port_outw(a,rAX); else port_outd(a,rEAX); + if (mode&DATA16) port_outw(a,rAX); else port_outd(a,rEAX); PC += 2; } break; /*d8*/ case ESC0: @@ -2853,23 +2686,21 @@ repag0: else { if ((exop&0xeb)==0x21) { CODE_FLUSH(); - PC += ModRMSim(PC, _mode|NOFLDR); - b = _mode; sim=1; + PC += ModRMSim(PC, mode|NOFLDR); + b = mode; sim=1; } else { - PC += ModRM(opc, PC, _mode|NOFLDR); + PC += ModRM(opc, PC, mode|NOFLDR); } } b &= 7; if (TheCPU.fpstate) { /* For simulator, only need to mask all - exceptions, and set rounding properly; - for JIT, load emulated FPU state + exceptions; for JIT, load emulated FPU state into real FPU */ - if (CONFIG_CPUSIM) { + if (CONFIG_CPUSIM) fesetenv(FE_DFL_ENV); - fp87_set_rounding(); - } else + else loadfpstate(*TheCPU.fpstate); TheCPU.fpstate = NULL; } @@ -2877,7 +2708,7 @@ repag0: if (Fp87_op(exop,b)) { TheCPU.err = -96; return P0; } } else - Gen(O_FOP, _mode, exop, b); + Gen(O_FOP, mode, exop, b); } break; @@ -2891,14 +2722,14 @@ repag0: case 0: /* SLDT */ CODE_FLUSH(); if (REALMODE()) goto illegal_op; - PC += ModRMSim(PC+1, _mode) + 1; + PC += ModRMSim(PC+1, mode) + 1; error("SLDT not implemented\n"); break; case 1: /* STR */ /* Store Task Register */ CODE_FLUSH(); if (REALMODE()) goto illegal_op; - PC += ModRMSim(PC+1, _mode) + 1; + PC += ModRMSim(PC+1, mode) + 1; error("STR not implemented\n"); break; case 2: /* LLDT */ @@ -2911,7 +2742,7 @@ repag0: unsigned short sv; int tmp; CODE_FLUSH(); if (REALMODE()) goto illegal_op; - PC += ModRMSim(PC+1, _mode) + 1; + PC += ModRMSim(PC+1, mode) + 1; if (TheCPU.mode & RM_REG) { sv = CPUWORD(REG3); } else { @@ -2928,7 +2759,7 @@ repag0: unsigned short sv; int tmp; CODE_FLUSH(); if (REALMODE()) goto illegal_op; - PC += ModRMSim(PC+1, _mode) + 1; + PC += ModRMSim(PC+1, mode) + 1; if (TheCPU.mode & RM_REG) { sv = CPUWORD(REG3); } else { @@ -2952,24 +2783,24 @@ repag0: switch (opm) { case 0: /* SGDT */ /* Store Global Descriptor Table Register */ - PC++; PC += ModRM(opc, PC, _mode|DATA16|MSTORE); + PC++; PC += ModRM(opc, PC, mode|DATA16|MSTORE); error("SGDT not implemented\n"); break; case 1: /* SIDT */ /* Store Interrupt Descriptor Table Register */ - PC++; PC += ModRM(opc, PC, _mode|DATA16|MSTORE); + PC++; PC += ModRM(opc, PC, mode|DATA16|MSTORE); error("SIDT not implemented\n"); break; - case 2: /* LGDT */ /* PM privileged AND real _mode */ + case 2: /* LGDT */ /* PM privileged AND real mode */ /* Load Global Descriptor Table Register */ - case 3: /* LIDT */ /* PM privileged AND real _mode */ + case 3: /* LIDT */ /* PM privileged AND real mode */ /* Load Interrupt Descriptor Table Register */ CODE_FLUSH(); goto not_permitted; case 4: /* SMSW, 80286 compatibility */ /* Store Machine Status Word */ - Gen(L_CR0, _mode); - PC++; PC += ModRM(opc, PC, _mode|DATA16|MSTORE); + Gen(L_CR0, mode); + PC++; PC += ModRM(opc, PC, mode|DATA16|MSTORE); break; case 5: /* Illegal */ case 6: /* LMSW, 80286 compatibility, Privileged */ @@ -2985,20 +2816,20 @@ repag0: unsigned short sv; int tmp; CODE_FLUSH(); if (REALMODE()) goto illegal_op; - PC += ModRMSim(PC+1, _mode) + 1; + PC += ModRMSim(PC+1, mode) + 1; if (TheCPU.mode & RM_REG) { sv = CPUWORD(REG3); } else { sv = GetDWord(TheCPU.mem_ref); } - if (!e_larlsl(_mode, sv)) { + if (!e_larlsl(mode, sv)) { EFLAGS &= ~EFLAGS_ZF; if (CONFIG_CPUSIM) RFL.valid = V_INVALID; } else { if (opc2==0x02) { /* LAR */ tmp = GetSelectorFlags(sv); - if (_mode&DATA16) tmp &= 0xff; + if (mode&DATA16) tmp &= 0xff; tmp <<= 8; if (tmp) SetFlagAccessed(sv); } @@ -3007,7 +2838,7 @@ repag0: } EFLAGS |= EFLAGS_ZF; if (CONFIG_CPUSIM) RFL.valid = V_INVALID; - SetCPU_WL(_mode, REG1, tmp); + SetCPU_WL(mode, REG1, tmp); } } break; @@ -3080,7 +2911,7 @@ repag0: goto not_implemented; case 0x31: /* RDTSC */ - Gen(O_RDTSC, _mode); + Gen(O_RDTSC, mode); PC+=2; break; case 0x32: /* RDMSR */ CODE_FLUSH(); @@ -3116,8 +2947,8 @@ repag0: case JLEimmdisp: /*8e*/ case JNLEimmdisp: /*8f*/ { - PC = JumpGen(PC, _mode, JO+(opc2-JOimmdisp), - 2 + BT24(BitDATA16,_mode)); + PC = JumpGen(PC, mode, JO+(opc2-JOimmdisp), + 2 + BT24(BitDATA16,mode)); if (TheCPU.err) return PC; } break; @@ -3138,26 +2969,26 @@ repag0: case SETNLbrm: /*9d*/ case SETLEbrm: /*9e*/ case SETNLEbrm: /*9f*/ - Gen(O_SETCC, _mode, (opc2&0x0f)); - PC++; PC += ModRM(opc, PC, _mode|MBYTE|MSTORE); + Gen(O_SETCC, mode, (opc2&0x0f)); + PC++; PC += ModRM(opc, PC, mode|MBYTE|MSTORE); break; /// case 0xa0: /* PUSHfs */ - Gen(L_REG, _mode, Ofs_FS); - Gen(O_PUSH, _mode); PC+=2; + Gen(L_REG, mode, Ofs_FS); + Gen(O_PUSH, mode); PC+=2; break; case 0xa1: /* POPfs */ if (REALADDR()) { - Gen(O_POP, _mode); - Gen(S_REG, _mode, Ofs_FS); - AddrGen(A_SR_SH4, _mode, Ofs_FS, Ofs_XFS); + Gen(O_POP, mode); + Gen(S_REG, mode, Ofs_FS); + AddrGen(A_SR_SH4, mode, Ofs_FS, Ofs_XFS); } else { /* restartable */ unsigned short sv = 0; CODE_FLUSH(); - TOS_WORD(_mode, &sv); - TheCPU.err = MAKESEG(_mode, Ofs_FS, sv); + TOS_WORD(mode, &sv); + TheCPU.err = MAKESEG(mode, Ofs_FS, sv); if (TheCPU.err) return P0; - POP_ONLY(_mode); + POP_ONLY(mode); TheCPU.fs = sv; } PC+=2; @@ -3179,29 +3010,29 @@ repag0: case 0xab: /* BTS */ case 0xb3: /* BTR */ case 0xbb: /* BTC */ - PC++; PC += ModRM(opc, PC, _mode); + PC++; PC += ModRM(opc, PC, mode); if (TheCPU.mode & RM_REG) { - Gen(L_REG, _mode, REG3); + Gen(L_REG, mode, REG3); } else { /* add bit offset to effective address, then load and store from there */ - Gen(O_BITOP, _mode, (opc2-0xa0), REG1); - Gen(L_DI_R1, _mode); + Gen(O_BITOP, mode, (opc2-0xa0), REG1); + Gen(L_DI_R1, mode); } - Gen(O_BITOP, _mode|RM_REG, (opc2-0xa0), REG1); + Gen(O_BITOP, mode|RM_REG, (opc2-0xa0), REG1); if (opc2 != 0xa3) { if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode, REG3); + Gen(S_REG, mode, REG3); else - Gen(S_DI, _mode); + Gen(S_DI, mode); } break; case 0xbc: /* BSF */ case 0xbd: /* BSR */ - PC++; PC += ModRM(opc, PC, _mode|MLOAD); - _mode |= (TheCPU.mode & RM_REG); - Gen(O_BITOP, _mode, (opc2-0xa0), REG1); + PC++; PC += ModRM(opc, PC, mode|MLOAD); + mode |= (TheCPU.mode & RM_REG); + Gen(O_BITOP, mode, (opc2-0xa0), REG1); break; case 0xba: { /* GRP8 - Code Extension 22 */ unsigned char opm = (Fetch(PC+2))&0x38; @@ -3216,15 +3047,15 @@ repag0: case 0x28: /* BTS imm8 */ case 0x30: /* BTR imm8 */ case 0x38: /* BTC imm8 */ - PC++; PC += ModRM(opc, PC, _mode|MLOAD); - _mode |= (TheCPU.mode & RM_REG); - Gen(O_BITOP, _mode, opm, Fetch(PC)); + PC++; PC += ModRM(opc, PC, mode|MLOAD); + mode |= (TheCPU.mode & RM_REG); + Gen(O_BITOP, mode, opm, Fetch(PC)); if (opm != 0x20) { if (TheCPU.mode & RM_REG) { - Gen(S_REG, _mode, REG3); + Gen(S_REG, mode, REG3); } else { - Gen(S_DI, _mode); + Gen(S_DI, mode); } } PC++; @@ -3240,18 +3071,18 @@ repag0: /* Double Precision Shift Left by IMMED */ case 0xad: /* SHRDcl */ /* Double Precision Shift Left by CL */ - PC++; PC += ModRM(opc, PC, _mode|MLOAD); + PC++; PC += ModRM(opc, PC, mode|MLOAD); if (opc2&1) { - Gen(O_SHFD, _mode, (opc2&8), REG1); + Gen(O_SHFD, mode, (opc2&8), REG1); } else { - Gen(O_SHFD, _mode|IMMED, (opc2&8), REG1, Fetch(PC)); + Gen(O_SHFD, mode|IMMED, (opc2&8), REG1, Fetch(PC)); PC++; } if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode, REG3); + Gen(S_REG, mode, REG3); else - Gen(S_DI, _mode); + Gen(S_DI, mode); break; case 0xa6: /* CMPXCHGb (486 STEP A only) */ @@ -3260,21 +3091,21 @@ repag0: goto not_implemented; /// case 0xa8: /* PUSHgs */ - Gen(L_REG, _mode, Ofs_GS); - Gen(O_PUSH, _mode); PC+=2; + Gen(L_REG, mode, Ofs_GS); + Gen(O_PUSH, mode); PC+=2; break; case 0xa9: /* POPgs */ if (REALADDR()) { - Gen(O_POP, _mode); - Gen(S_REG, _mode, Ofs_GS); - AddrGen(A_SR_SH4, _mode, Ofs_GS, Ofs_XGS); + Gen(O_POP, mode); + Gen(S_REG, mode, Ofs_GS); + AddrGen(A_SR_SH4, mode, Ofs_GS, Ofs_XGS); } else { /* restartable */ unsigned short sv = 0; CODE_FLUSH(); - TOS_WORD(_mode, &sv); - TheCPU.err = MAKESEG(_mode, Ofs_GS, sv); + TOS_WORD(mode, &sv); + TheCPU.err = MAKESEG(mode, Ofs_GS, sv); if (TheCPU.err) return P0; - POP_ONLY(_mode); + POP_ONLY(mode); TheCPU.gs = sv; } PC+=2; @@ -3285,26 +3116,26 @@ repag0: goto illegal_op; /* case 0xae: Code Extension 24(MMX) */ case 0xaf: /* IMULregrm */ - PC++; PC += ModRM(opc, PC, _mode|MLOAD); - Gen(O_IMUL, _mode|MEMADR, REG1); // reg*[edi]->reg signed + PC++; PC += ModRM(opc, PC, mode|MLOAD); + Gen(O_IMUL, mode|MEMADR, REG1); // reg*[edi]->reg signed break; case 0xb0: /* CMPXCHGb */ - PC++; PC += ModRM(opc, PC, _mode|MBYTE|MLOAD); - _mode |= (TheCPU.mode & RM_REG); - Gen(O_CMPXCHG, _mode | MBYTE, REG1); + PC++; PC += ModRM(opc, PC, mode|MBYTE|MLOAD); + mode |= (TheCPU.mode & RM_REG); + Gen(O_CMPXCHG, mode | MBYTE, REG1); if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode | MBYTE, REG3); + Gen(S_REG, mode | MBYTE, REG3); else - Gen(S_DI, _mode | MBYTE); + Gen(S_DI, mode | MBYTE); break; case 0xb1: /* CMPXCHGw */ - PC++; PC += ModRM(opc, PC, _mode|MLOAD); - _mode |= (TheCPU.mode & RM_REG); - Gen(O_CMPXCHG, _mode, REG1); + PC++; PC += ModRM(opc, PC, mode|MLOAD); + mode |= (TheCPU.mode & RM_REG); + Gen(O_CMPXCHG, mode, REG1); if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode, REG3); + Gen(S_REG, mode, REG3); else - Gen(S_DI, _mode); + Gen(S_DI, mode); break; /// case 0xb2: /* LSS */ @@ -3313,21 +3144,21 @@ repag0: goto not_permitted; } if (REALADDR()) { - PC++; PC += ModRM(opc, PC, _mode); - Gen(L_LXS1, _mode, REG1); - Gen(L_LXS2, _mode, Ofs_SS, Ofs_XSS); + PC++; PC += ModRM(opc, PC, mode); + Gen(L_LXS1, mode, REG1); + Gen(L_LXS2, mode, Ofs_SS, Ofs_XSS); } else { unsigned short sv = 0; unsigned long rv; CODE_FLUSH(); - PC++; PC += ModRMSim(PC, _mode); - rv = DataGetWL_U(_mode,TheCPU.mem_ref); - TheCPU.mem_ref += BT24(BitDATA16,_mode); + PC++; PC += ModRMSim(PC, mode); + rv = DataGetWL_U(mode,TheCPU.mem_ref); + TheCPU.mem_ref += BT24(BitDATA16,mode); sv = GetDWord(TheCPU.mem_ref); - TheCPU.err = MAKESEG(_mode, Ofs_SS, sv); + TheCPU.err = MAKESEG(mode, Ofs_SS, sv); if (TheCPU.err) return P0; - SetCPU_WL(_mode, REG1, rv); + SetCPU_WL(mode, REG1, rv); TheCPU.ss = sv; } break; @@ -3337,21 +3168,21 @@ repag0: goto not_permitted; } if (REALADDR()) { - PC++; PC += ModRM(opc, PC, _mode); - Gen(L_LXS1, _mode, REG1); - Gen(L_LXS2, _mode, Ofs_FS, Ofs_XFS); + PC++; PC += ModRM(opc, PC, mode); + Gen(L_LXS1, mode, REG1); + Gen(L_LXS2, mode, Ofs_FS, Ofs_XFS); } else { unsigned short sv = 0; unsigned long rv; CODE_FLUSH(); - PC++; PC += ModRMSim(PC, _mode); - rv = DataGetWL_U(_mode,TheCPU.mem_ref); - TheCPU.mem_ref += BT24(BitDATA16,_mode); + PC++; PC += ModRMSim(PC, mode); + rv = DataGetWL_U(mode,TheCPU.mem_ref); + TheCPU.mem_ref += BT24(BitDATA16,mode); sv = GetDWord(TheCPU.mem_ref); - TheCPU.err = MAKESEG(_mode, Ofs_FS, sv); + TheCPU.err = MAKESEG(mode, Ofs_FS, sv); if (TheCPU.err) return P0; - SetCPU_WL(_mode, REG1, rv); + SetCPU_WL(mode, REG1, rv); TheCPU.fs = sv; } break; @@ -3361,39 +3192,39 @@ repag0: goto not_permitted; } if (REALADDR()) { - PC++; PC += ModRM(opc, PC, _mode); - Gen(L_LXS1, _mode, REG1); - Gen(L_LXS2, _mode, Ofs_GS, Ofs_XGS); + PC++; PC += ModRM(opc, PC, mode); + Gen(L_LXS1, mode, REG1); + Gen(L_LXS2, mode, Ofs_GS, Ofs_XGS); } else { unsigned short sv = 0; unsigned long rv; CODE_FLUSH(); - PC++; PC += ModRMSim(PC, _mode); - rv = DataGetWL_U(_mode,TheCPU.mem_ref); - TheCPU.mem_ref += BT24(BitDATA16,_mode); + PC++; PC += ModRMSim(PC, mode); + rv = DataGetWL_U(mode,TheCPU.mem_ref); + TheCPU.mem_ref += BT24(BitDATA16,mode); sv = GetDWord(TheCPU.mem_ref); - TheCPU.err = MAKESEG(_mode, Ofs_GS, sv); + TheCPU.err = MAKESEG(mode, Ofs_GS, sv); if (TheCPU.err) return P0; - SetCPU_WL(_mode, REG1, rv); + SetCPU_WL(mode, REG1, rv); TheCPU.gs = sv; } break; case 0xb6: /* MOVZXb */ - PC++; PC += ModRM(opc, PC, _mode|MBYTX|MLOAD); - Gen(L_MOVZS, _mode|MBYTX, 0, REG1); + PC++; PC += ModRM(opc, PC, mode|MBYTX|MLOAD); + Gen(L_MOVZS, mode|MBYTX, 0, REG1); break; case 0xb7: /* MOVZXw */ - PC++; PC += ModRM(opc, PC, _mode|DATA16|MLOAD); - Gen(L_MOVZS, _mode, 0, REG1); + PC++; PC += ModRM(opc, PC, mode|DATA16|MLOAD); + Gen(L_MOVZS, mode, 0, REG1); break; case 0xbe: /* MOVSXb */ - PC++; PC += ModRM(opc, PC, _mode|MBYTX|MLOAD); - Gen(L_MOVZS, _mode|MBYTX, 1, REG1); + PC++; PC += ModRM(opc, PC, mode|MBYTX|MLOAD); + Gen(L_MOVZS, mode|MBYTX, 1, REG1); break; case 0xbf: /* MOVSXw */ - PC++; PC += ModRM(opc, PC, _mode|DATA16|MLOAD); - Gen(L_MOVZS, _mode, 1, REG1); + PC++; PC += ModRM(opc, PC, mode|DATA16|MLOAD); + Gen(L_MOVZS, mode, 1, REG1); break; /// case 0xb8: /* JMP absolute to IA64 code */ @@ -3401,22 +3232,22 @@ repag0: CODE_FLUSH(); goto illegal_op; /* UD2 */ case 0xc0: /* XADDb */ - PC++; PC += ModRM(opc, PC, _mode|MBYTE|MLOAD); - Gen(O_XCHG, _mode | MBYTE, REG1); - Gen(O_ADD_R, _mode | MBYTE, REG1); + PC++; PC += ModRM(opc, PC, mode|MBYTE|MLOAD); + Gen(O_XCHG, mode | MBYTE, REG1); + Gen(O_ADD_R, mode | MBYTE, REG1); if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode|MBYTE, REG3); + Gen(S_REG, mode|MBYTE, REG3); else - Gen(S_DI, _mode|MBYTE); + Gen(S_DI, mode|MBYTE); break; case 0xc1: /* XADDw */ - PC++; PC += ModRM(opc, PC, _mode|MLOAD); - Gen(O_XCHG, _mode, REG1); - Gen(O_ADD_R, _mode, REG1); + PC++; PC += ModRM(opc, PC, mode|MLOAD); + Gen(O_XCHG, mode, REG1); + Gen(O_ADD_R, mode, REG1); if (TheCPU.mode & RM_REG) - Gen(S_REG, _mode, REG3); + Gen(S_REG, mode, REG3); else - Gen(S_DI, _mode); + Gen(S_DI, mode); break; /* case 0xc2-0xc6: MMX */ @@ -3427,7 +3258,7 @@ repag0: modrm = Fetch(PC+2); if (D_MO(modrm) != 1 || D_HO(modrm) == 3) goto illegal_op; - PC++; PC += ModRMSim(PC, _mode); + PC++; PC += ModRMSim(PC, mode); edxeax = ((uint64_t)rEDX << 32) | rEAX; m = read_qword(TheCPU.mem_ref); if (edxeax == m) @@ -3452,7 +3283,7 @@ repag0: case 0xcd: /* BSWAPebp */ case 0xce: /* BSWAPesi */ case 0xcf: /* BSWAPedi */ - if (!(_mode&DATA16)) { + if (!(mode&DATA16)) { Gen(O_BSWAP, 0, R1Tab_l[D_LO(opc2)]); } /* else undefined */ PC+=2; break; @@ -3481,14 +3312,58 @@ repag0: } if (TheCPU.err < 0) return P0; + if (NewNode) { + int rc=0; + if (!CONFIG_CPUSIM && !(TheCPU.mode&SKIPOP)) { + NewIMeta(P0, &rc); + if (rc < 0) { + if (debug_level('e')>2) + e_printf("============ Tab full:cannot close sequence\n"); + CODE_FLUSH(); + NewIMeta(P0, &rc); + NewNode = 1; + } + } + } + else + { + if (eTimeCorrect >= 0) + TheCPU.EMUtime += FAKE_INS_TIME; + } - /* check segment boundaries. TODO for prot _mode */ + /* check segment boundaries. TODO for prot mode */ if (REALADDR() && (PC - LONG_CS > 0xffff)) { e_printf("PC out of bounds, %x\n", PC - LONG_CS); CODE_FLUSH(); goto not_permitted; } - return PC; + +#ifdef SINGLEBLOCK + if (!CONFIG_CPUSIM && NewNode && CurrIMeta > 0) { + P0 = PC; + CODE_FLUSH(); + } +#endif + + if (NewNode && (CEmuStat & CeS_TRAP)) { + P0 = PC; + CODE_FLUSH(); + } + if (CEmuStat & CeS_MOVSS) { + /* following non-compiled (sim or protected mode) + mov ss / pop ss only */ + if (!(CEmuStat & CeS_INHI)) { + // directly following mov ss / pop ss + CEmuStat |= CeS_INHI; + CEmuStat &= ~CeS_TRAP; + } else { + // instruction after clear unconditionally + // even if it's another mov ss / pop ss + CEmuStat &= ~(CeS_INHI|CeS_MOVSS); + } + } + } + return 0; not_implemented: dbug_printf("!!! Unimplemented %02x %02x %02x at %08x\n",opc, @@ -3506,8 +3381,3 @@ illegal_op: TheCPU.err = EXCP06_ILLOP; return P0; } -/* reset for VGA reads and writes */ -void instr_emu_sim_reset_count(int cnt) -{ - interp_inst_emu_count = cnt; -} diff --git a/src/base/emu-i386/simx86/memory.c b/src/base/emu-i386/simx86/memory.c index 1e9b985..166097f 100644 --- a/src/base/emu-i386/simx86/memory.c +++ b/src/base/emu-i386/simx86/memory.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ @@ -106,8 +106,8 @@ static int AddMpMap(unsigned int addr, unsigned int aend, int onoff) M->mega = (page>>8); } if (bp < 32) { - bs |= (((unsigned)(onoff? test_and_set_bit(page&255, M->pagemap) : - test_and_clear_bit(page&255, M->pagemap)) & 1) << bp); + bs |= (((unsigned)(onoff? set_bit(page&255, M->pagemap) : + clear_bit(page&255, M->pagemap)) & 1) << bp); bp++; } if (debug_level('e')>1) { @@ -123,7 +123,7 @@ static int AddMpMap(unsigned int addr, unsigned int aend, int onoff) } -int e_querymprot(dosaddr_t addr) +static inline int e_querymprot(unsigned int addr) { register int a2 = addr >> PAGE_SHIFT; tMpMap *M = FindM(addr); @@ -168,7 +168,6 @@ int e_markpage(unsigned int addr, size_t len) dbug_printf("MARK from %08x to %08x for %08x\n", abeg<subpage)); set_bit(abeg&CGRMASK, M->subpage); abeg++; if ((abeg&CGRMASK) == 0) @@ -198,8 +197,8 @@ int e_unmarkpage(unsigned int addr, size_t len) } /* check if unmarked pages have no more code, and if so, unprotect */ - abeg = addr & _PAGE_MASK; - aend = (addr + len) & _PAGE_MASK; + abeg = addr & PAGE_MASK; + aend = (addr + len) & PAGE_MASK; /* don't unprotect partial first page with code (if not also last) */ if (aend != abeg && abeg != addr && e_querymark(abeg, PAGE_SIZE)) abeg += PAGE_SIZE; @@ -245,8 +244,6 @@ int e_querymark(unsigned int addr, size_t len) mask = ~0ULL; if (idx == sizeof(M->subpage)/sizeof(M->subpage[0])) { M = M->next; - if (!M) - return 0; idx = 0; } } @@ -259,7 +256,7 @@ int e_querymark(unsigned int addr, size_t len) return 0; found: if (debug_level('e')>1) { -// if (len > 1) abeg += ffsll(M->subpage[idx] & mask) - 1; + if (len > 1) abeg += ffsll(M->subpage[idx] & mask) - 1; dbug_printf("QUERY MARK found code at " "%08x to %08x for %08x\n", abeg<1 || in_dosemu) { v = *((int *)p); __asm__("bswap %0" : "=r" (v) : "0" (v)); e_printf("Faulting ops: %08x\n",v); if (!InCompiledCode) { - unsigned int cs = in_vm86 ? _CS : _scp_cs; - greg_t eip = in_vm86 ? _IP : _scp_rip; + unsigned int cs = in_vm86 ? _CS : _cs; + greg_t eip = in_vm86 ? _IP : _rip; e_printf("*\tFault out of %scode, cs:eip=%x:%llx," " cr2=%x, fault_cnt=%d\n", in_dosemu ? "DOSEMU " : "", @@ -453,7 +450,7 @@ int e_handle_pagefault(dosaddr_t addr, unsigned err, sigcontext_t *scp) #endif /* We HAVE to invalidate all the code in the page * if the page is going to be unprotected */ - addr &= _PAGE_MASK; + addr &= PAGE_MASK; return InvalidateNodeRange(addr, PAGE_SIZE, p); } @@ -462,16 +459,16 @@ int e_handle_fault(sigcontext_t *scp) if (!InCompiledCode) return 0; /* page-faults are handled not here and only DE remains */ - if (_scp_trapno != 0) { - error("Fault %i in jit-compiled code\n", _scp_trapno); + if (_trapno != 0) { + error("Fault %i in jit-compiled code\n", _trapno); return 0; } - TheCPU.err = EXCP00_DIVZ + _scp_trapno; - _scp_eax = TheCPU.cr2; - _scp_edx = _scp_eflags; - TheCPU.cr2 = DOSADDR_REL(LINP(_scp_cr2)); - _scp_rip = *(long *)_scp_rsp; - _scp_rsp += sizeof(long); + TheCPU.err = EXCP00_DIVZ + _trapno; + _eax = TheCPU.cr2; + _edx = _eflags; + TheCPU.cr2 = _cr2; + _rip = *(long *)_rsp; + _rsp += sizeof(long); return 1; } #endif diff --git a/src/base/emu-i386/simx86/modrm-gen.c b/src/base/emu-i386/simx86/modrm-gen.c index 9a673a7..d665511 100644 --- a/src/base/emu-i386/simx86/modrm-gen.c +++ b/src/base/emu-i386/simx86/modrm-gen.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ diff --git a/src/base/emu-i386/simx86/modrm-sim.c b/src/base/emu-i386/simx86/modrm-sim.c index 912dc16..3956122 100644 --- a/src/base/emu-i386/simx86/modrm-sim.c +++ b/src/base/emu-i386/simx86/modrm-sim.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ @@ -37,7 +37,7 @@ #include "codegen-sim.h" /* - * Why this one? It is only a duplicate of modrm-gen but it interprets + * Why this one? It is only a duplicate of modrm-gen but it interpretes * addresses instead of compiling them. After some headaches I decided * that it was better to have a duplicate than to parse,compile,execute, * find the node,delete it etc. @@ -55,7 +55,7 @@ int ModRMSim(unsigned int PC, int mode) AddrGen = AddrGen_sim; l = _ModRM(0, PC, mode); AddrGen = AddrGen_save; - TheCPU.mem_ref = AR1.d; + TheCPU.mem_ref = AR1.d - TheCPU.mem_base; return l; } diff --git a/src/base/emu-i386/simx86/protmode.c b/src/base/emu-i386/simx86/protmode.c index 00ccd04..b5a530c 100644 --- a/src/base/emu-i386/simx86/protmode.c +++ b/src/base/emu-i386/simx86/protmode.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * * linux/kernel/ldt.c @@ -84,7 +84,7 @@ int SetSegReal(unsigned short sel, int ofs) sd = (SDTR *)CPUOFFS(e_ofsseg[(ofs>>2)]); CPUWORD(ofs) = sel; - sd->BoundL = sel<<4; + sd->BoundL = (sel<<4) + TheCPU.mem_base; sd->BoundH = sd->BoundL + 0xffff; sd->Attrib = 2; @@ -191,7 +191,7 @@ int SetSegProt(int a16, int ofs, unsigned char *big, unsigned long sel) e_printf("Small segment %#lx in 32-bit mode\n",sel); } SetFlagAccessed(sel); - sd->BoundL = GetPhysicalAddress(sel); + sd->BoundL = GetPhysicalAddress(sel) + TheCPU.mem_base; sd->BoundH = sd->BoundL + GetSelectorByteLimit(sel); sd->Attrib = (lbig&4) | 1; e_printf("SetSeg PROT %s%04lx\n",MKOFSNAM(ofs,buf),sel); @@ -369,20 +369,20 @@ void emu_mhp_SetTypebyte (unsigned short selector, int typebyte) /* ======================================================================= */ -int emu_ldt_write(dosaddr_t addr, uint32_t op, int len) +int emu_ldt_write(unsigned char *paddr, uint32_t op, int len) { - static cpuctx_t sc = {0}; - cpuctx_t *scp = ≻ + static sigcontext_t sc = {0}; + sigcontext_t *scp = ≻ - if (!(msdos_ldt_access(addr))) + if (!(msdos_ldt_access(paddr))) return 0; - _cr2 = addr; + _cr2 = (uintptr_t)paddr; _ds = TheCPU.ds; _es = TheCPU.es; _fs = TheCPU.fs; _gs = TheCPU.gs; - msdos_ldt_write(scp, op, len, _cr2); + msdos_ldt_write(scp, op, len, (unsigned char *)_cr2); if (_ds == 0) { TheCPU.ds = 0; SetSegProt(0,Ofs_DS,NULL,0); } if (_es == 0) { TheCPU.es = 0; SetSegProt(0,Ofs_ES,NULL,0); } if (_fs == 0) { TheCPU.fs = 0; SetSegProt(0,Ofs_FS,NULL,0); } @@ -396,7 +396,7 @@ void emu_pagefault_handler(dosaddr_t addr, int err, uint32_t op, int len) default_sim_pagefault_handler(addr, err, op, len); return; } - if ((err & 2) && emu_ldt_write(addr, op, len)) + if ((err & 2) && emu_ldt_write(MEM_BASE32(addr), op, len)) return; /* trigger an exception in DPMI */ TheCPU.err = EXCP0E_PAGE; diff --git a/src/base/emu-i386/simx86/protmode.h b/src/base/emu-i386/simx86/protmode.h index e8b514c..e7fd4aa 100644 --- a/src/base/emu-i386/simx86/protmode.h +++ b/src/base/emu-i386/simx86/protmode.h @@ -230,12 +230,8 @@ int SetSegReal(unsigned short sel, int ofs); int e_larlsl(int mode, unsigned short sel); int hsw_verr(unsigned short sel); int hsw_verw(unsigned short sel); -int emu_ldt_write(dosaddr_t addr, uint32_t op, int len); +int emu_ldt_write(unsigned char *paddr, uint32_t op, int len); void emu_pagefault_handler(dosaddr_t addr, int err, uint32_t op, int len); // -extern Descriptor *GDT; -extern Descriptor *LDT; -extern Gatedesc *IDT; - #endif diff --git a/src/base/emu-i386/simx86/sigsegv.c b/src/base/emu-i386/simx86/sigsegv.c index dada026..2abdba2 100644 --- a/src/base/emu-i386/simx86/sigsegv.c +++ b/src/base/emu-i386/simx86/sigsegv.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ @@ -136,48 +136,20 @@ void e_VgaMovs(unsigned char **rdi, unsigned char **rsi, unsigned int rep, static int jitx86_instr_len(const unsigned char *rip) { const unsigned char *p = rip; - int len; if (*p==0xf3) p++; /* rep */ if (*p==0x66) p++; /* word */ - len = p - rip + 2; /* moves */ - if (*p >= 0x88 && *p <= 0x8b) { - int disp32_still_possible = 0; - switch (p[1] & 0xc0) { /* decode modifier */ - case 0: /* disp32 possible */ - switch (p[1] & 0x07) { /* decode rm */ - case 5: /* disp32 actually here */ - len += 4; - break; - case 4: /* disp32 is still possible in SIB byte */ - disp32_still_possible = 1; - break; - } - break; - case 0x40: /* have disp8 */ - len++; - break; - case 0x80: /* have disp32 */ - len += 4; - break; - } - if ((p[1] & 0xc0) < 0xc0 /* SIB byte possible */ - && (p[1] & 0x07) == 4) { /* SIB actually here */ - len++; - if (disp32_still_possible && (p[2] & 0x07) == 5) /* disp32 used by SIB */ - len += 4; - } - return len; - } + if (*p >= 0x88 && *p <= 0x8b) + return p - rip + 2; /* string moves */ if (*p >= 0xa4 && *p <= 0xad) return p - rip + 1; return 0; } -static int e_vgaemu_fault(sigcontext_t *scp, unsigned page_fault) +int e_vgaemu_fault(sigcontext_t *scp, unsigned page_fault) { int i, j; unsigned vga_page = 0, u=0; @@ -196,8 +168,12 @@ static int e_vgaemu_fault(sigcontext_t *scp, unsigned page_fault) if (i == VGAEMU_MAX_MAPPINGS) { if ((unsigned)((page_fault << 12) - vga.mem.graph_base) < vga.mem.graph_size) { /* unmapped VGA area */ - u = jitx86_instr_len((unsigned char *)_scp_rip); - _scp_rip += u; +#ifdef HOST_ARCH_X86 + if (!CONFIG_CPUSIM) { + u = jitx86_instr_len((unsigned char *)_rip); + _rip += u; + } +#endif if (u==0) { e_printf("eVGAEmuFault: unknown instruction, page at 0x%05x now writable\n", page_fault << 12); vga_emu_protect_page(page_fault, 2); @@ -205,10 +181,14 @@ static int e_vgaemu_fault(sigcontext_t *scp, unsigned page_fault) } return 1; } - else if (memcheck_is_rom(page_fault << PAGE_SHIFT)) { /* ROM area */ - u = jitx86_instr_len((unsigned char *)_scp_rip); - _scp_rip += u; - if (u==0 || (_scp_err&2)==0) { + else if (page_fault >= 0xc0 && page_fault < (0xc0 + vgaemu_bios.pages)) { /* ROM area */ +#ifdef HOST_ARCH_X86 + if (!CONFIG_CPUSIM) { + u = jitx86_instr_len((unsigned char *)_rip); + _rip += u; + } +#endif + if (u==0 || (_err&2)==0) { e_printf("eVGAEmuFault: unknown instruction, converting ROM to RAM at 0x%05x\n", page_fault << 12); vga_emu_protect_page(page_fault, 2); /**/ leavedos_main(0x5641); @@ -223,14 +203,14 @@ static int e_vgaemu_fault(sigcontext_t *scp, unsigned page_fault) } if (vga_page < vga.mem.pages) { -/**/ e_printf("eVGAEmuFault: trying %08x\n",*((int *)_scp_rip)); +/**/ e_printf("eVGAEmuFault: trying %08x, a=%08"PRI_RG"\n",*((int *)_rip),_rdi); /* try CPatch, which should not fail */ if (Cpatch(scp)) return 1; } error("eVGAEmuFault: unimplemented decode instr at %08"PRI_RG": %08x\n", - _scp_rip, *((int *)_scp_rip)); + _rip, *((int *)_rip)); leavedos_from_sig(0x5643); return 0; } @@ -249,61 +229,33 @@ static int e_vgaemu_fault(sigcontext_t *scp, unsigned page_fault) #define GetSegmentBaseAddress(s) GetSegmentBase(s) /* this function is called from dosemu_fault */ -static int e_emu_pagefault(sigcontext_t *scp, int pmode) +int e_emu_pagefault(sigcontext_t *scp, int pmode) { if (InCompiledCode) { - dosaddr_t cr2 = DOSADDR_REL(LINP(_scp_cr2)); + dosaddr_t cr2 = DOSADDR_REL(LINP(_cr2)); if (e_vgaemu_fault(scp, cr2 >> 12) == 1) return 1; #ifdef HOST_ARCH_X86 - if (e_handle_pagefault(cr2, _scp_err, scp)) + if (e_handle_pagefault(cr2, _err, scp)) return 1; #endif /* use CPatch for LDT page faults, which should not fail */ - if (msdos_ldt_access(cr2) && Cpatch(scp)) + if (msdos_ldt_access((unsigned char *)_cr2) && Cpatch(scp)) return 1; - TheCPU.scp_err = _scp_err; + TheCPU.scp_err = _err; /* save eip, eflags, and do a "ret" out of compiled code */ TheCPU.err = EXCP0E_PAGE; - _scp_eax = FindPC((unsigned char *)_scp_rip); - e_printf("FindPC: found %x\n",_scp_eax); - _scp_edx = *(long *)_scp_rsp; // flags - _scp_rsp += sizeof(long); - TheCPU.cr2 = cr2; - _scp_rip = *(long *)_scp_rsp; - _scp_rsp += sizeof(long); + _eax = FindPC((unsigned char *)_rip); + e_printf("FindPC: found %x\n",_eax); + _edx = *(long *)_rsp; // flags + _rsp += sizeof(long); + TheCPU.cr2 = _cr2; + _rip = *(long *)_rsp; + _rsp += sizeof(long); return 1; } return 0; } -int e_emu_fault(sigcontext_t *scp, int in_vm86) -{ - /* Possibilities: - * 1. Compiled code touches VGA prot - * 2. Compiled code touches cpuemu prot - * 3. Compiled code touches DPMI prot - * 4. reserved, was "fullsim code touches DPMI prot", but fullsim - * no longer faults since commit 70ca014459 - * 5. dosemu code touches cpuemu prot (bug) - * Compiled code means dpmi-jit, otherwise vm86 not here. - */ - if (_scp_trapno == 0x0e) { - /* cases 1, 2, 3 */ - if ((in_vm86 || EMU_DPMI()) && e_emu_pagefault(scp, !in_vm86)) - return 1; - /* case 5, any jit, bug */ - if (e_handle_pagefault(DOSADDR_REL(LINP(_scp_cr2)), _scp_err, scp)) { - dosemu_error("touched jit-protected page%s\n", - in_vm86 ? " in vm86-emu" : ""); - return 1; - } - } else if ((in_vm86 || EMU_DPMI()) && e_handle_fault(scp)) { - /* compiled code can cause fault (usually DE, Divide Exception) */ - return 1; - } - return 0; -} - /* ======================================================================= */ diff --git a/src/base/emu-i386/simx86/softfloat/Makefile b/src/base/emu-i386/simx86/softfloat/Makefile deleted file mode 100644 index 439028a..0000000 --- a/src/base/emu-i386/simx86/softfloat/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". -# -# for details see file COPYING.DOSEMU in the DOSEMU distribution -# - -top_builddir=../../../../.. -include $(top_builddir)/Makefile.conf - - -CFILES = softfloat.c - -include $(REALTOPDIR)/src/Makefile.common diff --git a/src/base/emu-i386/simx86/softfloat/softfloat-macros.h b/src/base/emu-i386/simx86/softfloat/softfloat-macros.h deleted file mode 100644 index e737775..0000000 --- a/src/base/emu-i386/simx86/softfloat/softfloat-macros.h +++ /dev/null @@ -1,606 +0,0 @@ -/* - * QEMU float support macros - * - * Derived from SoftFloat. - */ - -/*============================================================================ - -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. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| This macro tests for minimum version of the GNU C compiler. -*----------------------------------------------------------------------------*/ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) -#define SOFTFLOAT_GNUC_PREREQ(maj, min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -#else -#define SOFTFLOAT_GNUC_PREREQ(maj, min) 0 -#endif - -/*---------------------------------------------------------------------------- -| 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. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -SINLINE void shift32RightJamming(uint32_t a, int16 count, uint32_t *zPtr) { - uint32_t z; - - if (count == 0) { - z = a; - } else if (count < 32) { - z = (a >> count) | ((a << ((-count) & 31)) != 0); - } else { - z = (a != 0); - } - *zPtr = 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. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -SINLINE void shift64RightJamming(uint64_t a, int16 count, uint64_t *zPtr) { - uint64_t z; - - if (count == 0) { - z = a; - } else if (count < 64) { - z = (a >> count) | ((a << ((-count) & 63)) != 0); - } else { - z = (a != 0); - } - *zPtr = 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'.) -*----------------------------------------------------------------------------*/ - -SINLINE void shift64ExtraRightJamming(uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr) { - uint64_t z0, z1; - int8 negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } else if (count < 64) { - z1 = (a0 << negCount) | (a1 != 0); - z0 = a0 >> count; - } else { - if (count == 64) { - z1 = a0 | (a1 != 0); - } else { - z1 = ((a0 | a1) != 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'. 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'. -*----------------------------------------------------------------------------*/ - -SINLINE void shift128Right(uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr) { - uint64_t z0, z1; - int8 negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } else if (count < 64) { - z1 = (a0 << negCount) | (a1 >> count); - z0 = a0 >> count; - } else { - z1 = (count < 64) ? (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'. -*----------------------------------------------------------------------------*/ - -SINLINE void shift128RightJamming(uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr) { - uint64_t z0, z1; - int8 negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } else if (count < 64) { - z1 = (a0 << negCount) | (a1 >> count) | ((a1 << negCount) != 0); - z0 = a0 >> count; - } else { - if (count == 64) { - z1 = a0 | (a1 != 0); - } else if (count < 128) { - z1 = (a0 >> (count & 63)) | (((a0 << negCount) | a1) != 0); - } else { - z1 = ((a0 | a1) != 0); - } - z0 = 0; - } - *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'.) -*----------------------------------------------------------------------------*/ - -SINLINE void shift128ExtraRightJamming(uint64_t a0, uint64_t a1, uint64_t a2, int16 count, uint64_t *z0Ptr, - uint64_t *z1Ptr, uint64_t *z2Ptr) { - uint64_t z0, z1, z2; - int8 negCount = (-count) & 63; - - if (count == 0) { - z2 = a2; - z1 = a1; - z0 = a0; - } else { - if (count < 64) { - z2 = a1 << negCount; - z1 = (a0 << negCount) | (a1 >> count); - z0 = a0 >> count; - } else { - if (count == 64) { - z2 = a1; - z1 = a0; - } else { - a2 |= a1; - if (count < 128) { - z2 = a0 << negCount; - z1 = a0 >> (count & 63); - } else { - z2 = (count == 128) ? a0 : (a0 != 0); - z1 = 0; - } - } - z0 = 0; - } - z2 |= (a2 != 0); - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| 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'. -*----------------------------------------------------------------------------*/ - -SINLINE void shortShift128Left(uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr) { - - *z1Ptr = a1 << count; - *z0Ptr = (count == 0) ? a0 : (a0 << count) | (a1 >> ((-count) & 63)); -} - -/*---------------------------------------------------------------------------- -| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' 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 three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -SINLINE void shortShift192Left(uint64_t a0, uint64_t a1, uint64_t a2, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr, - uint64_t *z2Ptr) { - uint64_t z0, z1, z2; - int8 negCount; - - z2 = a2 << count; - z1 = a1 << count; - z0 = a0 << count; - if (0 < count) { - negCount = ((-count) & 63); - z1 |= a2 >> negCount; - z0 |= a1 >> negCount; - } - *z2Ptr = z2; - *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'. -*----------------------------------------------------------------------------*/ - -SINLINE void add128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr) { - uint64_t z1; - - z1 = a1 + b1; - *z1Ptr = z1; - *z0Ptr = a0 + b0 + (z1 < a1); -} - -/*---------------------------------------------------------------------------- -| 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'. -*----------------------------------------------------------------------------*/ - -SINLINE void add192(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t b0, uint64_t b1, uint64_t b2, uint64_t *z0Ptr, - uint64_t *z1Ptr, uint64_t *z2Ptr) { - uint64_t z0, z1, z2; - int8 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'. -*----------------------------------------------------------------------------*/ - -SINLINE void sub128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr) { - - *z1Ptr = a1 - b1; - *z0Ptr = a0 - b0 - (a1 < b1); -} - -/*---------------------------------------------------------------------------- -| 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'. -*----------------------------------------------------------------------------*/ - -SINLINE void sub192(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t b0, uint64_t b1, uint64_t b2, uint64_t *z0Ptr, - uint64_t *z1Ptr, uint64_t *z2Ptr) { - uint64_t z0, z1, z2; - int8 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; -} - -/*---------------------------------------------------------------------------- -| 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'. -*----------------------------------------------------------------------------*/ - -SINLINE void mul64To128(uint64_t a, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr) { - uint32_t aHigh, aLow, bHigh, bLow; - uint64_t z0, zMiddleA, zMiddleB, z1; - - aLow = a; - aHigh = a >> 32; - bLow = b; - bHigh = b >> 32; - z1 = ((uint64_t) aLow) * bLow; - zMiddleA = ((uint64_t) aLow) * bHigh; - zMiddleB = ((uint64_t) aHigh) * bLow; - z0 = ((uint64_t) aHigh) * bHigh; - zMiddleA += zMiddleB; - z0 += (((uint64_t)(zMiddleA < zMiddleB)) << 32) + (zMiddleA >> 32); - zMiddleA <<= 32; - z1 += zMiddleA; - z0 += (z1 < zMiddleA); - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| 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'. -*----------------------------------------------------------------------------*/ - -SINLINE void mul128By64To192(uint64_t a0, uint64_t a1, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr, uint64_t *z2Ptr) { - uint64_t 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; -} - -/*---------------------------------------------------------------------------- -| 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'. -*----------------------------------------------------------------------------*/ - -SINLINE void mul128To256(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr, - uint64_t *z2Ptr, uint64_t *z3Ptr) { - uint64_t z0, z1, z2, z3; - uint64_t 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; -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static uint64_t estimateDiv128To64(uint64_t a0, uint64_t a1, uint64_t b) { - uint64_t b0, b1; - uint64_t rem0, rem1, term0, term1; - uint64_t z; - - if (b <= a0) - return LIT64(0xFFFFFFFFFFFFFFFF); - b0 = b >> 32; - z = (b0 << 32 <= a0) ? LIT64(0xFFFFFFFF00000000) : (a0 / b0) << 32; - mul64To128(b, z, &term0, &term1); - sub128(a0, a1, term0, term1, &rem0, &rem1); - while (((int64_t) rem0) < 0) { - z -= LIT64(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; -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static uint32_t estimateSqrt32(int16 aExp, uint32_t a) { - static const uint16_t sqrtOddAdjustments[] = {0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67}; - static const uint16_t sqrtEvenAdjustments[] = {0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002}; - int8 index; - uint32_t z; - - index = (a >> 27) & 15; - if (aExp & 1) { - z = 0x4000 + (a >> 17) - sqrtOddAdjustments[(int) index]; - z = ((a / z) << 14) + (z << 15); - a >>= 1; - } else { - z = 0x8000 + (a >> 17) - sqrtEvenAdjustments[(int) index]; - z = a / z + z; - z = (0x20000 <= z) ? 0xFFFF8000 : (z << 15); - if (z <= a) - return (uint32_t)(((int32_t) a) >> 1); - } - return ((uint32_t)((((uint64_t) a) << 31) / z)) + (z >> 1); -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 32 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros32(uint32_t a) { -#if SOFTFLOAT_GNUC_PREREQ(3, 4) - if (a) { - return __builtin_clz(a); - } else { - return 32; - } -#else - static const int8 countLeadingZerosHigh[] = { - 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}; - int8 shiftCount; - - shiftCount = 0; - if (a < 0x10000) { - shiftCount += 16; - a <<= 16; - } - if (a < 0x1000000) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZerosHigh[a >> 24]; - return shiftCount; -#endif -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros64(uint64_t a) { -#if SOFTFLOAT_GNUC_PREREQ(3, 4) - if (a) { - return __builtin_clzll(a); - } else { - return 64; - } -#else - int8 shiftCount; - - shiftCount = 0; - if (a < ((uint64_t) 1) << 32) { - shiftCount += 32; - } else { - a >>= 32; - } - shiftCount += countLeadingZeros32(a); - return shiftCount; -#endif -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -SINLINE flag eq128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t 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. -*----------------------------------------------------------------------------*/ - -SINLINE flag le128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t 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. -*----------------------------------------------------------------------------*/ - -SINLINE flag lt128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1) { - - return (a0 < b0) || ((a0 == b0) && (a1 < b1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is -| not equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -SINLINE flag ne128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1) { - - return (a0 != b0) || (a1 != b1); -} diff --git a/src/base/emu-i386/simx86/softfloat/softfloat-specialize.h b/src/base/emu-i386/simx86/softfloat/softfloat-specialize.h deleted file mode 100644 index 45ff01a..0000000 --- a/src/base/emu-i386/simx86/softfloat/softfloat-specialize.h +++ /dev/null @@ -1,993 +0,0 @@ -/* - * QEMU float support - * - * Derived from SoftFloat. - */ - -/*============================================================================ - -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. - -=============================================================================*/ - -#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32) -#define SNAN_BIT_IS_ONE 1 -#else -#define SNAN_BIT_IS_ONE 0 -#endif - -/*---------------------------------------------------------------------------- -| The pattern for a default generated half-precision NaN. -*----------------------------------------------------------------------------*/ -#if defined(TARGET_ARM) -const float16 float16_default_nan = const_float16(0x7E00); -#elif SNAN_BIT_IS_ONE -const float16 float16_default_nan = const_float16(0x7DFF); -#else -const float16 float16_default_nan = const_float16(0xFE00); -#endif - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -#if defined(TARGET_SPARC) -const float32 float32_default_nan = const_float32(0x7FFFFFFF); -#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) -const float32 float32_default_nan = const_float32(0x7FC00000); -#elif SNAN_BIT_IS_ONE -const float32 float32_default_nan = const_float32(0x7FBFFFFF); -#else -const float32 float32_default_nan = const_float32(0xFFC00000); -#endif - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -#if defined(TARGET_SPARC) -const float64 float64_default_nan = const_float64(LIT64(0x7FFFFFFFFFFFFFFF)); -#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) -const float64 float64_default_nan = const_float64(LIT64(0x7FF8000000000000)); -#elif SNAN_BIT_IS_ONE -const float64 float64_default_nan = const_float64(LIT64(0x7FF7FFFFFFFFFFFF)); -#else -const float64 float64_default_nan = const_float64(LIT64(0xFFF8000000000000)); -#endif - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ -#if SNAN_BIT_IS_ONE -#define floatx80_default_nan_high 0x7FFF -#define floatx80_default_nan_low LIT64(0xBFFFFFFFFFFFFFFF) -#else -#define floatx80_default_nan_high 0xFFFF -#define floatx80_default_nan_low LIT64(0xC000000000000000) -#endif - -const floatx80 floatx80_default_nan = make_floatx80_init(floatx80_default_nan_high, floatx80_default_nan_low); - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#if SNAN_BIT_IS_ONE -#define float128_default_nan_high LIT64(0x7FFF7FFFFFFFFFFF) -#define float128_default_nan_low LIT64(0xFFFFFFFFFFFFFFFF) -#else -#define float128_default_nan_high LIT64(0xFFFF800000000000) -#define float128_default_nan_low LIT64(0x0000000000000000) -#endif - -const float128 float128_default_nan = make_float128_init(float128_default_nan_high, float128_default_nan_low); - -/*---------------------------------------------------------------------------- -| Raises the exceptions specified by `flags'. Floating-point traps can be -| defined here if desired. It is currently not possible for such a trap -| to substitute a result value. If traps are not implemented, this routine -| should be simply `float_exception_flags |= flags;'. -*----------------------------------------------------------------------------*/ - -void float_raise(uint8_t flags STATUS_PARAM) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | flags)); -} - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ -typedef struct { - flag sign; - uint64_t high, low; -} commonNaNT; - -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is a quiet -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float16_is_quiet_nan(float16 a_) { - uint16_t a = float16_val(a_); -#if SNAN_BIT_IS_ONE - return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF); -#else - return ((a & ~0x8000) >= 0x7c80); -#endif -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float16_is_signaling_nan(float16 a_) { - uint16_t a = float16_val(a_); -#if SNAN_BIT_IS_ONE - return ((a & ~0x8000) >= 0x7c80); -#else - return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF); -#endif -} - -/*---------------------------------------------------------------------------- -| Returns a quiet NaN if the half-precision floating point value `a' is a -| signaling NaN; otherwise returns `a'. -*----------------------------------------------------------------------------*/ -float16 float16_maybe_silence_nan(float16 a_) { - if (float16_is_signaling_nan(a_)) { -#if SNAN_BIT_IS_ONE -#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32) - return float16_default_nan; -#else -#error Rules for silencing a signaling NaN are target-specific -#endif -#else - uint16_t a = float16_val(a_); - a |= (1 << 9); - return make_float16(a); -#endif - } - return a_; -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static commonNaNT float16ToCommonNaN(float16 a STATUS_PARAM) { - commonNaNT z; - - if (float16_is_signaling_nan(a)) - float_raise(float_flag_invalid STATUS_VAR); - z.sign = float16_val(a) >> 15; - z.low = 0; - z.high = ((uint64_t) float16_val(a)) << 54; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the half- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float16 commonNaNToFloat16(commonNaNT a STATUS_PARAM) { - uint16_t mantissa = a.high >> 54; - - if (STATUS(default_nan_mode)) { - return float16_default_nan; - } - - if (mantissa) { - return make_float16(((((uint16_t) a.sign) << 15) | (0x1F << 10) | mantissa)); - } else { - return float16_default_nan; - } -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a quiet -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float32_is_quiet_nan(float32 a_) { - uint32_t a = float32_val(a_); -#if SNAN_BIT_IS_ONE - return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); -#else - return (0xFF800000 <= (uint32_t)(a << 1)); -#endif -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float32_is_signaling_nan(float32 a_) { - uint32_t a = float32_val(a_); -#if SNAN_BIT_IS_ONE - return (0xFF800000 <= (uint32_t)(a << 1)); -#else - return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); -#endif -} - -/*---------------------------------------------------------------------------- -| Returns a quiet NaN if the single-precision floating point value `a' is a -| signaling NaN; otherwise returns `a'. -*----------------------------------------------------------------------------*/ - -float32 float32_maybe_silence_nan(float32 a_) { - if (float32_is_signaling_nan(a_)) { -#if SNAN_BIT_IS_ONE -#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32) - return float32_default_nan; -#else -#error Rules for silencing a signaling NaN are target-specific -#endif -#else - uint32_t a = float32_val(a_); - a |= (1 << 22); - return make_float32(a); -#endif - } - return a_; -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static commonNaNT float32ToCommonNaN(float32 a STATUS_PARAM) { - commonNaNT z; - - if (float32_is_signaling_nan(a)) - float_raise(float_flag_invalid STATUS_VAR); - z.sign = float32_val(a) >> 31; - z.low = 0; - z.high = ((uint64_t) float32_val(a)) << 41; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float32 commonNaNToFloat32(commonNaNT a STATUS_PARAM) { - uint32_t mantissa = a.high >> 41; - - if (STATUS(default_nan_mode)) { - return float32_default_nan; - } - - if (mantissa) - return make_float32((((uint32_t) a.sign) << 31) | 0x7F800000 | (a.high >> 41)); - else - return float32_default_nan; -} - -/*---------------------------------------------------------------------------- -| Select which NaN to propagate for a two-input operation. -| IEEE754 doesn't specify all the details of this, so the -| algorithm is target-specific. -| The routine is passed various bits of information about the -| two NaNs and should return 0 to select NaN a and 1 for NaN b. -| Note that signalling NaNs are always squashed to quiet NaNs -| by the caller, by calling floatXX_maybe_silence_nan() before -| returning them. -| -| aIsLargerSignificand is only valid if both a and b are NaNs -| of some kind, and is true if a has the larger significand, -| or if both a and b have the same significand but a is -| positive but b is negative. It is only needed for the x87 -| tie-break rule. -*----------------------------------------------------------------------------*/ - -#if defined(TARGET_ARM) -static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, flag aIsLargerSignificand) { - /* ARM mandated NaN propagation rules: take the first of: - * 1. A if it is signaling - * 2. B if it is signaling - * 3. A (quiet) - * 4. B (quiet) - * A signaling NaN is always quietened before returning it. - */ - if (aIsSNaN) { - return 0; - } else if (bIsSNaN) { - return 1; - } else if (aIsQNaN) { - return 0; - } else { - return 1; - } -} -#elif defined(TARGET_MIPS) -static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, flag aIsLargerSignificand) { - /* According to MIPS specifications, if one of the two operands is - * a sNaN, a new qNaN has to be generated. This is done in - * floatXX_maybe_silence_nan(). For qNaN inputs the specifications - * says: "When possible, this QNaN result is one of the operand QNaN - * values." In practice it seems that most implementations choose - * the first operand if both operands are qNaN. In short this gives - * the following rules: - * 1. A if it is signaling - * 2. B if it is signaling - * 3. A (quiet) - * 4. B (quiet) - * A signaling NaN is always silenced before returning it. - */ - if (aIsSNaN) { - return 0; - } else if (bIsSNaN) { - return 1; - } else if (aIsQNaN) { - return 0; - } else { - return 1; - } -} -#elif defined(TARGET_PPC) -static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, flag aIsLargerSignificand) { - /* PowerPC propagation rules: - * 1. A if it sNaN or qNaN - * 2. B if it sNaN or qNaN - * A signaling NaN is always silenced before returning it. - */ - if (aIsSNaN || aIsQNaN) { - return 0; - } else { - return 1; - } -} -#else -static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, flag aIsLargerSignificand) { - /* This implements x87 NaN propagation rules: - * SNaN + QNaN => return the QNaN - * two SNaNs => return the one with the larger significand, silenced - * two QNaNs => return the one with the larger significand - * SNaN and a non-NaN => return the SNaN, silenced - * QNaN and a non-NaN => return the QNaN - * - * If we get down to comparing significands and they are the same, - * return the NaN with the positive sign bit (if any). - */ - if (aIsSNaN) { - if (bIsSNaN) { - return aIsLargerSignificand ? 0 : 1; - } - return bIsQNaN ? 1 : 0; - } else if (aIsQNaN) { - if (bIsSNaN || !bIsQNaN) - return 0; - else { - return aIsLargerSignificand ? 0 : 1; - } - } else { - return 1; - } -} -#endif - -/*---------------------------------------------------------------------------- -| Select which NaN to propagate for a three-input operation. -| For the moment we assume that no CPU needs the 'larger significand' -| information. -| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN -*----------------------------------------------------------------------------*/ -#if defined(TARGET_ARM) -static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, flag cIsQNaN, flag cIsSNaN, - flag infzero STATUS_PARAM) { - /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns - * the default NaN - */ - if (infzero && cIsQNaN) { - float_raise(float_flag_invalid STATUS_VAR); - return 3; - } - - /* This looks different from the ARM ARM pseudocode, because the ARM ARM - * puts the operands to a fused mac operation (a*b)+c in the order c,a,b. - */ - if (cIsSNaN) { - return 2; - } else if (aIsSNaN) { - return 0; - } else if (bIsSNaN) { - return 1; - } else if (cIsQNaN) { - return 2; - } else if (aIsQNaN) { - return 0; - } else { - return 1; - } -} -#elif defined(TARGET_PPC) -static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, flag cIsQNaN, flag cIsSNaN, - flag infzero STATUS_PARAM) { - /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer - * to return an input NaN if we have one (ie c) rather than generating - * a default NaN - */ - if (infzero) { - float_raise(float_flag_invalid STATUS_VAR); - return 2; - } - - /* If fRA is a NaN return it; otherwise if fRB is a NaN return it; - * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB - */ - if (aIsSNaN || aIsQNaN) { - return 0; - } else if (cIsSNaN || cIsQNaN) { - return 2; - } else { - return 1; - } -} -#else -/* A default implementation: prefer a to b to c. - * This is unlikely to actually match any real implementation. - */ -static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, flag cIsQNaN, flag cIsSNaN, - flag infzero STATUS_PARAM) { - if (aIsSNaN || aIsQNaN) { - return 0; - } else if (bIsSNaN || bIsQNaN) { - return 1; - } else { - return 2; - } -} -#endif - -/*---------------------------------------------------------------------------- -| Takes two single-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. -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32NaN(float32 a, float32 b STATUS_PARAM) { - flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN; - flag aIsLargerSignificand; - uint32_t av, bv; - - aIsQuietNaN = float32_is_quiet_nan(a); - aIsSignalingNaN = float32_is_signaling_nan(a); - bIsQuietNaN = float32_is_quiet_nan(b); - bIsSignalingNaN = float32_is_signaling_nan(b); - av = float32_val(a); - bv = float32_val(b); - - if (aIsSignalingNaN | bIsSignalingNaN) - float_raise(float_flag_invalid STATUS_VAR); - - if (STATUS(default_nan_mode)) - return float32_default_nan; - - if ((uint32_t)(av << 1) < (uint32_t)(bv << 1)) { - aIsLargerSignificand = 0; - } else if ((uint32_t)(bv << 1) < (uint32_t)(av << 1)) { - aIsLargerSignificand = 1; - } else { - aIsLargerSignificand = (av < bv) ? 1 : 0; - } - - if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN, aIsLargerSignificand)) { - return float32_maybe_silence_nan(b); - } else { - return float32_maybe_silence_nan(a); - } -} - -/*---------------------------------------------------------------------------- -| Takes three single-precision floating-point values `a', `b' and `c', one of -| which is a NaN, and returns the appropriate NaN result. If any of `a', -| `b' or `c' is a signaling NaN, the invalid exception is raised. -| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case -| obviously c is a NaN, and whether to propagate c or some other NaN is -| implementation defined). -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32MulAddNaN(float32 a, float32 b, float32 c, flag infzero STATUS_PARAM) { - flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN, cIsQuietNaN, cIsSignalingNaN; - int which; - - aIsQuietNaN = float32_is_quiet_nan(a); - aIsSignalingNaN = float32_is_signaling_nan(a); - bIsQuietNaN = float32_is_quiet_nan(b); - bIsSignalingNaN = float32_is_signaling_nan(b); - cIsQuietNaN = float32_is_quiet_nan(c); - cIsSignalingNaN = float32_is_signaling_nan(c); - - if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) { - float_raise(float_flag_invalid STATUS_VAR); - } - - which = pickNaNMulAdd(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN, cIsQuietNaN, cIsSignalingNaN, - infzero STATUS_VAR); - - if (STATUS(default_nan_mode)) { - /* Note that this check is after pickNaNMulAdd so that function - * has an opportunity to set the Invalid flag. - */ - return float32_default_nan; - } - - switch (which) { - case 0: - return float32_maybe_silence_nan(a); - case 1: - return float32_maybe_silence_nan(b); - case 2: - return float32_maybe_silence_nan(c); - case 3: - default: - return float32_default_nan; - } -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a quiet -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float64_is_quiet_nan(float64 a_) { - uint64_t a = float64_val(a_); -#if SNAN_BIT_IS_ONE - return (((a >> 51) & 0xFFF) == 0xFFE) && (a & LIT64(0x0007FFFFFFFFFFFF)); -#else - return (LIT64(0xFFF0000000000000) <= (uint64_t)(a << 1)); -#endif -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float64_is_signaling_nan(float64 a_) { - uint64_t a = float64_val(a_); -#if SNAN_BIT_IS_ONE - return (LIT64(0xFFF0000000000000) <= (uint64_t)(a << 1)); -#else - return (((a >> 51) & 0xFFF) == 0xFFE) && (a & LIT64(0x0007FFFFFFFFFFFF)); -#endif -} - -/*---------------------------------------------------------------------------- -| Returns a quiet NaN if the double-precision floating point value `a' is a -| signaling NaN; otherwise returns `a'. -*----------------------------------------------------------------------------*/ - -float64 float64_maybe_silence_nan(float64 a_) { - if (float64_is_signaling_nan(a_)) { -#if SNAN_BIT_IS_ONE -#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32) - return float64_default_nan; -#else -#error Rules for silencing a signaling NaN are target-specific -#endif -#else - uint64_t a = float64_val(a_); - a |= LIT64(0x0008000000000000); - return make_float64(a); -#endif - } - return a_; -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static commonNaNT float64ToCommonNaN(float64 a STATUS_PARAM) { - commonNaNT z; - - if (float64_is_signaling_nan(a)) - float_raise(float_flag_invalid STATUS_VAR); - z.sign = float64_val(a) >> 63; - z.low = 0; - z.high = float64_val(a) << 12; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float64 commonNaNToFloat64(commonNaNT a STATUS_PARAM) { - uint64_t mantissa = a.high >> 12; - - if (STATUS(default_nan_mode)) { - return float64_default_nan; - } - - if (mantissa) - return make_float64((((uint64_t) a.sign) << 63) | LIT64(0x7FF0000000000000) | (a.high >> 12)); - else - return float64_default_nan; -} - -/*---------------------------------------------------------------------------- -| Takes two 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. -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64NaN(float64 a, float64 b STATUS_PARAM) { - flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN; - flag aIsLargerSignificand; - uint64_t av, bv; - - aIsQuietNaN = float64_is_quiet_nan(a); - aIsSignalingNaN = float64_is_signaling_nan(a); - bIsQuietNaN = float64_is_quiet_nan(b); - bIsSignalingNaN = float64_is_signaling_nan(b); - av = float64_val(a); - bv = float64_val(b); - - if (aIsSignalingNaN | bIsSignalingNaN) - float_raise(float_flag_invalid STATUS_VAR); - - if (STATUS(default_nan_mode)) - return float64_default_nan; - - if ((uint64_t)(av << 1) < (uint64_t)(bv << 1)) { - aIsLargerSignificand = 0; - } else if ((uint64_t)(bv << 1) < (uint64_t)(av << 1)) { - aIsLargerSignificand = 1; - } else { - aIsLargerSignificand = (av < bv) ? 1 : 0; - } - - if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN, aIsLargerSignificand)) { - return float64_maybe_silence_nan(b); - } else { - return float64_maybe_silence_nan(a); - } -} - -/*---------------------------------------------------------------------------- -| Takes three double-precision floating-point values `a', `b' and `c', one of -| which is a NaN, and returns the appropriate NaN result. If any of `a', -| `b' or `c' is a signaling NaN, the invalid exception is raised. -| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case -| obviously c is a NaN, and whether to propagate c or some other NaN is -| implementation defined). -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64MulAddNaN(float64 a, float64 b, float64 c, flag infzero STATUS_PARAM) { - flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN, cIsQuietNaN, cIsSignalingNaN; - int which; - - aIsQuietNaN = float64_is_quiet_nan(a); - aIsSignalingNaN = float64_is_signaling_nan(a); - bIsQuietNaN = float64_is_quiet_nan(b); - bIsSignalingNaN = float64_is_signaling_nan(b); - cIsQuietNaN = float64_is_quiet_nan(c); - cIsSignalingNaN = float64_is_signaling_nan(c); - - if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) { - float_raise(float_flag_invalid STATUS_VAR); - } - - which = pickNaNMulAdd(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN, cIsQuietNaN, cIsSignalingNaN, - infzero STATUS_VAR); - - if (STATUS(default_nan_mode)) { - /* Note that this check is after pickNaNMulAdd so that function - * has an opportunity to set the Invalid flag. - */ - return float64_default_nan; - } - - switch (which) { - case 0: - return float64_maybe_silence_nan(a); - case 1: - return float64_maybe_silence_nan(b); - case 2: - return float64_maybe_silence_nan(c); - case 3: - default: - return float64_default_nan; - } -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| quiet NaN; otherwise returns 0. This slightly differs from the same -| function for other types as floatx80 has an explicit bit. -*----------------------------------------------------------------------------*/ - -int floatx80_is_quiet_nan(floatx80 a) { -#if SNAN_BIT_IS_ONE - uint64_t aLow; - - aLow = a.low & ~LIT64(0x4000000000000000); - return ((a.high & 0x7FFF) == 0x7FFF) && (uint64_t)(aLow << 1) && (a.low == aLow); -#else - return ((a.high & 0x7FFF) == 0x7FFF) && (LIT64(0x8000000000000000) <= ((uint64_t)(a.low << 1))); -#endif -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. This slightly differs from the same -| function for other types as floatx80 has an explicit bit. -*----------------------------------------------------------------------------*/ - -int floatx80_is_signaling_nan(floatx80 a) { -#if SNAN_BIT_IS_ONE - return ((a.high & 0x7FFF) == 0x7FFF) && (LIT64(0x8000000000000000) <= ((uint64_t)(a.low << 1))); -#else - uint64_t aLow; - - aLow = a.low & ~LIT64(0x4000000000000000); - return ((a.high & 0x7FFF) == 0x7FFF) && (uint64_t)(aLow << 1) && (a.low == aLow); -#endif -} - -/*---------------------------------------------------------------------------- -| Returns a quiet NaN if the extended double-precision floating point value -| `a' is a signaling NaN; otherwise returns `a'. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_maybe_silence_nan(floatx80 a) { - if (floatx80_is_signaling_nan(a)) { -#if SNAN_BIT_IS_ONE -#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32) - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; -#else -#error Rules for silencing a signaling NaN are target-specific -#endif -#else - a.low |= LIT64(0xC000000000000000); - return a; -#endif - } - return a; -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static commonNaNT floatx80ToCommonNaN(floatx80 a STATUS_PARAM) { - commonNaNT z; - - if (floatx80_is_signaling_nan(a)) - float_raise(float_flag_invalid STATUS_VAR); - if (a.low >> 63) { - z.sign = a.high >> 15; - z.low = 0; - z.high = a.low << 1; - } else { - z.sign = floatx80_default_nan_high >> 15; - z.low = 0; - z.high = floatx80_default_nan_low << 1; - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -static floatx80 commonNaNToFloatx80(commonNaNT a STATUS_PARAM) { - floatx80 z; - - if (STATUS(default_nan_mode)) { - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - - if (a.high >> 1) { - z.low = LIT64(0x8000000000000000) | a.high >> 1; - z.high = (((uint16_t) a.sign) << 15) | 0x7FFF; - } else { - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - } - - 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. -*----------------------------------------------------------------------------*/ - -static floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b STATUS_PARAM) { - flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN; - flag aIsLargerSignificand; - - aIsQuietNaN = floatx80_is_quiet_nan(a); - aIsSignalingNaN = floatx80_is_signaling_nan(a); - bIsQuietNaN = floatx80_is_quiet_nan(b); - bIsSignalingNaN = floatx80_is_signaling_nan(b); - - if (aIsSignalingNaN | bIsSignalingNaN) - float_raise(float_flag_invalid STATUS_VAR); - - if (STATUS(default_nan_mode)) { - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - - if (a.low < b.low) { - aIsLargerSignificand = 0; - } else if (b.low < a.low) { - aIsLargerSignificand = 1; - } else { - aIsLargerSignificand = (a.high < b.high) ? 1 : 0; - } - - if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN, aIsLargerSignificand)) { - return floatx80_maybe_silence_nan(b); - } else { - return floatx80_maybe_silence_nan(a); - } -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a quiet -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float128_is_quiet_nan(float128 a) { -#if SNAN_BIT_IS_ONE - return (((a.high >> 47) & 0xFFFF) == 0xFFFE) && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF))); -#else - return (LIT64(0xFFFE000000000000) <= (uint64_t)(a.high << 1)) && (a.low || (a.high & LIT64(0x0000FFFFFFFFFFFF))); -#endif -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float128_is_signaling_nan(float128 a) { -#if SNAN_BIT_IS_ONE - return (LIT64(0xFFFE000000000000) <= (uint64_t)(a.high << 1)) && (a.low || (a.high & LIT64(0x0000FFFFFFFFFFFF))); -#else - return (((a.high >> 47) & 0xFFFF) == 0xFFFE) && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF))); -#endif -} - -/*---------------------------------------------------------------------------- -| Returns a quiet NaN if the quadruple-precision floating point value `a' is -| a signaling NaN; otherwise returns `a'. -*----------------------------------------------------------------------------*/ - -float128 float128_maybe_silence_nan(float128 a) { - if (float128_is_signaling_nan(a)) { -#if SNAN_BIT_IS_ONE -#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32) - a.low = float128_default_nan_low; - a.high = float128_default_nan_high; -#else -#error Rules for silencing a signaling NaN are target-specific -#endif -#else - a.high |= LIT64(0x0000800000000000); - return a; -#endif - } - return a; -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static commonNaNT float128ToCommonNaN(float128 a STATUS_PARAM) { - commonNaNT z; - - if (float128_is_signaling_nan(a)) - float_raise(float_flag_invalid STATUS_VAR); - z.sign = a.high >> 63; - shortShift128Left(a.high, a.low, 16, &z.high, &z.low); - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float128 commonNaNToFloat128(commonNaNT a STATUS_PARAM) { - float128 z; - - if (STATUS(default_nan_mode)) { - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - - shift128Right(a.high, a.low, 16, &z.high, &z.low); - z.high |= (((uint64_t) a.sign) << 63) | LIT64(0x7FFF000000000000); - 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. -*----------------------------------------------------------------------------*/ - -static float128 propagateFloat128NaN(float128 a, float128 b STATUS_PARAM) { - flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN; - flag aIsLargerSignificand; - - aIsQuietNaN = float128_is_quiet_nan(a); - aIsSignalingNaN = float128_is_signaling_nan(a); - bIsQuietNaN = float128_is_quiet_nan(b); - bIsSignalingNaN = float128_is_signaling_nan(b); - - if (aIsSignalingNaN | bIsSignalingNaN) - float_raise(float_flag_invalid STATUS_VAR); - - if (STATUS(default_nan_mode)) { - a.low = float128_default_nan_low; - a.high = float128_default_nan_high; - return a; - } - - if (lt128(a.high << 1, a.low, b.high << 1, b.low)) { - aIsLargerSignificand = 0; - } else if (lt128(b.high << 1, b.low, a.high << 1, a.low)) { - aIsLargerSignificand = 1; - } else { - aIsLargerSignificand = (a.high < b.high) ? 1 : 0; - } - - if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN, aIsLargerSignificand)) { - return float128_maybe_silence_nan(b); - } else { - return float128_maybe_silence_nan(a); - } -} diff --git a/src/base/emu-i386/simx86/softfloat/softfloat.c b/src/base/emu-i386/simx86/softfloat/softfloat.c deleted file mode 100644 index ed50bc9..0000000 --- a/src/base/emu-i386/simx86/softfloat/softfloat.c +++ /dev/null @@ -1,6384 +0,0 @@ -/* - * QEMU float support - * - * Derived from SoftFloat. - */ - -/*============================================================================ - -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. - -=============================================================================*/ - -/* softfloat (and in particular the code in softfloat-specialize.h) is - * target-dependent and needs the TARGET_* macros. - */ -//#include - -#include "softfloat.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" - -void set_float_rounding_mode(int val STATUS_PARAM) { - STATUS_W(float_rounding_mode, val); -} - -void set_float_exception_flags(int val STATUS_PARAM) { - STATUS_W(float_exception_flags, val); -} - -void set_floatx80_rounding_precision(int val STATUS_PARAM) { - STATUS_W(floatx80_rounding_precision, val); -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE uint32_t extractFloat16Frac(float16 a) { - return float16_val(a) & 0x3ff; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE int16 extractFloat16Exp(float16 a) { - return (float16_val(a) >> 10) & 0x1f; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE flag extractFloat16Sign(float16 a) { - return float16_val(a) >> 15; -} - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| positive or negative integer is returned. -*----------------------------------------------------------------------------*/ - -static int32 roundAndPackInt32(flag zSign, uint64_t absZ STATUS_PARAM) { - int8 roundingMode; - flag roundNearestEven; - int8 roundIncrement, roundBits; - int32_t z; - - roundingMode = STATUS(float_rounding_mode); - roundNearestEven = (roundingMode == float_round_nearest_even); - roundIncrement = 0x40; - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - roundIncrement = 0; - } else { - roundIncrement = 0x7F; - if (zSign) { - if (roundingMode == float_round_up) - roundIncrement = 0; - } else { - if (roundingMode == float_round_down) - roundIncrement = 0; - } - } - } - roundBits = absZ & 0x7F; - absZ = (absZ + roundIncrement) >> 7; - absZ &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); - z = absZ; - if (zSign) - z = -z; - if ((absZ >> 32) || (z && ((z < 0) ^ zSign))) { - float_raise(float_flag_invalid STATUS_VAR); - return zSign ? (int32_t) 0x80000000 : 0x7FFFFFFF; - } - if (roundBits) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return z; -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest positive or negative integer is -| returned. -*----------------------------------------------------------------------------*/ - -static int64 roundAndPackInt64(flag zSign, uint64_t absZ0, uint64_t absZ1 STATUS_PARAM) { - int8 roundingMode; - flag roundNearestEven, increment; - int64_t z; - - roundingMode = STATUS(float_rounding_mode); - roundNearestEven = (roundingMode == float_round_nearest_even); - increment = ((int64_t) absZ1 < 0); - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - increment = 0; - } else { - if (zSign) { - increment = (roundingMode == float_round_down) && absZ1; - } else { - increment = (roundingMode == float_round_up) && absZ1; - } - } - } - if (increment) { - ++absZ0; - if (absZ0 == 0) - goto overflow; - absZ0 &= ~(((uint64_t)(absZ1 << 1) == 0) & roundNearestEven); - } - z = absZ0; - if (zSign) - z = -z; - if (z && ((z < 0) ^ zSign)) { - overflow: - float_raise(float_flag_invalid STATUS_VAR); - return zSign ? (int64_t) LIT64(0x8000000000000000) : LIT64(0x7FFFFFFFFFFFFFFF); - } - if (absZ1) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE uint32_t extractFloat32Frac(float32 a) { - - return float32_val(a) & 0x007FFFFF; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE int16 extractFloat32Exp(float32 a) { - - return (float32_val(a) >> 23) & 0xFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE flag extractFloat32Sign(float32 a) { - - return float32_val(a) >> 31; -} - -/*---------------------------------------------------------------------------- -| If `a' is denormal and we are in flush-to-zero mode then set the -| input-denormal exception and return zero. Otherwise just return the value. -*----------------------------------------------------------------------------*/ -static float32 float32_squash_input_denormal(float32 a STATUS_PARAM) { - if (STATUS(flush_inputs_to_zero)) { - if (extractFloat32Exp(a) == 0 && extractFloat32Frac(a) != 0) { - float_raise(float_flag_input_denormal STATUS_VAR); - return make_float32(float32_val(a) & 0x80000000); - } - } - return a; -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-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. -*----------------------------------------------------------------------------*/ - -static void normalizeFloat32Subnormal(uint32_t aSig, int16 *zExpPtr, uint32_t *zSigPtr) { - int8 shiftCount; - - shiftCount = countLeadingZeros32(aSig) - 8; - *zSigPtr = aSig << shiftCount; - *zExpPtr = 1 - shiftCount; -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| single-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -SINLINE float32 packFloat32(flag zSign, int16 zExp, uint32_t zSig) { - - return make_float32((((uint32_t) zSign) << 31) + (((uint32_t) zExp) << 23) + zSig); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the single-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 single- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 30 -| and 29, which is 7 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' 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 `zSig' 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. -*----------------------------------------------------------------------------*/ - -static float32 roundAndPackFloat32(flag zSign, int16 zExp, uint32_t zSig STATUS_PARAM) { - int8 roundingMode; - flag roundNearestEven; - int8 roundIncrement, roundBits; - flag isTiny; - - roundingMode = STATUS(float_rounding_mode); - roundNearestEven = (roundingMode == float_round_nearest_even); - roundIncrement = 0x40; - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - roundIncrement = 0; - } else { - roundIncrement = 0x7F; - if (zSign) { - if (roundingMode == float_round_up) - roundIncrement = 0; - } else { - if (roundingMode == float_round_down) - roundIncrement = 0; - } - } - } - roundBits = zSig & 0x7F; - if (0xFD <= (uint16_t) zExp) { - if ((0xFD < zExp) || ((zExp == 0xFD) && ((int32_t)(zSig + roundIncrement) < 0))) { - float_raise(float_flag_overflow | float_flag_inexact STATUS_VAR); - return packFloat32(zSign, 0xFF, -(roundIncrement == 0)); - } - if (zExp < 0) { - if (STATUS(flush_to_zero)) { - float_raise(float_flag_output_denormal STATUS_VAR); - return packFloat32(zSign, 0, 0); - } - isTiny = (STATUS(float_detect_tininess) == float_tininess_before_rounding) || (zExp < -1) || - (zSig + roundIncrement < 0x80000000); - shift32RightJamming(zSig, -zExp, &zSig); - zExp = 0; - roundBits = zSig & 0x7F; - if (isTiny && roundBits) - float_raise(float_flag_underflow STATUS_VAR); - } - } - if (roundBits) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - zSig = (zSig + roundIncrement) >> 7; - zSig &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); - if (zSig == 0) - zExp = 0; - return packFloat32(zSign, zExp, zSig); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float32 normalizeRoundAndPackFloat32(flag zSign, int16 zExp, uint32_t zSig STATUS_PARAM) { - int8 shiftCount; - - shiftCount = countLeadingZeros32(zSig) - 1; - return roundAndPackFloat32(zSign, zExp - shiftCount, zSig << shiftCount STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE uint64_t extractFloat64Frac(float64 a) { - - return float64_val(a) & LIT64(0x000FFFFFFFFFFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE int16 extractFloat64Exp(float64 a) { - - return (float64_val(a) >> 52) & 0x7FF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE flag extractFloat64Sign(float64 a) { - - return float64_val(a) >> 63; -} - -/*---------------------------------------------------------------------------- -| If `a' is denormal and we are in flush-to-zero mode then set the -| input-denormal exception and return zero. Otherwise just return the value. -*----------------------------------------------------------------------------*/ -static float64 float64_squash_input_denormal(float64 a STATUS_PARAM) { - if (STATUS(flush_inputs_to_zero)) { - if (extractFloat64Exp(a) == 0 && extractFloat64Frac(a) != 0) { - float_raise(float_flag_input_denormal STATUS_VAR); - return make_float64(float64_val(a) & (1ULL << 63)); - } - } - return a; -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal 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. -*----------------------------------------------------------------------------*/ - -static void normalizeFloat64Subnormal(uint64_t aSig, int16 *zExpPtr, uint64_t *zSigPtr) { - int8 shiftCount; - - shiftCount = countLeadingZeros64(aSig) - 11; - *zSigPtr = aSig << shiftCount; - *zExpPtr = 1 - shiftCount; -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| double-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -SINLINE float64 packFloat64(flag zSign, int16 zExp, uint64_t zSig) { - - return make_float64((((uint64_t) zSign) << 63) + (((uint64_t) zExp) << 52) + zSig); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the 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 double- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 62 -| and 61, which is 10 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' 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 `zSig' 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. -*----------------------------------------------------------------------------*/ - -static float64 roundAndPackFloat64(flag zSign, int16 zExp, uint64_t zSig STATUS_PARAM) { - int8 roundingMode; - flag roundNearestEven; - int16 roundIncrement, roundBits; - flag isTiny; - - roundingMode = STATUS(float_rounding_mode); - roundNearestEven = (roundingMode == float_round_nearest_even); - roundIncrement = 0x200; - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - roundIncrement = 0; - } else { - roundIncrement = 0x3FF; - if (zSign) { - if (roundingMode == float_round_up) - roundIncrement = 0; - } else { - if (roundingMode == float_round_down) - roundIncrement = 0; - } - } - } - roundBits = zSig & 0x3FF; - if (0x7FD <= (uint16_t) zExp) { - if ((0x7FD < zExp) || ((zExp == 0x7FD) && ((int64_t)(zSig + roundIncrement) < 0))) { - float_raise(float_flag_overflow | float_flag_inexact STATUS_VAR); - return packFloat64(zSign, 0x7FF, -(roundIncrement == 0)); - } - if (zExp < 0) { - if (STATUS(flush_to_zero)) { - float_raise(float_flag_output_denormal STATUS_VAR); - return packFloat64(zSign, 0, 0); - } - isTiny = (STATUS(float_detect_tininess) == float_tininess_before_rounding) || (zExp < -1) || - (zSig + roundIncrement < LIT64(0x8000000000000000)); - shift64RightJamming(zSig, -zExp, &zSig); - zExp = 0; - roundBits = zSig & 0x3FF; - if (isTiny && roundBits) - float_raise(float_flag_underflow STATUS_VAR); - } - } - if (roundBits) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - zSig = (zSig + roundIncrement) >> 10; - zSig &= ~(((roundBits ^ 0x200) == 0) & roundNearestEven); - if (zSig == 0) - zExp = 0; - return packFloat64(zSign, zExp, zSig); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float64 normalizeRoundAndPackFloat64(flag zSign, int16 zExp, uint64_t zSig STATUS_PARAM) { - int8 shiftCount; - - shiftCount = countLeadingZeros64(zSig) - 1; - return roundAndPackFloat64(zSign, zExp - shiftCount, zSig << shiftCount STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE uint64_t extractFloatx80Frac(floatx80 a) { - - return a.low; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE int32 extractFloatx80Exp(floatx80 a) { - - return a.high & 0x7FFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -SINLINE flag extractFloatx80Sign(floatx80 a) { - - return a.high >> 15; -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static void normalizeFloatx80Subnormal(uint64_t aSig, int32 *zExpPtr, uint64_t *zSigPtr) { - int8 shiftCount; - - shiftCount = countLeadingZeros64(aSig); - *zSigPtr = aSig << shiftCount; - *zExpPtr = 1 - shiftCount; -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an -| extended double-precision floating-point value, returning the result. -*----------------------------------------------------------------------------*/ - -SINLINE floatx80 packFloatx80(flag zSign, int32 zExp, uint64_t zSig) { - floatx80 z; - - z.low = zSig; - z.high = (((uint16_t) zSign) << 15) + zExp; - return z; -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign, int32 zExp, uint64_t zSig0, - uint64_t zSig1 STATUS_PARAM) { - int8 roundingMode; - flag roundNearestEven, increment, isTiny; - int64 roundIncrement, roundMask, roundBits; - - roundingMode = STATUS(float_rounding_mode); - roundNearestEven = (roundingMode == float_round_nearest_even); - if (roundingPrecision == 80) - goto precision80; - if (roundingPrecision == 64) { - roundIncrement = LIT64(0x0000000000000400); - roundMask = LIT64(0x00000000000007FF); - } else if (roundingPrecision == 32) { - roundIncrement = LIT64(0x0000008000000000); - roundMask = LIT64(0x000000FFFFFFFFFF); - } else { - goto precision80; - } - zSig0 |= (zSig1 != 0); - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - roundIncrement = 0; - } else { - roundIncrement = roundMask; - if (zSign) { - if (roundingMode == float_round_up) - roundIncrement = 0; - } else { - if (roundingMode == float_round_down) - roundIncrement = 0; - } - } - } - roundBits = zSig0 & roundMask; - if (0x7FFD <= (uint32_t)(zExp - 1)) { - if ((0x7FFE < zExp) || ((zExp == 0x7FFE) && (zSig0 + roundIncrement < zSig0))) { - goto overflow; - } - if (zExp <= 0) { - if (STATUS(flush_to_zero)) { - float_raise(float_flag_output_denormal STATUS_VAR); - return packFloatx80(zSign, 0, 0); - } - isTiny = (STATUS(float_detect_tininess) == float_tininess_before_rounding) || (zExp < 0) || - (zSig0 <= zSig0 + roundIncrement); - shift64RightJamming(zSig0, 1 - zExp, &zSig0); - zExp = 0; - roundBits = zSig0 & roundMask; - if (isTiny && roundBits) - float_raise(float_flag_underflow STATUS_VAR); - if (roundBits) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - zSig0 += roundIncrement; - if ((int64_t) zSig0 < 0) - zExp = 1; - roundIncrement = roundMask + 1; - if (roundNearestEven && (roundBits << 1 == roundIncrement)) { - roundMask |= roundIncrement; - } - zSig0 &= ~roundMask; - return packFloatx80(zSign, zExp, zSig0); - } - } - if (roundBits) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - zSig0 += roundIncrement; - if (zSig0 < roundIncrement) { - ++zExp; - zSig0 = LIT64(0x8000000000000000); - } - roundIncrement = roundMask + 1; - if (roundNearestEven && (roundBits << 1 == roundIncrement)) { - roundMask |= roundIncrement; - } - zSig0 &= ~roundMask; - if (zSig0 == 0) - zExp = 0; - return packFloatx80(zSign, zExp, zSig0); -precision80: - increment = ((int64_t) 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 <= (uint32_t)(zExp - 1)) { - if ((0x7FFE < zExp) || ((zExp == 0x7FFE) && (zSig0 == LIT64(0xFFFFFFFFFFFFFFFF)) && increment)) { - roundMask = 0; - overflow: - float_raise(float_flag_overflow | float_flag_inexact STATUS_VAR); - if ((roundingMode == float_round_to_zero) || (zSign && (roundingMode == float_round_up)) || - (!zSign && (roundingMode == float_round_down))) { - return packFloatx80(zSign, 0x7FFE, ~roundMask); - } - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (zExp <= 0) { - isTiny = (STATUS(float_detect_tininess) == float_tininess_before_rounding) || (zExp < 0) || !increment || - (zSig0 < LIT64(0xFFFFFFFFFFFFFFFF)); - shift64ExtraRightJamming(zSig0, zSig1, 1 - zExp, &zSig0, &zSig1); - zExp = 0; - if (isTiny && zSig1) - float_raise(float_flag_underflow STATUS_VAR); - if (zSig1) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - if (roundNearestEven) { - increment = ((int64_t) zSig1 < 0); - } else { - if (zSign) { - increment = (roundingMode == float_round_down) && zSig1; - } else { - increment = (roundingMode == float_round_up) && zSig1; - } - } - if (increment) { - ++zSig0; - zSig0 &= ~(((uint64_t)(zSig1 << 1) == 0) & roundNearestEven); - if ((int64_t) zSig0 < 0) - zExp = 1; - } - return packFloatx80(zSign, zExp, zSig0); - } - } - if (zSig1) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - if (increment) { - ++zSig0; - if (zSig0 == 0) { - ++zExp; - zSig0 = LIT64(0x8000000000000000); - } else { - zSig0 &= ~(((uint64_t)(zSig1 << 1) == 0) & roundNearestEven); - } - } else { - if (zSig0 == 0) - zExp = 0; - } - return packFloatx80(zSign, zExp, zSig0); -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static floatx80 normalizeRoundAndPackFloatx80(int8 roundingPrecision, flag zSign, int32 zExp, uint64_t zSig0, - uint64_t zSig1 STATUS_PARAM) { - int8 shiftCount; - - if (zSig0 == 0) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - shiftCount = countLeadingZeros64(zSig0); - shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); - zExp -= shiftCount; - return roundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the least-significant 64 fraction bits of the quadruple-precision -| floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE uint64_t extractFloat128Frac1(float128 a) { - - return a.low; -} - -/*---------------------------------------------------------------------------- -| Returns the most-significant 48 fraction bits of the quadruple-precision -| floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE uint64_t extractFloat128Frac0(float128 a) { - - return a.high & LIT64(0x0000FFFFFFFFFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the quadruple-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -SINLINE int32 extractFloat128Exp(float128 a) { - - return (a.high >> 48) & 0x7FFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -SINLINE flag extractFloat128Sign(float128 a) { - - return a.high >> 63; -} - -/*---------------------------------------------------------------------------- -| 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'. -*----------------------------------------------------------------------------*/ - -static void normalizeFloat128Subnormal(uint64_t aSig0, uint64_t aSig1, int32 *zExpPtr, uint64_t *zSig0Ptr, - uint64_t *zSig1Ptr) { - int8 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; - } -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', the exponent `zExp', and the significand formed -| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision -| floating-point value, returning the result. After being shifted into the -| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply -| added together to form the most significant 32 bits of the result. This -| means that any integer portion of `zSig0' will be added into the exponent. -| Since a properly normalized significand will have an integer portion equal -| to 1, the `zExp' input should be 1 less than the desired result exponent -| whenever `zSig0' and `zSig1' concatenated form a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -SINLINE float128 packFloat128(flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1) { - float128 z; - - z.low = zSig1; - z.high = (((uint64_t) zSign) << 63) + (((uint64_t) zExp) << 48) + zSig0; - return z; -} - -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ - -static float128 roundAndPackFloat128(flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1, - uint64_t zSig2 STATUS_PARAM) { - int8 roundingMode; - flag roundNearestEven, increment, isTiny; - - roundingMode = STATUS(float_rounding_mode); - roundNearestEven = (roundingMode == float_round_nearest_even); - increment = ((int64_t) zSig2 < 0); - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - increment = 0; - } else { - if (zSign) { - increment = (roundingMode == float_round_down) && zSig2; - } else { - increment = (roundingMode == float_round_up) && zSig2; - } - } - } - if (0x7FFD <= (uint32_t) zExp) { - if ((0x7FFD < zExp) || - ((zExp == 0x7FFD) && eq128(LIT64(0x0001FFFFFFFFFFFF), LIT64(0xFFFFFFFFFFFFFFFF), zSig0, zSig1) && - increment)) { - float_raise(float_flag_overflow | float_flag_inexact STATUS_VAR); - if ((roundingMode == float_round_to_zero) || (zSign && (roundingMode == float_round_up)) || - (!zSign && (roundingMode == float_round_down))) { - return packFloat128(zSign, 0x7FFE, LIT64(0x0000FFFFFFFFFFFF), LIT64(0xFFFFFFFFFFFFFFFF)); - } - return packFloat128(zSign, 0x7FFF, 0, 0); - } - if (zExp < 0) { - if (STATUS(flush_to_zero)) { - float_raise(float_flag_output_denormal STATUS_VAR); - return packFloat128(zSign, 0, 0, 0); - } - isTiny = (STATUS(float_detect_tininess) == float_tininess_before_rounding) || (zExp < -1) || !increment || - lt128(zSig0, zSig1, LIT64(0x0001FFFFFFFFFFFF), LIT64(0xFFFFFFFFFFFFFFFF)); - shift128ExtraRightJamming(zSig0, zSig1, zSig2, -zExp, &zSig0, &zSig1, &zSig2); - zExp = 0; - if (isTiny && zSig2) - float_raise(float_flag_underflow STATUS_VAR); - if (roundNearestEven) { - increment = ((int64_t) zSig2 < 0); - } else { - if (zSign) { - increment = (roundingMode == float_round_down) && zSig2; - } else { - increment = (roundingMode == float_round_up) && zSig2; - } - } - } - } - if (zSig2) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - if (increment) { - add128(zSig0, zSig1, 0, 1, &zSig0, &zSig1); - zSig1 &= ~((zSig2 + zSig2 == 0) & roundNearestEven); - } 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. -*----------------------------------------------------------------------------*/ - -static float128 normalizeRoundAndPackFloat128(flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1 STATUS_PARAM) { - int8 shiftCount; - uint64_t zSig2; - - if (zSig0 == 0) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - 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_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the single-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 int32_to_float32(int32 a STATUS_PARAM) { - flag zSign; - - if (a == 0) - return float32_zero; - if (a == (int32_t) 0x80000000) - return packFloat32(1, 0x9E, 0); - zSign = (a < 0); - return normalizeRoundAndPackFloat32(zSign, 0x9C, zSign ? -a : a STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the double-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 int32_to_float64(int32 a STATUS_PARAM) { - flag zSign; - uint32 absA; - int8 shiftCount; - uint64_t zSig; - - if (a == 0) - return float64_zero; - zSign = (a < 0); - absA = zSign ? -a : a; - shiftCount = countLeadingZeros32(absA) + 21; - zSig = absA; - return packFloat64(zSign, 0x432 - shiftCount, zSig << shiftCount); -} - -/*---------------------------------------------------------------------------- -| 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(int32 a STATUS_PARAM) { - flag zSign; - uint32 absA; - int8 shiftCount; - uint64_t zSig; - - if (a == 0) - return packFloatx80(0, 0, 0); - zSign = (a < 0); - absA = zSign ? -a : a; - shiftCount = countLeadingZeros32(absA) + 32; - zSig = absA; - return packFloatx80(zSign, 0x403E - shiftCount, zSig << shiftCount); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' to -| the quadruple-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 int32_to_float128(int32 a STATUS_PARAM) { - flag zSign; - uint32 absA; - int8 shiftCount; - uint64_t zSig0; - - if (a == 0) - return packFloat128(0, 0, 0, 0); - zSign = (a < 0); - absA = zSign ? -a : a; - shiftCount = countLeadingZeros32(absA) + 17; - zSig0 = absA; - return packFloat128(zSign, 0x402E - shiftCount, zSig0 << shiftCount, 0); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 64-bit two's complement integer `a' -| to the single-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 int64_to_float32(int64 a STATUS_PARAM) { - flag zSign; - uint64 absA; - int8 shiftCount; - - if (a == 0) - return float32_zero; - zSign = (a < 0); - absA = zSign ? -a : a; - shiftCount = countLeadingZeros64(absA) - 40; - if (0 <= shiftCount) { - return packFloat32(zSign, 0x95 - shiftCount, absA << shiftCount); - } else { - shiftCount += 7; - if (shiftCount < 0) { - shift64RightJamming(absA, -shiftCount, &absA); - } else { - absA <<= shiftCount; - } - return roundAndPackFloat32(zSign, 0x9C - shiftCount, absA STATUS_VAR); - } -} - -float32 uint64_to_float32(uint64 a STATUS_PARAM) { - int8 shiftCount; - - if (a == 0) - return float32_zero; - shiftCount = countLeadingZeros64(a) - 40; - if (0 <= shiftCount) { - return packFloat32(1 > 0, 0x95 - shiftCount, a << shiftCount); - } else { - shiftCount += 7; - if (shiftCount < 0) { - shift64RightJamming(a, -shiftCount, &a); - } else { - a <<= shiftCount; - } - return roundAndPackFloat32(1 > 0, 0x9C - shiftCount, a STATUS_VAR); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 64-bit two's complement integer `a' -| to the double-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 int64_to_float64(int64 a STATUS_PARAM) { - flag zSign; - - if (a == 0) - return float64_zero; - if (a == (int64_t) LIT64(0x8000000000000000)) { - return packFloat64(1, 0x43E, 0); - } - zSign = (a < 0); - return normalizeRoundAndPackFloat64(zSign, 0x43C, zSign ? -a : a STATUS_VAR); -} - -float64 uint64_to_float64(uint64 a STATUS_PARAM) { - if (a == 0) - return float64_zero; - return normalizeRoundAndPackFloat64(0, 0x43C, a STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 64-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 int64_to_floatx80(int64 a STATUS_PARAM) { - flag zSign; - uint64 absA; - int8 shiftCount; - - if (a == 0) - return packFloatx80(0, 0, 0); - zSign = (a < 0); - absA = zSign ? -a : a; - shiftCount = countLeadingZeros64(absA); - return packFloatx80(zSign, 0x403E - shiftCount, absA << shiftCount); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 64-bit two's complement integer `a' to -| the quadruple-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 int64_to_float128(int64 a STATUS_PARAM) { - flag zSign; - uint64 absA; - int8 shiftCount; - int32 zExp; - uint64_t zSig0, zSig1; - - if (a == 0) - return packFloat128(0, 0, 0, 0); - zSign = (a < 0); - absA = zSign ? -a : a; - shiftCount = countLeadingZeros64(absA) + 49; - zExp = 0x406E - shiftCount; - if (64 <= shiftCount) { - zSig1 = 0; - zSig0 = absA; - shiftCount -= 64; - } else { - zSig1 = absA; - zSig0 = 0; - } - shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); - return packFloat128(zSign, zExp, zSig0, zSig1); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float32_to_int32(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp, shiftCount; - uint32_t aSig; - uint64_t aSig64; - - a = float32_squash_input_denormal(a STATUS_VAR); - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - if ((aExp == 0xFF) && aSig) - aSign = 0; - if (aExp) - aSig |= 0x00800000; - shiftCount = 0xAF - aExp; - aSig64 = aSig; - aSig64 <<= 32; - if (0 < shiftCount) - shift64RightJamming(aSig64, shiftCount, &aSig64); - return roundAndPackInt32(aSign, aSig64 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float32_to_int32_round_to_zero(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp, shiftCount; - uint32_t aSig; - int32_t z; - a = float32_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - shiftCount = aExp - 0x9E; - if (0 <= shiftCount) { - if (float32_val(a) != 0xCF000000) { - float_raise(float_flag_invalid STATUS_VAR); - if (!aSign || ((aExp == 0xFF) && aSig)) - return 0x7FFFFFFF; - } - return (int32_t) 0x80000000; - } else if (aExp <= 0x7E) { - if (aExp | aSig) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return 0; - } - aSig = (aSig | 0x00800000) << 8; - z = aSig >> (-shiftCount); - if ((uint32_t)(aSig << (shiftCount & 31))) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - if (aSign) - z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 16-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int16 float32_to_int16_round_to_zero(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp, shiftCount; - uint32_t aSig; - int32 z; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - shiftCount = aExp - 0x8E; - if (0 <= shiftCount) { - if (float32_val(a) != 0xC7000000) { - float_raise(float_flag_invalid STATUS_VAR); - if (!aSign || ((aExp == 0xFF) && aSig)) { - return 0x7FFF; - } - } - return (int32_t) 0xffff8000; - } else if (aExp <= 0x7E) { - if (aExp | aSig) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - return 0; - } - shiftCount -= 0x10; - aSig = (aSig | 0x00800000) << 8; - z = aSig >> (-shiftCount); - if ((uint32_t)(aSig << (shiftCount & 31))) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - if (aSign) { - z = -z; - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp, shiftCount; - uint32_t aSig; - uint64_t aSig64, aSigExtra; - a = float32_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - shiftCount = 0xBE - aExp; - if (shiftCount < 0) { - float_raise(float_flag_invalid STATUS_VAR); - if (!aSign || ((aExp == 0xFF) && aSig)) { - return LIT64(0x7FFFFFFFFFFFFFFF); - } - return (int64_t) LIT64(0x8000000000000000); - } - if (aExp) - aSig |= 0x00800000; - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra); - return roundAndPackInt64(aSign, aSig64, aSigExtra STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64_round_to_zero(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp, shiftCount; - uint32_t aSig; - uint64_t aSig64; - int64 z; - a = float32_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - shiftCount = aExp - 0xBE; - if (0 <= shiftCount) { - if (float32_val(a) != 0xDF000000) { - float_raise(float_flag_invalid STATUS_VAR); - if (!aSign || ((aExp == 0xFF) && aSig)) { - return LIT64(0x7FFFFFFFFFFFFFFF); - } - } - return (int64_t) LIT64(0x8000000000000000); - } else if (aExp <= 0x7E) { - if (aExp | aSig) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return 0; - } - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - z = aSig64 >> (-shiftCount); - if ((uint64_t)(aSig64 << (shiftCount & 63))) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - if (aSign) - z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float32_to_float64(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp; - uint32_t aSig; - a = float32_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - if (aExp == 0xFF) { - if (aSig) - return commonNaNToFloat64(float32ToCommonNaN(a STATUS_VAR) STATUS_VAR); - return packFloat64(aSign, 0x7FF, 0); - } - if (aExp == 0) { - if (aSig == 0) - return packFloat64(aSign, 0, 0); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - --aExp; - } - return packFloat64(aSign, aExp + 0x380, ((uint64_t) aSig) << 29); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `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 float32_to_floatx80(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp; - uint32_t aSig; - - a = float32_squash_input_denormal(a STATUS_VAR); - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - if (aExp == 0xFF) { - if (aSig) - return commonNaNToFloatx80(float32ToCommonNaN(a STATUS_VAR) STATUS_VAR); - return packFloatx80(aSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) - return packFloatx80(aSign, 0, 0); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - aSig |= 0x00800000; - return packFloatx80(aSign, aExp + 0x3F80, ((uint64_t) aSig) << 40); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float32_to_float128(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp; - uint32_t aSig; - - a = float32_squash_input_denormal(a STATUS_VAR); - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - if (aExp == 0xFF) { - if (aSig) - return commonNaNToFloat128(float32ToCommonNaN(a STATUS_VAR) STATUS_VAR); - return packFloat128(aSign, 0x7FFF, 0, 0); - } - if (aExp == 0) { - if (aSig == 0) - return packFloat128(aSign, 0, 0, 0); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - --aExp; - } - return packFloat128(aSign, aExp + 0x3F80, ((uint64_t) aSig) << 25, 0); -} - -/*---------------------------------------------------------------------------- -| Rounds the single-precision floating-point value `a' to an integer, and -| returns the result as a single-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_round_to_int(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp; - uint32_t lastBitMask, roundBitsMask; - int8 roundingMode; - uint32_t z; - a = float32_squash_input_denormal(a STATUS_VAR); - - aExp = extractFloat32Exp(a); - if (0x96 <= aExp) { - if ((aExp == 0xFF) && extractFloat32Frac(a)) { - return propagateFloat32NaN(a, a STATUS_VAR); - } - return a; - } - if (aExp <= 0x7E) { - if ((uint32_t)(float32_val(a) << 1) == 0) - return a; - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - aSign = extractFloat32Sign(a); - switch (STATUS(float_rounding_mode)) { - case float_round_nearest_even: - if ((aExp == 0x7E) && extractFloat32Frac(a)) { - return packFloat32(aSign, 0x7F, 0); - } - break; - case float_round_down: - return make_float32(aSign ? 0xBF800000 : 0); - case float_round_up: - return make_float32(aSign ? 0x80000000 : 0x3F800000); - } - return packFloat32(aSign, 0, 0); - } - lastBitMask = 1; - lastBitMask <<= 0x96 - aExp; - roundBitsMask = lastBitMask - 1; - z = float32_val(a); - roundingMode = STATUS(float_rounding_mode); - if (roundingMode == float_round_nearest_even) { - z += lastBitMask >> 1; - if ((z & roundBitsMask) == 0) - z &= ~lastBitMask; - } else if (roundingMode != float_round_to_zero) { - if (extractFloat32Sign(make_float32(z)) ^ (roundingMode == float_round_up)) { - z += roundBitsMask; - } - } - z &= ~roundBitsMask; - if (z != float32_val(a)) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return make_float32(z); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 addFloat32Sigs(float32 a, float32 b, flag zSign STATUS_PARAM) { - int16 aExp, bExp, zExp; - uint32_t aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - expDiff = aExp - bExp; - aSig <<= 6; - bSig <<= 6; - if (0 < expDiff) { - if (aExp == 0xFF) { - if (aSig) - return propagateFloat32NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) { - --expDiff; - } else { - bSig |= 0x20000000; - } - shift32RightJamming(bSig, expDiff, &bSig); - zExp = aExp; - } else if (expDiff < 0) { - if (bExp == 0xFF) { - if (bSig) - return propagateFloat32NaN(a, b STATUS_VAR); - return packFloat32(zSign, 0xFF, 0); - } - if (aExp == 0) { - ++expDiff; - } else { - aSig |= 0x20000000; - } - shift32RightJamming(aSig, -expDiff, &aSig); - zExp = bExp; - } else { - if (aExp == 0xFF) { - if (aSig | bSig) - return propagateFloat32NaN(a, b STATUS_VAR); - return a; - } - if (aExp == 0) { - if (STATUS(flush_to_zero)) { - if (aSig | bSig) { - float_raise(float_flag_output_denormal STATUS_VAR); - } - return packFloat32(zSign, 0, 0); - } - return packFloat32(zSign, 0, (aSig + bSig) >> 6); - } - zSig = 0x40000000 + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= 0x20000000; - zSig = (aSig + bSig) << 1; - --zExp; - if ((int32_t) zSig < 0) { - zSig = aSig + bSig; - ++zExp; - } -roundAndPack: - return roundAndPackFloat32(zSign, zExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 subFloat32Sigs(float32 a, float32 b, flag zSign STATUS_PARAM) { - int16 aExp, bExp, zExp; - uint32_t aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - expDiff = aExp - bExp; - aSig <<= 7; - bSig <<= 7; - if (0 < expDiff) - goto aExpBigger; - if (expDiff < 0) - goto bExpBigger; - if (aExp == 0xFF) { - if (aSig | bSig) - return propagateFloat32NaN(a, b STATUS_VAR); - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - if (aExp == 0) { - aExp = 1; - bExp = 1; - } - if (bSig < aSig) - goto aBigger; - if (aSig < bSig) - goto bBigger; - return packFloat32(STATUS(float_rounding_mode) == float_round_down, 0, 0); -bExpBigger: - if (bExp == 0xFF) { - if (bSig) - return propagateFloat32NaN(a, b STATUS_VAR); - return packFloat32(zSign ^ 1, 0xFF, 0); - } - if (aExp == 0) { - ++expDiff; - } else { - aSig |= 0x40000000; - } - shift32RightJamming(aSig, -expDiff, &aSig); - bSig |= 0x40000000; -bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; -aExpBigger: - if (aExp == 0xFF) { - if (aSig) - return propagateFloat32NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) { - --expDiff; - } else { - bSig |= 0x40000000; - } - shift32RightJamming(bSig, expDiff, &bSig); - aSig |= 0x40000000; -aBigger: - zSig = aSig - bSig; - zExp = aExp; -normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat32(zSign, zExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the single-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_add(float32 a, float32 b STATUS_PARAM) { - flag aSign, bSign; - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - aSign = extractFloat32Sign(a); - bSign = extractFloat32Sign(b); - if (aSign == bSign) { - return addFloat32Sigs(a, b, aSign STATUS_VAR); - } else { - return subFloat32Sigs(a, b, aSign STATUS_VAR); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sub(float32 a, float32 b STATUS_PARAM) { - flag aSign, bSign; - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - aSign = extractFloat32Sign(a); - bSign = extractFloat32Sign(b); - if (aSign == bSign) { - return subFloat32Sigs(a, b, aSign STATUS_VAR); - } else { - return addFloat32Sigs(a, b, aSign STATUS_VAR); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_mul(float32 a, float32 b STATUS_PARAM) { - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - uint32_t aSig, bSig; - uint64_t zSig64; - uint32_t zSig; - - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - bSign = extractFloat32Sign(b); - zSign = aSign ^ bSign; - if (aExp == 0xFF) { - if (aSig || ((bExp == 0xFF) && bSig)) { - return propagateFloat32NaN(a, b STATUS_VAR); - } - if ((bExp | bSig) == 0) { - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - return packFloat32(zSign, 0xFF, 0); - } - if (bExp == 0xFF) { - if (bSig) - return propagateFloat32NaN(a, b STATUS_VAR); - if ((aExp | aSig) == 0) { - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - return packFloat32(zSign, 0xFF, 0); - } - if (aExp == 0) { - if (aSig == 0) - return packFloat32(zSign, 0, 0); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) - return packFloat32(zSign, 0, 0); - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - zExp = aExp + bExp - 0x7F; - aSig = (aSig | 0x00800000) << 7; - bSig = (bSig | 0x00800000) << 8; - shift64RightJamming(((uint64_t) aSig) * bSig, 32, &zSig64); - zSig = zSig64; - if (0 <= (int32_t)(zSig << 1)) { - zSig <<= 1; - --zExp; - } - return roundAndPackFloat32(zSign, zExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the single-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_div(float32 a, float32 b STATUS_PARAM) { - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - uint32_t aSig, bSig, zSig; - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - bSign = extractFloat32Sign(b); - zSign = aSign ^ bSign; - if (aExp == 0xFF) { - if (aSig) - return propagateFloat32NaN(a, b STATUS_VAR); - if (bExp == 0xFF) { - if (bSig) - return propagateFloat32NaN(a, b STATUS_VAR); - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - return packFloat32(zSign, 0xFF, 0); - } - if (bExp == 0xFF) { - if (bSig) - return propagateFloat32NaN(a, b STATUS_VAR); - return packFloat32(zSign, 0, 0); - } - if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - float_raise(float_flag_divbyzero STATUS_VAR); - return packFloat32(zSign, 0xFF, 0); - } - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) - return packFloat32(zSign, 0, 0); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - zExp = aExp - bExp + 0x7D; - aSig = (aSig | 0x00800000) << 7; - bSig = (bSig | 0x00800000) << 8; - if (bSig <= (aSig + aSig)) { - aSig >>= 1; - ++zExp; - } - zSig = (((uint64_t) aSig) << 32) / bSig; - if ((zSig & 0x3F) == 0) { - zSig |= ((uint64_t) bSig * zSig != ((uint64_t) aSig) << 32); - } - return roundAndPackFloat32(zSign, zExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the single-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_rem(float32 a, float32 b STATUS_PARAM) { - flag aSign, zSign; - int16 aExp, bExp, expDiff; - uint32_t aSig, bSig; - uint32_t q; - uint64_t aSig64, bSig64, q64; - uint32_t alternateASig; - int32_t sigMean; - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - if (aExp == 0xFF) { - if (aSig || ((bExp == 0xFF) && bSig)) { - return propagateFloat32NaN(a, b STATUS_VAR); - } - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - if (bExp == 0xFF) { - if (bSig) - return propagateFloat32NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) { - if (bSig == 0) { - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) - return a; - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - expDiff = aExp - bExp; - aSig |= 0x00800000; - bSig |= 0x00800000; - if (expDiff < 32) { - aSig <<= 8; - bSig <<= 8; - if (expDiff < 0) { - if (expDiff < -1) - return a; - aSig >>= 1; - } - q = (bSig <= aSig); - if (q) - aSig -= bSig; - if (0 < expDiff) { - q = (((uint64_t) aSig) << 32) / bSig; - q >>= 32 - expDiff; - bSig >>= 2; - aSig = ((aSig >> 1) << (expDiff - 1)) - bSig * q; - } else { - aSig >>= 2; - bSig >>= 2; - } - } else { - if (bSig <= aSig) - aSig -= bSig; - aSig64 = ((uint64_t) aSig) << 40; - bSig64 = ((uint64_t) bSig) << 40; - expDiff -= 64; - while (0 < expDiff) { - q64 = estimateDiv128To64(aSig64, 0, bSig64); - q64 = (2 < q64) ? q64 - 2 : 0; - aSig64 = -((bSig * q64) << 38); - expDiff -= 62; - } - expDiff += 64; - q64 = estimateDiv128To64(aSig64, 0, bSig64); - q64 = (2 < q64) ? q64 - 2 : 0; - q = q64 >> (64 - expDiff); - bSig <<= 6; - aSig = ((aSig64 >> 33) << (expDiff - 1)) - bSig * q; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while (0 <= (int32_t) aSig); - sigMean = aSig + alternateASig; - if ((sigMean < 0) || ((sigMean == 0) && (q & 1))) { - aSig = alternateASig; - } - zSign = ((int32_t) aSig < 0); - if (zSign) - aSig = -aSig; - return normalizeRoundAndPackFloat32(aSign ^ zSign, bExp, aSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b' then adding 'c', with no intermediate rounding step after the -| multiplication. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic 754-2008. -| The flags argument allows the caller to select negation of the -| addend, the intermediate product, or the final result. (The difference -| between this and having the caller do a separate negation is that negating -| externally will flip the sign bit on NaNs.) -*----------------------------------------------------------------------------*/ - -float32 float32_muladd(float32 a, float32 b, float32 c, int flags STATUS_PARAM) { - flag aSign, bSign, cSign, zSign; - int aExp, bExp, cExp, pExp, zExp, expDiff; - uint32_t aSig, bSig, cSig; - flag pInf, pZero, pSign; - uint64_t pSig64, cSig64, zSig64; - uint32_t pSig; - int shiftcount; - flag signflip, infzero; - - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - c = float32_squash_input_denormal(c STATUS_VAR); - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - bSign = extractFloat32Sign(b); - cSig = extractFloat32Frac(c); - cExp = extractFloat32Exp(c); - cSign = extractFloat32Sign(c); - - infzero = ((aExp == 0 && aSig == 0 && bExp == 0xff && bSig == 0) || - (aExp == 0xff && aSig == 0 && bExp == 0 && bSig == 0)); - - /* It is implementation-defined whether the cases of (0,inf,qnan) - * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN - * they return if they do), so we have to hand this information - * off to the target-specific pick-a-NaN routine. - */ - if (((aExp == 0xff) && aSig) || ((bExp == 0xff) && bSig) || ((cExp == 0xff) && cSig)) { - return propagateFloat32MulAddNaN(a, b, c, infzero STATUS_VAR); - } - - if (infzero) { - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - - if (flags & float_muladd_negate_c) { - cSign ^= 1; - } - - signflip = (flags & float_muladd_negate_result) ? 1 : 0; - - /* Work out the sign and type of the product */ - pSign = aSign ^ bSign; - if (flags & float_muladd_negate_product) { - pSign ^= 1; - } - pInf = (aExp == 0xff) || (bExp == 0xff); - pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0); - - if (cExp == 0xff) { - if (pInf && (pSign ^ cSign)) { - /* addition of opposite-signed infinities => InvalidOperation */ - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - /* Otherwise generate an infinity of the same sign */ - return packFloat32(cSign ^ signflip, 0xff, 0); - } - - if (pInf) { - return packFloat32(pSign ^ signflip, 0xff, 0); - } - - if (pZero) { - if (cExp == 0) { - if (cSig == 0) { - /* Adding two exact zeroes */ - if (pSign == cSign) { - zSign = pSign; - } else if (STATUS(float_rounding_mode) == float_round_down) { - zSign = 1; - } else { - zSign = 0; - } - return packFloat32(zSign ^ signflip, 0, 0); - } - /* Exact zero plus a denorm */ - if (STATUS(flush_to_zero)) { - float_raise(float_flag_output_denormal STATUS_VAR); - return packFloat32(cSign ^ signflip, 0, 0); - } - } - /* Zero plus something non-zero : just return the something */ - return c ^ (signflip << 31); - } - - if (aExp == 0) { - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - - /* Calculate the actual result a * b + c */ - - /* Multiply first; this is easy. */ - /* NB: we subtract 0x7e where float32_mul() subtracts 0x7f - * because we want the true exponent, not the "one-less-than" - * flavour that roundAndPackFloat32() takes. - */ - pExp = aExp + bExp - 0x7e; - aSig = (aSig | 0x00800000) << 7; - bSig = (bSig | 0x00800000) << 8; - pSig64 = (uint64_t) aSig * bSig; - if ((int64_t)(pSig64 << 1) >= 0) { - pSig64 <<= 1; - pExp--; - } - - zSign = pSign ^ signflip; - - /* Now pSig64 is the significand of the multiply, with the explicit bit in - * position 62. - */ - if (cExp == 0) { - if (!cSig) { - /* Throw out the special case of c being an exact zero now */ - shift64RightJamming(pSig64, 32, &pSig64); - pSig = pSig64; - return roundAndPackFloat32(zSign, pExp - 1, pSig STATUS_VAR); - } - normalizeFloat32Subnormal(cSig, &cExp, &cSig); - } - - cSig64 = (uint64_t) cSig << (62 - 23); - cSig64 |= LIT64(0x4000000000000000); - expDiff = pExp - cExp; - - if (pSign == cSign) { - /* Addition */ - if (expDiff > 0) { - /* scale c to match p */ - shift64RightJamming(cSig64, expDiff, &cSig64); - zExp = pExp; - } else if (expDiff < 0) { - /* scale p to match c */ - shift64RightJamming(pSig64, -expDiff, &pSig64); - zExp = cExp; - } else { - /* no scaling needed */ - zExp = cExp; - } - /* Add significands and make sure explicit bit ends up in posn 62 */ - zSig64 = pSig64 + cSig64; - if ((int64_t) zSig64 < 0) { - shift64RightJamming(zSig64, 1, &zSig64); - } else { - zExp--; - } - } else { - /* Subtraction */ - if (expDiff > 0) { - shift64RightJamming(cSig64, expDiff, &cSig64); - zSig64 = pSig64 - cSig64; - zExp = pExp; - } else if (expDiff < 0) { - shift64RightJamming(pSig64, -expDiff, &pSig64); - zSig64 = cSig64 - pSig64; - zExp = cExp; - zSign ^= 1; - } else { - zExp = pExp; - if (cSig64 < pSig64) { - zSig64 = pSig64 - cSig64; - } else if (pSig64 < cSig64) { - zSig64 = cSig64 - pSig64; - zSign ^= 1; - } else { - /* Exact zero */ - zSign = signflip; - if (STATUS(float_rounding_mode) == float_round_down) { - zSign ^= 1; - } - return packFloat32(zSign, 0, 0); - } - } - --zExp; - /* Normalize to put the explicit bit back into bit 62. */ - shiftcount = countLeadingZeros64(zSig64) - 1; - zSig64 <<= shiftcount; - zExp -= shiftcount; - } - shift64RightJamming(zSig64, 32, &zSig64); - return roundAndPackFloat32(zSign, zExp, zSig64 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the single-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sqrt(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp, zExp; - uint32_t aSig, zSig; - uint64_t rem, term; - a = float32_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - if (aExp == 0xFF) { - if (aSig) - return propagateFloat32NaN(a, float32_zero STATUS_VAR); - if (!aSign) - return a; - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - if (aSign) { - if ((aExp | aSig) == 0) - return a; - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - if (aExp == 0) { - if (aSig == 0) - return float32_zero; - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - zExp = ((aExp - 0x7F) >> 1) + 0x7E; - aSig = (aSig | 0x00800000) << 8; - zSig = estimateSqrt32(aExp, aSig) + 2; - if ((zSig & 0x7F) <= 5) { - if (zSig < 2) { - zSig = 0x7FFFFFFF; - goto roundAndPack; - } - aSig >>= aExp & 1; - term = ((uint64_t) zSig) * zSig; - rem = (((uint64_t) aSig) << 32) - term; - while ((int64_t) rem < 0) { - --zSig; - rem += (((uint64_t) zSig) << 1) | 1; - } - zSig |= (rem != 0); - } - shift32RightJamming(zSig, 1, &zSig); -roundAndPack: - return roundAndPackFloat32(0, zExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the binary exponential of the single-precision floating-point value -| `a'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -| -| Uses the following identities: -| -| 1. ------------------------------------------------------------------------- -| x x*ln(2) -| 2 = e -| -| 2. ------------------------------------------------------------------------- -| 2 3 4 5 n -| x x x x x x x -| e = 1 + --- + --- + --- + --- + --- + ... + --- + ... -| 1! 2! 3! 4! 5! n! -*----------------------------------------------------------------------------*/ - -static const float64 float32_exp2_coefficients[15] = { - const_float64(0x3ff0000000000000ll), /* 1 */ - const_float64(0x3fe0000000000000ll), /* 2 */ - const_float64(0x3fc5555555555555ll), /* 3 */ - const_float64(0x3fa5555555555555ll), /* 4 */ - const_float64(0x3f81111111111111ll), /* 5 */ - const_float64(0x3f56c16c16c16c17ll), /* 6 */ - const_float64(0x3f2a01a01a01a01all), /* 7 */ - const_float64(0x3efa01a01a01a01all), /* 8 */ - const_float64(0x3ec71de3a556c734ll), /* 9 */ - const_float64(0x3e927e4fb7789f5cll), /* 10 */ - const_float64(0x3e5ae64567f544e4ll), /* 11 */ - const_float64(0x3e21eed8eff8d898ll), /* 12 */ - const_float64(0x3de6124613a86d09ll), /* 13 */ - const_float64(0x3da93974a8c07c9dll), /* 14 */ - const_float64(0x3d6ae7f3e733b81fll), /* 15 */ -}; - -float32 float32_exp2(float32 a STATUS_PARAM) { - flag aSign; - int16 aExp; - uint32_t aSig; - float64 r, x, xn; - int i; - a = float32_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) - return propagateFloat32NaN(a, float32_zero STATUS_VAR); - return (aSign) ? float32_zero : a; - } - if (aExp == 0) { - if (aSig == 0) - return float32_one; - } - - float_raise(float_flag_inexact STATUS_VAR); - - /* ******************************* */ - /* using float64 for approximation */ - /* ******************************* */ - x = float32_to_float64(a STATUS_VAR); - x = float64_mul(x, float64_ln2 STATUS_VAR); - - xn = x; - r = float64_one; - for (i = 0; i < 15; i++) { - float64 f; - - f = float64_mul(xn, float32_exp2_coefficients[i] STATUS_VAR); - r = float64_add(r, f STATUS_VAR); - - xn = float64_mul(xn, x STATUS_VAR); - } - - return float64_to_float32(r, status); -} - -/*---------------------------------------------------------------------------- -| Returns the binary log of the single-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -float32 float32_log2(float32 a STATUS_PARAM) { - flag aSign, zSign; - int16 aExp; - uint32_t aSig, zSig, i; - - a = float32_squash_input_denormal(a STATUS_VAR); - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - - if (aExp == 0) { - if (aSig == 0) - return packFloat32(1, 0xFF, 0); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - if (aSign) { - float_raise(float_flag_invalid STATUS_VAR); - return float32_default_nan; - } - if (aExp == 0xFF) { - if (aSig) - return propagateFloat32NaN(a, float32_zero STATUS_VAR); - return a; - } - - aExp -= 0x7F; - aSig |= 0x00800000; - zSign = aExp < 0; - zSig = aExp << 23; - - for (i = 1 << 22; i > 0; i >>= 1) { - aSig = ((uint64_t) aSig * aSig) >> 23; - if (aSig & 0x01000000) { - aSig >>= 1; - zSig |= i; - } - } - - if (zSign) - zSig = -zSig; - - return normalizeRoundAndPackFloat32(zSign, 0x85, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_eq(float32 a, float32 b STATUS_PARAM) { - uint32_t av, bv; - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat32Exp(a) == 0xFF) && extractFloat32Frac(a)) || - ((extractFloat32Exp(b) == 0xFF) && extractFloat32Frac(b))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - av = float32_val(a); - bv = float32_val(b); - return (av == bv) || ((uint32_t)((av | bv) << 1) == 0); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The invalid -| exception is raised if either operand is a NaN. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_le(float32 a, float32 b STATUS_PARAM) { - flag aSign, bSign; - uint32_t av, bv; - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat32Exp(a) == 0xFF) && extractFloat32Frac(a)) || - ((extractFloat32Exp(b) == 0xFF) && extractFloat32Frac(b))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - aSign = extractFloat32Sign(a); - bSign = extractFloat32Sign(b); - av = float32_val(a); - bv = float32_val(b); - if (aSign != bSign) - return aSign || ((uint32_t)((av | bv) << 1) == 0); - return (av == bv) || (aSign ^ (av < bv)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. The comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_lt(float32 a, float32 b STATUS_PARAM) { - flag aSign, bSign; - uint32_t av, bv; - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat32Exp(a) == 0xFF) && extractFloat32Frac(a)) || - ((extractFloat32Exp(b) == 0xFF) && extractFloat32Frac(b))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - aSign = extractFloat32Sign(a); - bSign = extractFloat32Sign(b); - av = float32_val(a); - bv = float32_val(b); - if (aSign != bSign) - return aSign && ((uint32_t)((av | bv) << 1) != 0); - return (av != bv) && (aSign ^ (av < bv)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. The invalid exception is raised if either -| operand is a NaN. The comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_unordered(float32 a, float32 b STATUS_PARAM) { - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat32Exp(a) == 0xFF) && extractFloat32Frac(a)) || - ((extractFloat32Exp(b) == 0xFF) && extractFloat32Frac(b))) { - float_raise(float_flag_invalid STATUS_VAR); - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. The comparison is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_eq_quiet(float32 a, float32 b STATUS_PARAM) { - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat32Exp(a) == 0xFF) && extractFloat32Frac(a)) || - ((extractFloat32Exp(b) == 0xFF) && extractFloat32Frac(b))) { - if (float32_is_signaling_nan(a) || float32_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - return (float32_val(a) == float32_val(b)) || ((uint32_t)((float32_val(a) | float32_val(b)) << 1) == 0); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_le_quiet(float32 a, float32 b STATUS_PARAM) { - flag aSign, bSign; - uint32_t av, bv; - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat32Exp(a) == 0xFF) && extractFloat32Frac(a)) || - ((extractFloat32Exp(b) == 0xFF) && extractFloat32Frac(b))) { - if (float32_is_signaling_nan(a) || float32_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - aSign = extractFloat32Sign(a); - bSign = extractFloat32Sign(b); - av = float32_val(a); - bv = float32_val(b); - if (aSign != bSign) - return aSign || ((uint32_t)((av | bv) << 1) == 0); - return (av == bv) || (aSign ^ (av < bv)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_lt_quiet(float32 a, float32 b STATUS_PARAM) { - flag aSign, bSign; - uint32_t av, bv; - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat32Exp(a) == 0xFF) && extractFloat32Frac(a)) || - ((extractFloat32Exp(b) == 0xFF) && extractFloat32Frac(b))) { - if (float32_is_signaling_nan(a) || float32_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - aSign = extractFloat32Sign(a); - bSign = extractFloat32Sign(b); - av = float32_val(a); - bv = float32_val(b); - if (aSign != bSign) - return aSign && ((uint32_t)((av | bv) << 1) != 0); - return (av != bv) && (aSign ^ (av < bv)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_unordered_quiet(float32 a, float32 b STATUS_PARAM) { - a = float32_squash_input_denormal(a STATUS_VAR); - b = float32_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat32Exp(a) == 0xFF) && extractFloat32Frac(a)) || - ((extractFloat32Exp(b) == 0xFF) && extractFloat32Frac(b))) { - if (float32_is_signaling_nan(a) || float32_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32(float64 a STATUS_PARAM) { - flag aSign; - int16 aExp, shiftCount; - uint64_t aSig; - a = float64_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if ((aExp == 0x7FF) && aSig) - aSign = 0; - if (aExp) - aSig |= LIT64(0x0010000000000000); - shiftCount = 0x42C - aExp; - if (0 < shiftCount) - shift64RightJamming(aSig, shiftCount, &aSig); - return roundAndPackInt32(aSign, aSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32_round_to_zero(float64 a STATUS_PARAM) { - flag aSign; - int16 aExp, shiftCount; - uint64_t aSig, savedASig; - int32_t z; - a = float64_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (0x41E < aExp) { - if ((aExp == 0x7FF) && aSig) - aSign = 0; - goto invalid; - } else if (aExp < 0x3FF) { - if (aExp || aSig) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return 0; - } - aSig |= LIT64(0x0010000000000000); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if (aSign) - z = -z; - if ((z < 0) ^ aSign) { - invalid: - float_raise(float_flag_invalid STATUS_VAR); - return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF; - } - if ((aSig << shiftCount) != savedASig) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 16-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int16 float64_to_int16_round_to_zero(float64 a STATUS_PARAM) { - flag aSign; - int16 aExp, shiftCount; - uint64_t aSig, savedASig; - int32 z; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (0x40E < aExp) { - if ((aExp == 0x7FF) && aSig) { - aSign = 0; - } - goto invalid; - } else if (aExp < 0x3FF) { - if (aExp || aSig) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - return 0; - } - aSig |= LIT64(0x0010000000000000); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if (aSign) { - z = -z; - } - if (((int16_t) z < 0) ^ aSign) { - invalid: - float_raise(float_flag_invalid STATUS_VAR); - return aSign ? (int32_t) 0xffff8000 : 0x7FFF; - } - if ((aSig << shiftCount) != savedASig) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 float64_to_int64(float64 a STATUS_PARAM) { - flag aSign; - int16 aExp, shiftCount; - uint64_t aSig, aSigExtra; - a = float64_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (aExp) - aSig |= LIT64(0x0010000000000000); - shiftCount = 0x433 - aExp; - if (shiftCount <= 0) { - if (0x43E < aExp) { - float_raise(float_flag_invalid STATUS_VAR); - if (!aSign || ((aExp == 0x7FF) && (aSig != LIT64(0x0010000000000000)))) { - return LIT64(0x7FFFFFFFFFFFFFFF); - } - return (int64_t) LIT64(0x8000000000000000); - } - aSigExtra = 0; - aSig <<= -shiftCount; - } else { - shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra); - } - return roundAndPackInt64(aSign, aSig, aSigExtra STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64 float64_to_int64_round_to_zero(float64 a STATUS_PARAM) { - flag aSign; - int16 aExp, shiftCount; - uint64_t aSig; - int64 z; - a = float64_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (aExp) - aSig |= LIT64(0x0010000000000000); - shiftCount = aExp - 0x433; - if (0 <= shiftCount) { - if (0x43E <= aExp) { - if (float64_val(a) != LIT64(0xC3E0000000000000)) { - float_raise(float_flag_invalid STATUS_VAR); - if (!aSign || ((aExp == 0x7FF) && (aSig != LIT64(0x0010000000000000)))) { - return LIT64(0x7FFFFFFFFFFFFFFF); - } - } - return (int64_t) LIT64(0x8000000000000000); - } - z = aSig << shiftCount; - } else { - if (aExp < 0x3FE) { - if (aExp | aSig) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return 0; - } - z = aSig >> (-shiftCount); - if ((uint64_t)(aSig << (shiftCount & 63))) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - } - if (aSign) - z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float64_to_float32(float64 a STATUS_PARAM) { - flag aSign; - int16 aExp; - uint64_t aSig; - uint32_t zSig; - a = float64_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (aExp == 0x7FF) { - if (aSig) - return commonNaNToFloat32(float64ToCommonNaN(a STATUS_VAR) STATUS_VAR); - return packFloat32(aSign, 0xFF, 0); - } - shift64RightJamming(aSig, 22, &aSig); - zSig = aSig; - if (aExp || zSig) { - zSig |= 0x40000000; - aExp -= 0x381; - } - return roundAndPackFloat32(aSign, aExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| half-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ -static float16 packFloat16(flag zSign, int16 zExp, uint16_t zSig) { - return make_float16((((uint32_t) zSign) << 15) + (((uint32_t) zExp) << 10) + zSig); -} - -/* Half precision floats come in two formats: standard IEEE and "ARM" format. - The latter gains extra exponent range by omitting the NaN/Inf encodings. */ - -float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM) { - flag aSign; - int16 aExp; - uint32_t aSig; - - aSign = extractFloat16Sign(a); - aExp = extractFloat16Exp(a); - aSig = extractFloat16Frac(a); - - if (aExp == 0x1f && ieee) { - if (aSig) { - return commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR) STATUS_VAR); - } - return packFloat32(aSign, 0xff, aSig << 13); - } - if (aExp == 0) { - int8 shiftCount; - - if (aSig == 0) { - return packFloat32(aSign, 0, 0); - } - - shiftCount = countLeadingZeros32(aSig) - 21; - aSig = aSig << shiftCount; - aExp = -shiftCount; - } - return packFloat32(aSign, aExp + 0x70, aSig << 13); -} - -float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM) { - flag aSign; - int16 aExp; - uint32_t aSig; - uint32_t mask; - uint32_t increment; - int8 roundingMode; - a = float32_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - if (aExp == 0xFF) { - if (aSig) { - /* Input is a NaN */ - float16 r = commonNaNToFloat16(float32ToCommonNaN(a STATUS_VAR) STATUS_VAR); - if (!ieee) { - return packFloat16(aSign, 0, 0); - } - return r; - } - /* Infinity */ - if (!ieee) { - float_raise(float_flag_invalid STATUS_VAR); - return packFloat16(aSign, 0x1f, 0x3ff); - } - return packFloat16(aSign, 0x1f, 0); - } - if (aExp == 0 && aSig == 0) { - return packFloat16(aSign, 0, 0); - } - /* Decimal point between bits 22 and 23. */ - aSig |= 0x00800000; - aExp -= 0x7f; - if (aExp < -14) { - mask = 0x00ffffff; - if (aExp >= -24) { - mask >>= 25 + aExp; - } - } else { - mask = 0x00001fff; - } - if (aSig & mask) { - float_raise(float_flag_underflow STATUS_VAR); - roundingMode = STATUS(float_rounding_mode); - switch (roundingMode) { - case float_round_nearest_even: - increment = (mask + 1) >> 1; - if ((aSig & mask) == increment) { - increment = aSig & (increment << 1); - } - break; - case float_round_up: - increment = aSign ? 0 : mask; - break; - case float_round_down: - increment = aSign ? mask : 0; - break; - default: /* round_to_zero */ - increment = 0; - break; - } - aSig += increment; - if (aSig >= 0x01000000) { - aSig >>= 1; - aExp++; - } - } else if (aExp < -14 && STATUS(float_detect_tininess) == float_tininess_before_rounding) { - float_raise(float_flag_underflow STATUS_VAR); - } - - if (ieee) { - if (aExp > 15) { - float_raise(float_flag_overflow | float_flag_inexact STATUS_VAR); - return packFloat16(aSign, 0x1f, 0); - } - } else { - if (aExp > 16) { - float_raise(float_flag_invalid | float_flag_inexact STATUS_VAR); - return packFloat16(aSign, 0x1f, 0x3ff); - } - } - if (aExp < -24) { - return packFloat16(aSign, 0, 0); - } - if (aExp < -14) { - aSig >>= -14 - aExp; - aExp = -14; - } - return packFloat16(aSign, aExp + 14, aSig >> 13); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `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 float64_to_floatx80(float64 a STATUS_PARAM) { - flag aSign; - int16 aExp; - uint64_t aSig; - - a = float64_squash_input_denormal(a STATUS_VAR); - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (aExp == 0x7FF) { - if (aSig) - return commonNaNToFloatx80(float64ToCommonNaN(a STATUS_VAR) STATUS_VAR); - return packFloatx80(aSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) - return packFloatx80(aSign, 0, 0); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - return packFloatx80(aSign, aExp + 0x3C00, (aSig | LIT64(0x0010000000000000)) << 11); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the quadruple-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float64_to_float128(float64 a STATUS_PARAM) { - flag aSign; - int16 aExp; - uint64_t aSig, zSig0, zSig1; - - a = float64_squash_input_denormal(a STATUS_VAR); - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (aExp == 0x7FF) { - if (aSig) - return commonNaNToFloat128(float64ToCommonNaN(a STATUS_VAR) STATUS_VAR); - return packFloat128(aSign, 0x7FFF, 0, 0); - } - if (aExp == 0) { - if (aSig == 0) - return packFloat128(aSign, 0, 0, 0); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - --aExp; - } - shift128Right(aSig, 0, 4, &zSig0, &zSig1); - return packFloat128(aSign, aExp + 0x3C00, zSig0, zSig1); -} - -/*---------------------------------------------------------------------------- -| Rounds the double-precision floating-point value `a' to an integer, and -| returns the result as a double-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_round_to_int(float64 a STATUS_PARAM) { - flag aSign; - int16 aExp; - uint64_t lastBitMask, roundBitsMask; - int8 roundingMode; - uint64_t z; - a = float64_squash_input_denormal(a STATUS_VAR); - - aExp = extractFloat64Exp(a); - if (0x433 <= aExp) { - if ((aExp == 0x7FF) && extractFloat64Frac(a)) { - return propagateFloat64NaN(a, a STATUS_VAR); - } - return a; - } - if (aExp < 0x3FF) { - if ((uint64_t)(float64_val(a) << 1) == 0) - return a; - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - aSign = extractFloat64Sign(a); - switch (STATUS(float_rounding_mode)) { - case float_round_nearest_even: - if ((aExp == 0x3FE) && extractFloat64Frac(a)) { - return packFloat64(aSign, 0x3FF, 0); - } - break; - case float_round_down: - return make_float64(aSign ? LIT64(0xBFF0000000000000) : 0); - case float_round_up: - return make_float64(aSign ? LIT64(0x8000000000000000) : LIT64(0x3FF0000000000000)); - } - return packFloat64(aSign, 0, 0); - } - lastBitMask = 1; - lastBitMask <<= 0x433 - aExp; - roundBitsMask = lastBitMask - 1; - z = float64_val(a); - roundingMode = STATUS(float_rounding_mode); - if (roundingMode == float_round_nearest_even) { - z += lastBitMask >> 1; - if ((z & roundBitsMask) == 0) - z &= ~lastBitMask; - } else if (roundingMode != float_round_to_zero) { - if (extractFloat64Sign(make_float64(z)) ^ (roundingMode == float_round_up)) { - z += roundBitsMask; - } - } - z &= ~roundBitsMask; - if (z != float64_val(a)) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return make_float64(z); -} - -float64 float64_trunc_to_int(float64 a STATUS_PARAM) { - int oldmode; - float64 res; - oldmode = STATUS(float_rounding_mode); - STATUS_W(float_rounding_mode, float_round_to_zero); - res = float64_round_to_int(a STATUS_VAR); - STATUS_W(float_rounding_mode, oldmode); - return res; -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 addFloat64Sigs(float64 a, float64 b, flag zSign STATUS_PARAM) { - int16 aExp, bExp, zExp; - uint64_t aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - expDiff = aExp - bExp; - aSig <<= 9; - bSig <<= 9; - if (0 < expDiff) { - if (aExp == 0x7FF) { - if (aSig) - return propagateFloat64NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) { - --expDiff; - } else { - bSig |= LIT64(0x2000000000000000); - } - shift64RightJamming(bSig, expDiff, &bSig); - zExp = aExp; - } else if (expDiff < 0) { - if (bExp == 0x7FF) { - if (bSig) - return propagateFloat64NaN(a, b STATUS_VAR); - return packFloat64(zSign, 0x7FF, 0); - } - if (aExp == 0) { - ++expDiff; - } else { - aSig |= LIT64(0x2000000000000000); - } - shift64RightJamming(aSig, -expDiff, &aSig); - zExp = bExp; - } else { - if (aExp == 0x7FF) { - if (aSig | bSig) - return propagateFloat64NaN(a, b STATUS_VAR); - return a; - } - if (aExp == 0) { - if (STATUS(flush_to_zero)) { - if (aSig | bSig) { - float_raise(float_flag_output_denormal STATUS_VAR); - } - return packFloat64(zSign, 0, 0); - } - return packFloat64(zSign, 0, (aSig + bSig) >> 9); - } - zSig = LIT64(0x4000000000000000) + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= LIT64(0x2000000000000000); - zSig = (aSig + bSig) << 1; - --zExp; - if ((int64_t) zSig < 0) { - zSig = aSig + bSig; - ++zExp; - } -roundAndPack: - return roundAndPackFloat64(zSign, zExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 subFloat64Sigs(float64 a, float64 b, flag zSign STATUS_PARAM) { - int16 aExp, bExp, zExp; - uint64_t aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - expDiff = aExp - bExp; - aSig <<= 10; - bSig <<= 10; - if (0 < expDiff) - goto aExpBigger; - if (expDiff < 0) - goto bExpBigger; - if (aExp == 0x7FF) { - if (aSig | bSig) - return propagateFloat64NaN(a, b STATUS_VAR); - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - if (aExp == 0) { - aExp = 1; - bExp = 1; - } - if (bSig < aSig) - goto aBigger; - if (aSig < bSig) - goto bBigger; - return packFloat64(STATUS(float_rounding_mode) == float_round_down, 0, 0); -bExpBigger: - if (bExp == 0x7FF) { - if (bSig) - return propagateFloat64NaN(a, b STATUS_VAR); - return packFloat64(zSign ^ 1, 0x7FF, 0); - } - if (aExp == 0) { - ++expDiff; - } else { - aSig |= LIT64(0x4000000000000000); - } - shift64RightJamming(aSig, -expDiff, &aSig); - bSig |= LIT64(0x4000000000000000); -bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; -aExpBigger: - if (aExp == 0x7FF) { - if (aSig) - return propagateFloat64NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) { - --expDiff; - } else { - bSig |= LIT64(0x4000000000000000); - } - shift64RightJamming(bSig, expDiff, &bSig); - aSig |= LIT64(0x4000000000000000); -aBigger: - zSig = aSig - bSig; - zExp = aExp; -normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat64(zSign, zExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_add(float64 a, float64 b STATUS_PARAM) { - flag aSign, bSign; - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - aSign = extractFloat64Sign(a); - bSign = extractFloat64Sign(b); - if (aSign == bSign) { - return addFloat64Sigs(a, b, aSign STATUS_VAR); - } else { - return subFloat64Sigs(a, b, aSign STATUS_VAR); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sub(float64 a, float64 b STATUS_PARAM) { - flag aSign, bSign; - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - aSign = extractFloat64Sign(a); - bSign = extractFloat64Sign(b); - if (aSign == bSign) { - return subFloat64Sigs(a, b, aSign STATUS_VAR); - } else { - return addFloat64Sigs(a, b, aSign STATUS_VAR); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_mul(float64 a, float64 b STATUS_PARAM) { - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - uint64_t aSig, bSig, zSig0, zSig1; - - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - bSign = extractFloat64Sign(b); - zSign = aSign ^ bSign; - if (aExp == 0x7FF) { - if (aSig || ((bExp == 0x7FF) && bSig)) { - return propagateFloat64NaN(a, b STATUS_VAR); - } - if ((bExp | bSig) == 0) { - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - return packFloat64(zSign, 0x7FF, 0); - } - if (bExp == 0x7FF) { - if (bSig) - return propagateFloat64NaN(a, b STATUS_VAR); - if ((aExp | aSig) == 0) { - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - return packFloat64(zSign, 0x7FF, 0); - } - if (aExp == 0) { - if (aSig == 0) - return packFloat64(zSign, 0, 0); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) - return packFloat64(zSign, 0, 0); - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - zExp = aExp + bExp - 0x3FF; - aSig = (aSig | LIT64(0x0010000000000000)) << 10; - bSig = (bSig | LIT64(0x0010000000000000)) << 11; - mul64To128(aSig, bSig, &zSig0, &zSig1); - zSig0 |= (zSig1 != 0); - if (0 <= (int64_t)(zSig0 << 1)) { - zSig0 <<= 1; - --zExp; - } - return roundAndPackFloat64(zSign, zExp, zSig0 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_div(float64 a, float64 b STATUS_PARAM) { - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - uint64_t aSig, bSig, zSig; - uint64_t rem0, rem1; - uint64_t term0, term1; - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - bSign = extractFloat64Sign(b); - zSign = aSign ^ bSign; - if (aExp == 0x7FF) { - if (aSig) - return propagateFloat64NaN(a, b STATUS_VAR); - if (bExp == 0x7FF) { - if (bSig) - return propagateFloat64NaN(a, b STATUS_VAR); - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - return packFloat64(zSign, 0x7FF, 0); - } - if (bExp == 0x7FF) { - if (bSig) - return propagateFloat64NaN(a, b STATUS_VAR); - return packFloat64(zSign, 0, 0); - } - if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - float_raise(float_flag_divbyzero STATUS_VAR); - return packFloat64(zSign, 0x7FF, 0); - } - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) - return packFloat64(zSign, 0, 0); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - zExp = aExp - bExp + 0x3FD; - aSig = (aSig | LIT64(0x0010000000000000)) << 10; - bSig = (bSig | LIT64(0x0010000000000000)) << 11; - if (bSig <= (aSig + aSig)) { - aSig >>= 1; - ++zExp; - } - zSig = estimateDiv128To64(aSig, 0, bSig); - if ((zSig & 0x1FF) <= 2) { - mul64To128(bSig, zSig, &term0, &term1); - sub128(aSig, 0, term0, term1, &rem0, &rem1); - while ((int64_t) rem0 < 0) { - --zSig; - add128(rem0, rem1, 0, bSig, &rem0, &rem1); - } - zSig |= (rem1 != 0); - } - return roundAndPackFloat64(zSign, zExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the double-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_rem(float64 a, float64 b STATUS_PARAM) { - flag aSign, zSign; - int16 aExp, bExp, expDiff; - uint64_t aSig, bSig; - uint64_t q, alternateASig; - int64_t sigMean; - - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - if (aExp == 0x7FF) { - if (aSig || ((bExp == 0x7FF) && bSig)) { - return propagateFloat64NaN(a, b STATUS_VAR); - } - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - if (bExp == 0x7FF) { - if (bSig) - return propagateFloat64NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) { - if (bSig == 0) { - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) - return a; - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - expDiff = aExp - bExp; - aSig = (aSig | LIT64(0x0010000000000000)) << 11; - bSig = (bSig | LIT64(0x0010000000000000)) << 11; - if (expDiff < 0) { - if (expDiff < -1) - return a; - aSig >>= 1; - } - q = (bSig <= aSig); - if (q) - aSig -= bSig; - expDiff -= 64; - while (0 < expDiff) { - q = estimateDiv128To64(aSig, 0, bSig); - q = (2 < q) ? q - 2 : 0; - aSig = -((bSig >> 2) * q); - expDiff -= 62; - } - expDiff += 64; - if (0 < expDiff) { - q = estimateDiv128To64(aSig, 0, bSig); - q = (2 < q) ? q - 2 : 0; - q >>= 64 - expDiff; - bSig >>= 2; - aSig = ((aSig >> 1) << (expDiff - 1)) - bSig * q; - } else { - aSig >>= 2; - bSig >>= 2; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while (0 <= (int64_t) aSig); - sigMean = aSig + alternateASig; - if ((sigMean < 0) || ((sigMean == 0) && (q & 1))) { - aSig = alternateASig; - } - zSign = ((int64_t) aSig < 0); - if (zSign) - aSig = -aSig; - return normalizeRoundAndPackFloat64(aSign ^ zSign, bExp, aSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b' then adding 'c', with no intermediate rounding step after the -| multiplication. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic 754-2008. -| The flags argument allows the caller to select negation of the -| addend, the intermediate product, or the final result. (The difference -| between this and having the caller do a separate negation is that negating -| externally will flip the sign bit on NaNs.) -*----------------------------------------------------------------------------*/ - -float64 float64_muladd(float64 a, float64 b, float64 c, int flags STATUS_PARAM) { - flag aSign, bSign, cSign, zSign; - int aExp, bExp, cExp, pExp, zExp, expDiff; - uint64_t aSig, bSig, cSig; - flag pInf, pZero, pSign; - uint64_t pSig0, pSig1, cSig0, cSig1, zSig0, zSig1; - int shiftcount; - flag signflip, infzero; - - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - c = float64_squash_input_denormal(c STATUS_VAR); - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - bSign = extractFloat64Sign(b); - cSig = extractFloat64Frac(c); - cExp = extractFloat64Exp(c); - cSign = extractFloat64Sign(c); - - infzero = ((aExp == 0 && aSig == 0 && bExp == 0x7ff && bSig == 0) || - (aExp == 0x7ff && aSig == 0 && bExp == 0 && bSig == 0)); - - /* It is implementation-defined whether the cases of (0,inf,qnan) - * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN - * they return if they do), so we have to hand this information - * off to the target-specific pick-a-NaN routine. - */ - if (((aExp == 0x7ff) && aSig) || ((bExp == 0x7ff) && bSig) || ((cExp == 0x7ff) && cSig)) { - return propagateFloat64MulAddNaN(a, b, c, infzero STATUS_VAR); - } - - if (infzero) { - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - - if (flags & float_muladd_negate_c) { - cSign ^= 1; - } - - signflip = (flags & float_muladd_negate_result) ? 1 : 0; - - /* Work out the sign and type of the product */ - pSign = aSign ^ bSign; - if (flags & float_muladd_negate_product) { - pSign ^= 1; - } - pInf = (aExp == 0x7ff) || (bExp == 0x7ff); - pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0); - - if (cExp == 0x7ff) { - if (pInf && (pSign ^ cSign)) { - /* addition of opposite-signed infinities => InvalidOperation */ - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - /* Otherwise generate an infinity of the same sign */ - return packFloat64(cSign ^ signflip, 0x7ff, 0); - } - - if (pInf) { - return packFloat64(pSign ^ signflip, 0x7ff, 0); - } - - if (pZero) { - if (cExp == 0) { - if (cSig == 0) { - /* Adding two exact zeroes */ - if (pSign == cSign) { - zSign = pSign; - } else if (STATUS(float_rounding_mode) == float_round_down) { - zSign = 1; - } else { - zSign = 0; - } - return packFloat64(zSign ^ signflip, 0, 0); - } - /* Exact zero plus a denorm */ - if (STATUS(flush_to_zero)) { - float_raise(float_flag_output_denormal STATUS_VAR); - return packFloat64(cSign ^ signflip, 0, 0); - } - } - /* Zero plus something non-zero : just return the something */ - return c ^ ((uint64_t) signflip << 63); - } - - if (aExp == 0) { - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - - /* Calculate the actual result a * b + c */ - - /* Multiply first; this is easy. */ - /* NB: we subtract 0x3fe where float64_mul() subtracts 0x3ff - * because we want the true exponent, not the "one-less-than" - * flavour that roundAndPackFloat64() takes. - */ - pExp = aExp + bExp - 0x3fe; - aSig = (aSig | LIT64(0x0010000000000000)) << 10; - bSig = (bSig | LIT64(0x0010000000000000)) << 11; - mul64To128(aSig, bSig, &pSig0, &pSig1); - if ((int64_t)(pSig0 << 1) >= 0) { - shortShift128Left(pSig0, pSig1, 1, &pSig0, &pSig1); - pExp--; - } - - zSign = pSign ^ signflip; - - /* Now [pSig0:pSig1] is the significand of the multiply, with the explicit - * bit in position 126. - */ - if (cExp == 0) { - if (!cSig) { - /* Throw out the special case of c being an exact zero now */ - shift128RightJamming(pSig0, pSig1, 64, &pSig0, &pSig1); - return roundAndPackFloat64(zSign, pExp - 1, pSig1 STATUS_VAR); - } - normalizeFloat64Subnormal(cSig, &cExp, &cSig); - } - - /* Shift cSig and add the explicit bit so [cSig0:cSig1] is the - * significand of the addend, with the explicit bit in position 126. - */ - cSig0 = cSig << (126 - 64 - 52); - cSig1 = 0; - cSig0 |= LIT64(0x4000000000000000); - expDiff = pExp - cExp; - - if (pSign == cSign) { - /* Addition */ - if (expDiff > 0) { - /* scale c to match p */ - shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1); - zExp = pExp; - } else if (expDiff < 0) { - /* scale p to match c */ - shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1); - zExp = cExp; - } else { - /* no scaling needed */ - zExp = cExp; - } - /* Add significands and make sure explicit bit ends up in posn 126 */ - add128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - if ((int64_t) zSig0 < 0) { - shift128RightJamming(zSig0, zSig1, 1, &zSig0, &zSig1); - } else { - zExp--; - } - shift128RightJamming(zSig0, zSig1, 64, &zSig0, &zSig1); - return roundAndPackFloat64(zSign, zExp, zSig1 STATUS_VAR); - } else { - /* Subtraction */ - if (expDiff > 0) { - shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1); - sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - zExp = pExp; - } else if (expDiff < 0) { - shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1); - sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1); - zExp = cExp; - zSign ^= 1; - } else { - zExp = pExp; - if (lt128(cSig0, cSig1, pSig0, pSig1)) { - sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - } else if (lt128(pSig0, pSig1, cSig0, cSig1)) { - sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1); - zSign ^= 1; - } else { - /* Exact zero */ - zSign = signflip; - if (STATUS(float_rounding_mode) == float_round_down) { - zSign ^= 1; - } - return packFloat64(zSign, 0, 0); - } - } - --zExp; - /* Do the equivalent of normalizeRoundAndPackFloat64() but - * starting with the significand in a pair of uint64_t. - */ - if (zSig0) { - shiftcount = countLeadingZeros64(zSig0) - 1; - shortShift128Left(zSig0, zSig1, shiftcount, &zSig0, &zSig1); - if (zSig1) { - zSig0 |= 1; - } - zExp -= shiftcount; - } else { - shiftcount = countLeadingZeros64(zSig1) - 1; - zSig0 = zSig1 << shiftcount; - zExp -= (shiftcount + 64); - } - return roundAndPackFloat64(zSign, zExp, zSig0 STATUS_VAR); - } -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the double-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sqrt(float64 a STATUS_PARAM) { - flag aSign; - int16 aExp, zExp; - uint64_t aSig, zSig, doubleZSig; - uint64_t rem0, rem1, term0, term1; - a = float64_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (aExp == 0x7FF) { - if (aSig) - return propagateFloat64NaN(a, a STATUS_VAR); - if (!aSign) - return a; - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - if (aSign) { - if ((aExp | aSig) == 0) - return a; - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - if (aExp == 0) { - if (aSig == 0) - return float64_zero; - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - zExp = ((aExp - 0x3FF) >> 1) + 0x3FE; - aSig |= LIT64(0x0010000000000000); - zSig = estimateSqrt32(aExp, aSig >> 21); - aSig <<= 9 - (aExp & 1); - zSig = estimateDiv128To64(aSig, 0, zSig << 32) + (zSig << 30); - if ((zSig & 0x1FF) <= 5) { - doubleZSig = zSig << 1; - mul64To128(zSig, zSig, &term0, &term1); - sub128(aSig, 0, term0, term1, &rem0, &rem1); - while ((int64_t) rem0 < 0) { - --zSig; - doubleZSig -= 2; - add128(rem0, rem1, zSig >> 63, doubleZSig | 1, &rem0, &rem1); - } - zSig |= ((rem0 | rem1) != 0); - } - return roundAndPackFloat64(0, zExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the binary log of the double-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -float64 float64_log2(float64 a STATUS_PARAM) { - flag aSign, zSign; - int16 aExp; - uint64_t aSig, aSig0, aSig1, zSig, i; - a = float64_squash_input_denormal(a STATUS_VAR); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - - if (aExp == 0) { - if (aSig == 0) - return packFloat64(1, 0x7FF, 0); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - if (aSign) { - float_raise(float_flag_invalid STATUS_VAR); - return float64_default_nan; - } - if (aExp == 0x7FF) { - if (aSig) - return propagateFloat64NaN(a, float64_zero STATUS_VAR); - return a; - } - - aExp -= 0x3FF; - aSig |= LIT64(0x0010000000000000); - zSign = aExp < 0; - zSig = (uint64_t) aExp << 52; - for (i = 1LL << 51; i > 0; i >>= 1) { - mul64To128(aSig, aSig, &aSig0, &aSig1); - aSig = (aSig0 << 12) | (aSig1 >> 52); - if (aSig & LIT64(0x0020000000000000)) { - aSig >>= 1; - zSig |= i; - } - } - - if (zSign) - zSig = -zSig; - return normalizeRoundAndPackFloat64(zSign, 0x408, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The invalid exception is raised -| if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_eq(float64 a, float64 b STATUS_PARAM) { - uint64_t av, bv; - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat64Exp(a) == 0x7FF) && extractFloat64Frac(a)) || - ((extractFloat64Exp(b) == 0x7FF) && extractFloat64Frac(b))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - av = float64_val(a); - bv = float64_val(b); - return (av == bv) || ((uint64_t)((av | bv) << 1) == 0); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. The invalid -| exception is raised if either operand is a NaN. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_le(float64 a, float64 b STATUS_PARAM) { - flag aSign, bSign; - uint64_t av, bv; - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat64Exp(a) == 0x7FF) && extractFloat64Frac(a)) || - ((extractFloat64Exp(b) == 0x7FF) && extractFloat64Frac(b))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - aSign = extractFloat64Sign(a); - bSign = extractFloat64Sign(b); - av = float64_val(a); - bv = float64_val(b); - if (aSign != bSign) - return aSign || ((uint64_t)((av | bv) << 1) == 0); - return (av == bv) || (aSign ^ (av < bv)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. The comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_lt(float64 a, float64 b STATUS_PARAM) { - flag aSign, bSign; - uint64_t av, bv; - - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - if (((extractFloat64Exp(a) == 0x7FF) && extractFloat64Frac(a)) || - ((extractFloat64Exp(b) == 0x7FF) && extractFloat64Frac(b))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - aSign = extractFloat64Sign(a); - bSign = extractFloat64Sign(b); - av = float64_val(a); - bv = float64_val(b); - if (aSign != bSign) - return aSign && ((uint64_t)((av | bv) << 1) != 0); - return (av != bv) && (aSign ^ (av < bv)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. The invalid exception is raised if either -| operand is a NaN. The comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_unordered(float64 a, float64 b STATUS_PARAM) { - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat64Exp(a) == 0x7FF) && extractFloat64Frac(a)) || - ((extractFloat64Exp(b) == 0x7FF) && extractFloat64Frac(b))) { - float_raise(float_flag_invalid STATUS_VAR); - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception.The comparison is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_eq_quiet(float64 a, float64 b STATUS_PARAM) { - uint64_t av, bv; - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat64Exp(a) == 0x7FF) && extractFloat64Frac(a)) || - ((extractFloat64Exp(b) == 0x7FF) && extractFloat64Frac(b))) { - if (float64_is_signaling_nan(a) || float64_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - av = float64_val(a); - bv = float64_val(b); - return (av == bv) || ((uint64_t)((av | bv) << 1) == 0); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_le_quiet(float64 a, float64 b STATUS_PARAM) { - flag aSign, bSign; - uint64_t av, bv; - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat64Exp(a) == 0x7FF) && extractFloat64Frac(a)) || - ((extractFloat64Exp(b) == 0x7FF) && extractFloat64Frac(b))) { - if (float64_is_signaling_nan(a) || float64_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - aSign = extractFloat64Sign(a); - bSign = extractFloat64Sign(b); - av = float64_val(a); - bv = float64_val(b); - if (aSign != bSign) - return aSign || ((uint64_t)((av | bv) << 1) == 0); - return (av == bv) || (aSign ^ (av < bv)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_lt_quiet(float64 a, float64 b STATUS_PARAM) { - flag aSign, bSign; - uint64_t av, bv; - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat64Exp(a) == 0x7FF) && extractFloat64Frac(a)) || - ((extractFloat64Exp(b) == 0x7FF) && extractFloat64Frac(b))) { - if (float64_is_signaling_nan(a) || float64_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - aSign = extractFloat64Sign(a); - bSign = extractFloat64Sign(b); - av = float64_val(a); - bv = float64_val(b); - if (aSign != bSign) - return aSign && ((uint64_t)((av | bv) << 1) != 0); - return (av != bv) && (aSign ^ (av < bv)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_unordered_quiet(float64 a, float64 b STATUS_PARAM) { - a = float64_squash_input_denormal(a STATUS_VAR); - b = float64_squash_input_denormal(b STATUS_VAR); - - if (((extractFloat64Exp(a) == 0x7FF) && extractFloat64Frac(a)) || - ((extractFloat64Exp(b) == 0x7FF) && extractFloat64Frac(b))) { - if (float64_is_signaling_nan(a) || float64_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic---which means in particular that the conversion -| is rounded according to the current rounding mode. If `a' is a NaN, the -| largest positive integer is returned. Otherwise, if the conversion -| overflows, the largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32(floatx80 a STATUS_PARAM) { - flag aSign; - int32 aExp, shiftCount; - uint64_t aSig; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - if ((aExp == 0x7FFF) && (uint64_t)(aSig << 1)) - aSign = 0; - shiftCount = 0x4037 - aExp; - if (shiftCount <= 0) - shiftCount = 1; - shift64RightJamming(aSig, shiftCount, &aSig); - return roundAndPackInt32(aSign, aSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic, except that the conversion is always rounded -| toward zero. If `a' is a NaN, the largest positive integer is returned. -| Otherwise, if the conversion overflows, the largest integer with the same -| sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32_round_to_zero(floatx80 a STATUS_PARAM) { - flag aSign; - int32 aExp, shiftCount; - uint64_t aSig, savedASig; - int32_t z; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - if (0x401E < aExp) { - if ((aExp == 0x7FFF) && (uint64_t)(aSig << 1)) - aSign = 0; - goto invalid; - } else if (aExp < 0x3FFF) { - if (aExp || aSig) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return 0; - } - shiftCount = 0x403E - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if (aSign) - z = -z; - if ((z < 0) ^ aSign) { - invalid: - float_raise(float_flag_invalid STATUS_VAR); - return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF; - } - if ((aSig << shiftCount) != savedASig) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 64-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic---which means in particular that the conversion -| is rounded according to the current rounding mode. If `a' is a NaN, -| the largest positive integer is returned. Otherwise, if the conversion -| overflows, the largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 floatx80_to_int64(floatx80 a STATUS_PARAM) { - flag aSign; - int32 aExp, shiftCount; - uint64_t aSig, aSigExtra; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - shiftCount = 0x403E - aExp; - if (shiftCount <= 0) { - if (shiftCount) { - float_raise(float_flag_invalid STATUS_VAR); - if (!aSign || ((aExp == 0x7FFF) && (aSig != LIT64(0x8000000000000000)))) { - return LIT64(0x7FFFFFFFFFFFFFFF); - } - return (int64_t) LIT64(0x8000000000000000); - } - aSigExtra = 0; - } else { - shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra); - } - return roundAndPackInt64(aSign, aSig, aSigExtra STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 64-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic, except that the conversion is always rounded -| toward zero. If `a' is a NaN, the largest positive integer is returned. -| Otherwise, if the conversion overflows, the largest integer with the same -| sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 floatx80_to_int64_round_to_zero(floatx80 a STATUS_PARAM) { - flag aSign; - int32 aExp, shiftCount; - uint64_t aSig; - int64 z; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - shiftCount = aExp - 0x403E; - if (0 <= shiftCount) { - aSig &= LIT64(0x7FFFFFFFFFFFFFFF); - if ((a.high != 0xC03E) || aSig) { - float_raise(float_flag_invalid STATUS_VAR); - if (!aSign || ((aExp == 0x7FFF) && aSig)) { - return LIT64(0x7FFFFFFFFFFFFFFF); - } - } - return (int64_t) LIT64(0x8000000000000000); - } else if (aExp < 0x3FFF) { - if (aExp | aSig) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return 0; - } - z = aSig >> (-shiftCount); - if ((uint64_t)(aSig << (shiftCount & 63))) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - if (aSign) - z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 floatx80_to_float32(floatx80 a STATUS_PARAM) { - flag aSign; - int32 aExp; - uint64_t aSig; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - if (aExp == 0x7FFF) { - if ((uint64_t)(aSig << 1)) { - return commonNaNToFloat32(floatx80ToCommonNaN(a STATUS_VAR) STATUS_VAR); - } - return packFloat32(aSign, 0xFF, 0); - } - shift64RightJamming(aSig, 33, &aSig); - if (aExp || aSig) - aExp -= 0x3F81; - return roundAndPackFloat32(aSign, aExp, aSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 floatx80_to_float64(floatx80 a STATUS_PARAM) { - flag aSign; - int32 aExp; - uint64_t aSig, zSig; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - if (aExp == 0x7FFF) { - if ((uint64_t)(aSig << 1)) { - return commonNaNToFloat64(floatx80ToCommonNaN(a STATUS_VAR) STATUS_VAR); - } - return packFloat64(aSign, 0x7FF, 0); - } - shift64RightJamming(aSig, 1, &zSig); - if (aExp || aSig) - aExp -= 0x3C01; - return roundAndPackFloat64(aSign, aExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the quadruple-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 floatx80_to_float128(floatx80 a STATUS_PARAM) { - flag aSign; - int16 aExp; - uint64_t aSig, zSig0, zSig1; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - if ((aExp == 0x7FFF) && (uint64_t)(aSig << 1)) { - return commonNaNToFloat128(floatx80ToCommonNaN(a STATUS_VAR) STATUS_VAR); - } - shift128Right(aSig << 1, 0, 16, &zSig0, &zSig1); - return packFloat128(aSign, aExp, zSig0, zSig1); -} - -/*---------------------------------------------------------------------------- -| Rounds the extended double-precision floating-point value `a' to an integer, -| and returns the result as an extended quadruple-precision floating-point -| value. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_round_to_int(floatx80 a STATUS_PARAM) { - flag aSign; - int32 aExp; - uint64_t lastBitMask, roundBitsMask; - int8 roundingMode; - floatx80 z; - - aExp = extractFloatx80Exp(a); - if (0x403E <= aExp) { - if ((aExp == 0x7FFF) && (uint64_t)(extractFloatx80Frac(a) << 1)) { - return propagateFloatx80NaN(a, a STATUS_VAR); - } - return a; - } - if (aExp < 0x3FFF) { - if ((aExp == 0) && ((uint64_t)(extractFloatx80Frac(a) << 1) == 0)) { - return a; - } - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - aSign = extractFloatx80Sign(a); - switch (STATUS(float_rounding_mode)) { - case float_round_nearest_even: - if ((aExp == 0x3FFE) && (uint64_t)(extractFloatx80Frac(a) << 1)) { - return packFloatx80(aSign, 0x3FFF, LIT64(0x8000000000000000)); - } - break; - case float_round_down: - return aSign ? packFloatx80(1, 0x3FFF, LIT64(0x8000000000000000)) : packFloatx80(0, 0, 0); - case float_round_up: - return aSign ? packFloatx80(1, 0, 0) : packFloatx80(0, 0x3FFF, LIT64(0x8000000000000000)); - } - return packFloatx80(aSign, 0, 0); - } - lastBitMask = 1; - lastBitMask <<= 0x403E - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = STATUS(float_rounding_mode); - if (roundingMode == float_round_nearest_even) { - z.low += lastBitMask >> 1; - if ((z.low & roundBitsMask) == 0) - z.low &= ~lastBitMask; - } else if (roundingMode != float_round_to_zero) { - if (extractFloatx80Sign(z) ^ (roundingMode == float_round_up)) { - z.low += roundBitsMask; - } - } - z.low &= ~roundBitsMask; - if (z.low == 0) { - ++z.high; - z.low = LIT64(0x8000000000000000); - } - if (z.low != a.low) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the extended double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, flag zSign STATUS_PARAM) { - int32 aExp, bExp, zExp; - uint64_t aSig, bSig, zSig0, zSig1; - int32 expDiff; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - expDiff = aExp - bExp; - if (0 < expDiff) { - if (aExp == 0x7FFF) { - if ((uint64_t)(aSig << 1)) - return propagateFloatx80NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) - --expDiff; - shift64ExtraRightJamming(bSig, 0, expDiff, &bSig, &zSig1); - zExp = aExp; - } else if (expDiff < 0) { - if (bExp == 0x7FFF) { - if ((uint64_t)(bSig << 1)) - return propagateFloatx80NaN(a, b STATUS_VAR); - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) - ++expDiff; - shift64ExtraRightJamming(aSig, 0, -expDiff, &aSig, &zSig1); - zExp = bExp; - } else { - if (aExp == 0x7FFF) { - if ((uint64_t)((aSig | bSig) << 1)) { - return propagateFloatx80NaN(a, b STATUS_VAR); - } - return a; - } - zSig1 = 0; - zSig0 = aSig + bSig; - if (aExp == 0) { - normalizeFloatx80Subnormal(zSig0, &zExp, &zSig0); - goto roundAndPack; - } - zExp = aExp; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ((int64_t) zSig0 < 0) - goto roundAndPack; -shiftRight1: - shift64ExtraRightJamming(zSig0, zSig1, 1, &zSig0, &zSig1); - zSig0 |= LIT64(0x8000000000000000); - ++zExp; -roundAndPack: - return roundAndPackFloatx80(STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the extended -| double-precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, flag zSign STATUS_PARAM) { - int32 aExp, bExp, zExp; - uint64_t aSig, bSig, zSig0, zSig1; - int32 expDiff; - floatx80 z; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - expDiff = aExp - bExp; - if (0 < expDiff) - goto aExpBigger; - if (expDiff < 0) - goto bExpBigger; - if (aExp == 0x7FFF) { - if ((uint64_t)((aSig | bSig) << 1)) { - return propagateFloatx80NaN(a, b STATUS_VAR); - } - float_raise(float_flag_invalid STATUS_VAR); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if (aExp == 0) { - aExp = 1; - bExp = 1; - } - zSig1 = 0; - if (bSig < aSig) - goto aBigger; - if (aSig < bSig) - goto bBigger; - return packFloatx80(STATUS(float_rounding_mode) == float_round_down, 0, 0); -bExpBigger: - if (bExp == 0x7FFF) { - if ((uint64_t)(bSig << 1)) - return propagateFloatx80NaN(a, b STATUS_VAR); - return packFloatx80(zSign ^ 1, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) - ++expDiff; - shift128RightJamming(aSig, 0, -expDiff, &aSig, &zSig1); -bBigger: - sub128(bSig, 0, aSig, zSig1, &zSig0, &zSig1); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; -aExpBigger: - if (aExp == 0x7FFF) { - if ((uint64_t)(aSig << 1)) - return propagateFloatx80NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) - --expDiff; - shift128RightJamming(bSig, 0, expDiff, &bSig, &zSig1); -aBigger: - sub128(aSig, 0, bSig, zSig1, &zSig0, &zSig1); - zExp = aExp; -normalizeRoundAndPack: - return normalizeRoundAndPackFloatx80(STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the extended double-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_add(floatx80 a, floatx80 b STATUS_PARAM) { - flag aSign, bSign; - - aSign = extractFloatx80Sign(a); - bSign = extractFloatx80Sign(b); - if (aSign == bSign) { - return addFloatx80Sigs(a, b, aSign STATUS_VAR); - } else { - return subFloatx80Sigs(a, b, aSign STATUS_VAR); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sub(floatx80 a, floatx80 b STATUS_PARAM) { - flag aSign, bSign; - - aSign = extractFloatx80Sign(a); - bSign = extractFloatx80Sign(b); - if (aSign == bSign) { - return subFloatx80Sigs(a, b, aSign STATUS_VAR); - } else { - return addFloatx80Sigs(a, b, aSign STATUS_VAR); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_mul(floatx80 a, floatx80 b STATUS_PARAM) { - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - uint64_t aSig, bSig, zSig0, zSig1; - floatx80 z; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); - zSign = aSign ^ bSign; - if (aExp == 0x7FFF) { - if ((uint64_t)(aSig << 1) || ((bExp == 0x7FFF) && (uint64_t)(bSig << 1))) { - return propagateFloatx80NaN(a, b STATUS_VAR); - } - if ((bExp | bSig) == 0) - goto invalid; - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (bExp == 0x7FFF) { - if ((uint64_t)(bSig << 1)) - return propagateFloatx80NaN(a, b STATUS_VAR); - if ((aExp | aSig) == 0) { - invalid: - float_raise(float_flag_invalid STATUS_VAR); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) - return packFloatx80(zSign, 0, 0); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) - return packFloatx80(zSign, 0, 0); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128(aSig, bSig, &zSig0, &zSig1); - if (0 < (int64_t) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --zExp; - } - return roundAndPackFloatx80(STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the extended double-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_div(floatx80 a, floatx80 b STATUS_PARAM) { - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - uint64_t aSig, bSig, zSig0, zSig1; - uint64_t rem0, rem1, rem2, term0, term1, term2; - floatx80 z; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); - zSign = aSign ^ bSign; - if (aExp == 0x7FFF) { - if ((uint64_t)(aSig << 1)) - return propagateFloatx80NaN(a, b STATUS_VAR); - if (bExp == 0x7FFF) { - if ((uint64_t)(bSig << 1)) - return propagateFloatx80NaN(a, b STATUS_VAR); - goto invalid; - } - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (bExp == 0x7FFF) { - if ((uint64_t)(bSig << 1)) - return propagateFloatx80NaN(a, b STATUS_VAR); - return packFloatx80(zSign, 0, 0); - } - if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - invalid: - float_raise(float_flag_invalid STATUS_VAR); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - float_raise(float_flag_divbyzero STATUS_VAR); - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) - return packFloatx80(zSign, 0, 0); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if (bSig <= aSig) { - shift128Right(aSig, 0, 1, &aSig, &rem1); - ++zExp; - } - zSig0 = estimateDiv128To64(aSig, rem1, bSig); - mul64To128(bSig, zSig0, &term0, &term1); - sub128(aSig, rem1, term0, term1, &rem0, &rem1); - while ((int64_t) rem0 < 0) { - --zSig0; - add128(rem0, rem1, 0, bSig, &rem0, &rem1); - } - zSig1 = estimateDiv128To64(rem1, 0, bSig); - if ((uint64_t)(zSig1 << 1) <= 8) { - mul64To128(bSig, zSig1, &term1, &term2); - sub128(rem1, 0, term1, term2, &rem1, &rem2); - while ((int64_t) rem1 < 0) { - --zSig1; - add128(rem1, rem2, 0, bSig, &rem1, &rem2); - } - zSig1 |= ((rem1 | rem2) != 0); - } - return roundAndPackFloatx80(STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the extended double-precision floating-point value -| `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_rem(floatx80 a, floatx80 b STATUS_PARAM) { - flag aSign, zSign; - int32 aExp, bExp, expDiff; - uint64_t aSig0, aSig1, bSig; - uint64_t q, term0, term1, alternateASig0, alternateASig1; - floatx80 z; - - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - if (aExp == 0x7FFF) { - if ((uint64_t)(aSig0 << 1) || ((bExp == 0x7FFF) && (uint64_t)(bSig << 1))) { - return propagateFloatx80NaN(a, b STATUS_VAR); - } - goto invalid; - } - if (bExp == 0x7FFF) { - if ((uint64_t)(bSig << 1)) - return propagateFloatx80NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) { - if (bSig == 0) { - invalid: - float_raise(float_flag_invalid STATUS_VAR); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if ((uint64_t)(aSig0 << 1) == 0) - return a; - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - bSig |= LIT64(0x8000000000000000); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if (expDiff < 0) { - if (expDiff < -1) - return a; - shift128Right(aSig0, 0, 1, &aSig0, &aSig1); - expDiff = 0; - } - q = (bSig <= aSig0); - if (q) - aSig0 -= bSig; - expDiff -= 64; - while (0 < expDiff) { - q = estimateDiv128To64(aSig0, aSig1, bSig); - q = (2 < q) ? q - 2 : 0; - mul64To128(bSig, q, &term0, &term1); - sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1); - shortShift128Left(aSig0, aSig1, 62, &aSig0, &aSig1); - expDiff -= 62; - } - expDiff += 64; - if (0 < expDiff) { - q = estimateDiv128To64(aSig0, aSig1, bSig); - q = (2 < q) ? q - 2 : 0; - q >>= 64 - expDiff; - mul64To128(bSig, q << (64 - expDiff), &term0, &term1); - sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1); - shortShift128Left(0, bSig, 64 - expDiff, &term0, &term1); - while (le128(term0, term1, aSig0, aSig1)) { - ++q; - sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1); - } - } else { - term1 = 0; - term0 = bSig; - } - sub128(term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1); - if (lt128(alternateASig0, alternateASig1, aSig0, aSig1) || - (eq128(alternateASig0, alternateASig1, aSig0, aSig1) && (q & 1))) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = !zSign; - } - return normalizeRoundAndPackFloatx80(80, zSign, bExp + expDiff, aSig0, aSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sqrt(floatx80 a STATUS_PARAM) { - flag aSign; - int32 aExp, zExp; - uint64_t aSig0, aSig1, zSig0, zSig1, doubleZSig0; - uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3; - floatx80 z; - - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - if (aExp == 0x7FFF) { - if ((uint64_t)(aSig0 << 1)) - return propagateFloatx80NaN(a, a STATUS_VAR); - if (!aSign) - return a; - goto invalid; - } - if (aSign) { - if ((aExp | aSig0) == 0) - return a; - invalid: - float_raise(float_flag_invalid STATUS_VAR); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if (aExp == 0) { - if (aSig0 == 0) - return packFloatx80(0, 0, 0); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - zExp = ((aExp - 0x3FFF) >> 1) + 0x3FFF; - zSig0 = estimateSqrt32(aExp, aSig0 >> 32); - shift128Right(aSig0, 0, 2 + (aExp & 1), &aSig0, &aSig1); - zSig0 = estimateDiv128To64(aSig0, aSig1, zSig0 << 32) + (zSig0 << 30); - doubleZSig0 = zSig0 << 1; - mul64To128(zSig0, zSig0, &term0, &term1); - sub128(aSig0, aSig1, term0, term1, &rem0, &rem1); - while ((int64_t) rem0 < 0) { - --zSig0; - doubleZSig0 -= 2; - add128(rem0, rem1, zSig0 >> 63, doubleZSig0 | 1, &rem0, &rem1); - } - zSig1 = estimateDiv128To64(rem1, 0, doubleZSig0); - if ((zSig1 & LIT64(0x3FFFFFFFFFFFFFFF)) <= 5) { - if (zSig1 == 0) - zSig1 = 1; - mul64To128(doubleZSig0, zSig1, &term1, &term2); - sub128(rem1, 0, term1, term2, &rem1, &rem2); - mul64To128(zSig1, zSig1, &term2, &term3); - sub192(rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3); - while ((int64_t) rem1 < 0) { - --zSig1; - shortShift128Left(0, zSig1, 1, &term2, &term3); - term3 |= 1; - term2 |= doubleZSig0; - add192(rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3); - } - zSig1 |= ((rem1 | rem2 | rem3) != 0); - } - shortShift128Left(0, zSig1, 1, &zSig0, &zSig1); - zSig0 |= doubleZSig0; - return roundAndPackFloatx80(STATUS(floatx80_rounding_precision), 0, zExp, zSig0, zSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is equal -| to the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_eq(floatx80 a, floatx80 b STATUS_PARAM) { - - if (((extractFloatx80Exp(a) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(a) << 1)) || - ((extractFloatx80Exp(b) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(b) << 1))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - return (a.low == b.low) && ((a.high == b.high) || ((a.low == 0) && ((uint16_t)((a.high | b.high) << 1) == 0))); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than or equal to the corresponding value `b', and 0 otherwise. The -| invalid exception is raised if either operand is a NaN. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_le(floatx80 a, floatx80 b STATUS_PARAM) { - flag aSign, bSign; - - if (((extractFloatx80Exp(a) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(a) << 1)) || - ((extractFloatx80Exp(b) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(b) << 1))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - aSign = extractFloatx80Sign(a); - bSign = extractFloatx80Sign(b); - if (aSign != bSign) { - return aSign || ((((uint16_t)((a.high | b.high) << 1)) | a.low | b.low) == 0); - } - return aSign ? le128(b.high, b.low, a.high, a.low) : le128(a.high, a.low, b.high, b.low); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than the corresponding value `b', and 0 otherwise. The invalid -| exception is raised if either operand is a NaN. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_lt(floatx80 a, floatx80 b STATUS_PARAM) { - flag aSign, bSign; - - if (((extractFloatx80Exp(a) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(a) << 1)) || - ((extractFloatx80Exp(b) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(b) << 1))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - aSign = extractFloatx80Sign(a); - bSign = extractFloatx80Sign(b); - if (aSign != bSign) { - return aSign && ((((uint16_t)((a.high | b.high) << 1)) | a.low | b.low) != 0); - } - return aSign ? lt128(b.high, b.low, a.high, a.low) : lt128(a.high, a.low, b.high, b.low); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point values `a' and `b' -| cannot be compared, and 0 otherwise. The invalid exception is raised if -| either operand is a NaN. The comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -int floatx80_unordered(floatx80 a, floatx80 b STATUS_PARAM) { - if (((extractFloatx80Exp(a) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(a) << 1)) || - ((extractFloatx80Exp(b) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(b) << 1))) { - float_raise(float_flag_invalid STATUS_VAR); - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. The comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_eq_quiet(floatx80 a, floatx80 b STATUS_PARAM) { - - if (((extractFloatx80Exp(a) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(a) << 1)) || - ((extractFloatx80Exp(b) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(b) << 1))) { - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - return (a.low == b.low) && ((a.high == b.high) || ((a.low == 0) && ((uint16_t)((a.high | b.high) << 1) == 0))); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs -| do not cause an exception. Otherwise, the comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_le_quiet(floatx80 a, floatx80 b STATUS_PARAM) { - flag aSign, bSign; - - if (((extractFloatx80Exp(a) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(a) << 1)) || - ((extractFloatx80Exp(b) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(b) << 1))) { - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - aSign = extractFloatx80Sign(a); - bSign = extractFloatx80Sign(b); - if (aSign != bSign) { - return aSign || ((((uint16_t)((a.high | b.high) << 1)) | a.low | b.low) == 0); - } - return aSign ? le128(b.high, b.low, a.high, a.low) : le128(a.high, a.low, b.high, b.low); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause -| an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_lt_quiet(floatx80 a, floatx80 b STATUS_PARAM) { - flag aSign, bSign; - - if (((extractFloatx80Exp(a) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(a) << 1)) || - ((extractFloatx80Exp(b) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(b) << 1))) { - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - aSign = extractFloatx80Sign(a); - bSign = extractFloatx80Sign(b); - if (aSign != bSign) { - return aSign && ((((uint16_t)((a.high | b.high) << 1)) | a.low | b.low) != 0); - } - return aSign ? lt128(b.high, b.low, a.high, a.low) : lt128(a.high, a.low, b.high, b.low); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point values `a' and `b' -| cannot be compared, and 0 otherwise. Quiet NaNs do not cause an exception. -| The comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -int floatx80_unordered_quiet(floatx80 a, floatx80 b STATUS_PARAM) { - if (((extractFloatx80Exp(a) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(a) << 1)) || - ((extractFloatx80Exp(b) == 0x7FFF) && (uint64_t)(extractFloatx80Frac(b) << 1))) { - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32(float128 a STATUS_PARAM) { - flag aSign; - int32 aExp, shiftCount; - uint64_t aSig0, aSig1; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - if ((aExp == 0x7FFF) && (aSig0 | aSig1)) - aSign = 0; - if (aExp) - aSig0 |= LIT64(0x0001000000000000); - aSig0 |= (aSig1 != 0); - shiftCount = 0x4028 - aExp; - if (0 < shiftCount) - shift64RightJamming(aSig0, shiftCount, &aSig0); - return roundAndPackInt32(aSign, aSig0 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32_round_to_zero(float128 a STATUS_PARAM) { - flag aSign; - int32 aExp, shiftCount; - uint64_t aSig0, aSig1, savedASig; - int32_t z; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - aSig0 |= (aSig1 != 0); - if (0x401E < aExp) { - if ((aExp == 0x7FFF) && aSig0) - aSign = 0; - goto invalid; - } else if (aExp < 0x3FFF) { - if (aExp || aSig0) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - return 0; - } - aSig0 |= LIT64(0x0001000000000000); - shiftCount = 0x402F - aExp; - savedASig = aSig0; - aSig0 >>= shiftCount; - z = aSig0; - if (aSign) - z = -z; - if ((z < 0) ^ aSign) { - invalid: - float_raise(float_flag_invalid STATUS_VAR); - return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF; - } - if ((aSig0 << shiftCount) != savedASig) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 64-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 float128_to_int64(float128 a STATUS_PARAM) { - flag aSign; - int32 aExp, shiftCount; - uint64_t aSig0, aSig1; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - if (aExp) - aSig0 |= LIT64(0x0001000000000000); - shiftCount = 0x402F - aExp; - if (shiftCount <= 0) { - if (0x403E < aExp) { - float_raise(float_flag_invalid STATUS_VAR); - if (!aSign || ((aExp == 0x7FFF) && (aSig1 || (aSig0 != LIT64(0x0001000000000000))))) { - return LIT64(0x7FFFFFFFFFFFFFFF); - } - return (int64_t) LIT64(0x8000000000000000); - } - shortShift128Left(aSig0, aSig1, -shiftCount, &aSig0, &aSig1); - } else { - shift64ExtraRightJamming(aSig0, aSig1, shiftCount, &aSig0, &aSig1); - } - return roundAndPackInt64(aSign, aSig0, aSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 64-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64 float128_to_int64_round_to_zero(float128 a STATUS_PARAM) { - flag aSign; - int32 aExp, shiftCount; - uint64_t aSig0, aSig1; - int64 z; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - if (aExp) - aSig0 |= LIT64(0x0001000000000000); - shiftCount = aExp - 0x402F; - if (0 < shiftCount) { - if (0x403E <= aExp) { - aSig0 &= LIT64(0x0000FFFFFFFFFFFF); - if ((a.high == LIT64(0xC03E000000000000)) && (aSig1 < LIT64(0x0002000000000000))) { - if (aSig1) - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } else { - float_raise(float_flag_invalid STATUS_VAR); - if (!aSign || ((aExp == 0x7FFF) && (aSig0 | aSig1))) { - return LIT64(0x7FFFFFFFFFFFFFFF); - } - } - return (int64_t) LIT64(0x8000000000000000); - } - z = (aSig0 << shiftCount) | (aSig1 >> ((-shiftCount) & 63)); - if ((uint64_t)(aSig1 << shiftCount)) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - } else { - if (aExp < 0x3FFF) { - if (aExp | aSig0 | aSig1) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - return 0; - } - z = aSig0 >> (-shiftCount); - if (aSig1 || (shiftCount && (uint64_t)(aSig0 << (shiftCount & 63)))) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - } - if (aSign) - z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the single-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float128_to_float32(float128 a STATUS_PARAM) { - flag aSign; - int32 aExp; - uint64_t aSig0, aSig1; - uint32_t zSig; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) { - return commonNaNToFloat32(float128ToCommonNaN(a STATUS_VAR) STATUS_VAR); - } - return packFloat32(aSign, 0xFF, 0); - } - aSig0 |= (aSig1 != 0); - shift64RightJamming(aSig0, 18, &aSig0); - zSig = aSig0; - if (aExp || zSig) { - zSig |= 0x40000000; - aExp -= 0x3F81; - } - return roundAndPackFloat32(aSign, aExp, zSig STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float128_to_float64(float128 a STATUS_PARAM) { - flag aSign; - int32 aExp; - uint64_t aSig0, aSig1; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) { - return commonNaNToFloat64(float128ToCommonNaN(a STATUS_VAR) STATUS_VAR); - } - return packFloat64(aSign, 0x7FF, 0); - } - shortShift128Left(aSig0, aSig1, 14, &aSig0, &aSig1); - aSig0 |= (aSig1 != 0); - if (aExp || aSig0) { - aSig0 |= LIT64(0x4000000000000000); - aExp -= 0x3C01; - } - return roundAndPackFloat64(aSign, aExp, aSig0 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `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 float128_to_floatx80(float128 a STATUS_PARAM) { - flag aSign; - int32 aExp; - uint64_t aSig0, aSig1; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) { - return commonNaNToFloatx80(float128ToCommonNaN(a STATUS_VAR) STATUS_VAR); - } - return packFloatx80(aSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) - return packFloatx80(aSign, 0, 0); - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } else { - aSig0 |= LIT64(0x0001000000000000); - } - shortShift128Left(aSig0, aSig1, 15, &aSig0, &aSig1); - return roundAndPackFloatx80(80, aSign, aExp, aSig0, aSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Rounds the quadruple-precision floating-point value `a' to an integer, and -| returns the result as a quadruple-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_round_to_int(float128 a STATUS_PARAM) { - flag aSign; - int32 aExp; - uint64_t lastBitMask, roundBitsMask; - int8 roundingMode; - float128 z; - - aExp = extractFloat128Exp(a); - if (0x402F <= aExp) { - if (0x406F <= aExp) { - if ((aExp == 0x7FFF) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) { - return propagateFloat128NaN(a, a STATUS_VAR); - } - return a; - } - lastBitMask = 1; - lastBitMask = (lastBitMask << (0x406E - aExp)) << 1; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = STATUS(float_rounding_mode); - if (roundingMode == float_round_nearest_even) { - if (lastBitMask) { - add128(z.high, z.low, 0, lastBitMask >> 1, &z.high, &z.low); - if ((z.low & roundBitsMask) == 0) - z.low &= ~lastBitMask; - } else { - if ((int64_t) z.low < 0) { - ++z.high; - if ((uint64_t)(z.low << 1) == 0) - z.high &= ~1; - } - } - } else if (roundingMode != float_round_to_zero) { - if (extractFloat128Sign(z) ^ (roundingMode == float_round_up)) { - add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); - } - } - z.low &= ~roundBitsMask; - } else { - if (aExp < 0x3FFF) { - if ((((uint64_t)(a.high << 1)) | a.low) == 0) - return a; - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - aSign = extractFloat128Sign(a); - switch (STATUS(float_rounding_mode)) { - case float_round_nearest_even: - if ((aExp == 0x3FFE) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) { - return packFloat128(aSign, 0x3FFF, 0, 0); - } - break; - case float_round_down: - return aSign ? packFloat128(1, 0x3FFF, 0, 0) : packFloat128(0, 0, 0, 0); - case float_round_up: - return aSign ? packFloat128(1, 0, 0, 0) : packFloat128(0, 0x3FFF, 0, 0); - } - return packFloat128(aSign, 0, 0, 0); - } - lastBitMask = 1; - lastBitMask <<= 0x402F - aExp; - roundBitsMask = lastBitMask - 1; - z.low = 0; - z.high = a.high; - roundingMode = STATUS(float_rounding_mode); - if (roundingMode == float_round_nearest_even) { - z.high += lastBitMask >> 1; - if (((z.high & roundBitsMask) | a.low) == 0) { - z.high &= ~lastBitMask; - } - } else if (roundingMode != float_round_to_zero) { - if (extractFloat128Sign(z) ^ (roundingMode == float_round_up)) { - z.high |= (a.low != 0); - z.high += roundBitsMask; - } - } - z.high &= ~roundBitsMask; - } - if ((z.low != a.low) || (z.high != a.high)) { - STATUS_W(float_exception_flags, (STATUS(float_exception_flags) | float_flag_inexact)); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs(float128 a, float128 b, flag zSign STATUS_PARAM) { - int32 aExp, bExp, zExp; - uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - int32 expDiff; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - expDiff = aExp - bExp; - if (0 < expDiff) { - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) - return propagateFloat128NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) { - --expDiff; - } else { - bSig0 |= LIT64(0x0001000000000000); - } - shift128ExtraRightJamming(bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2); - zExp = aExp; - } else if (expDiff < 0) { - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) - return propagateFloat128NaN(a, b STATUS_VAR); - return packFloat128(zSign, 0x7FFF, 0, 0); - } - if (aExp == 0) { - ++expDiff; - } else { - aSig0 |= LIT64(0x0001000000000000); - } - shift128ExtraRightJamming(aSig0, aSig1, 0, -expDiff, &aSig0, &aSig1, &zSig2); - zExp = bExp; - } else { - if (aExp == 0x7FFF) { - if (aSig0 | aSig1 | bSig0 | bSig1) { - return propagateFloat128NaN(a, b STATUS_VAR); - } - return a; - } - add128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); - if (aExp == 0) { - if (STATUS(flush_to_zero)) { - if (zSig0 | zSig1) { - float_raise(float_flag_output_denormal STATUS_VAR); - } - return packFloat128(zSign, 0, 0, 0); - } - return packFloat128(zSign, 0, zSig0, zSig1); - } - zSig2 = 0; - zSig0 |= LIT64(0x0002000000000000); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= LIT64(0x0001000000000000); - add128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); - --zExp; - if (zSig0 < LIT64(0x0002000000000000)) - goto roundAndPack; - ++zExp; -shiftRight1: - shift128ExtraRightJamming(zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2); -roundAndPack: - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs(float128 a, float128 b, flag zSign STATUS_PARAM) { - int32 aExp, bExp, zExp; - uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - int32 expDiff; - float128 z; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - expDiff = aExp - bExp; - shortShift128Left(aSig0, aSig1, 14, &aSig0, &aSig1); - shortShift128Left(bSig0, bSig1, 14, &bSig0, &bSig1); - if (0 < expDiff) - goto aExpBigger; - if (expDiff < 0) - goto bExpBigger; - if (aExp == 0x7FFF) { - if (aSig0 | aSig1 | bSig0 | bSig1) { - return propagateFloat128NaN(a, b STATUS_VAR); - } - float_raise(float_flag_invalid STATUS_VAR); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if (aExp == 0) { - aExp = 1; - bExp = 1; - } - if (bSig0 < aSig0) - goto aBigger; - if (aSig0 < bSig0) - goto bBigger; - if (bSig1 < aSig1) - goto aBigger; - if (aSig1 < bSig1) - goto bBigger; - return packFloat128(STATUS(float_rounding_mode) == float_round_down, 0, 0, 0); -bExpBigger: - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) - return propagateFloat128NaN(a, b STATUS_VAR); - return packFloat128(zSign ^ 1, 0x7FFF, 0, 0); - } - if (aExp == 0) { - ++expDiff; - } else { - aSig0 |= LIT64(0x4000000000000000); - } - shift128RightJamming(aSig0, aSig1, -expDiff, &aSig0, &aSig1); - bSig0 |= LIT64(0x4000000000000000); -bBigger: - sub128(bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; -aExpBigger: - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) - return propagateFloat128NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) { - --expDiff; - } else { - bSig0 |= LIT64(0x4000000000000000); - } - shift128RightJamming(bSig0, bSig1, expDiff, &bSig0, &bSig1); - aSig0 |= LIT64(0x4000000000000000); -aBigger: - sub128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); - zExp = aExp; -normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128(zSign, zExp - 14, zSig0, zSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add(float128 a, float128 b STATUS_PARAM) { - flag aSign, bSign; - - aSign = extractFloat128Sign(a); - bSign = extractFloat128Sign(b); - if (aSign == bSign) { - return addFloat128Sigs(a, b, aSign STATUS_VAR); - } else { - return subFloat128Sigs(a, b, aSign STATUS_VAR); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub(float128 a, float128 b STATUS_PARAM) { - flag aSign, bSign; - - aSign = extractFloat128Sign(a); - bSign = extractFloat128Sign(b); - if (aSign == bSign) { - return subFloat128Sigs(a, b, aSign STATUS_VAR); - } else { - return addFloat128Sigs(a, b, aSign STATUS_VAR); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul(float128 a, float128 b STATUS_PARAM) { - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - float128 z; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - bSign = extractFloat128Sign(b); - zSign = aSign ^ bSign; - if (aExp == 0x7FFF) { - if ((aSig0 | aSig1) || ((bExp == 0x7FFF) && (bSig0 | bSig1))) { - return propagateFloat128NaN(a, b STATUS_VAR); - } - if ((bExp | bSig0 | bSig1) == 0) - goto invalid; - return packFloat128(zSign, 0x7FFF, 0, 0); - } - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) - return propagateFloat128NaN(a, b STATUS_VAR); - if ((aExp | aSig0 | aSig1) == 0) { - invalid: - float_raise(float_flag_invalid STATUS_VAR); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - return packFloat128(zSign, 0x7FFF, 0, 0); - } - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) - return packFloat128(zSign, 0, 0, 0); - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) - return packFloat128(zSign, 0, 0, 0); - normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64(0x0001000000000000); - shortShift128Left(bSig0, bSig1, 16, &bSig0, &bSig1); - mul128To256(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3); - add128(zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1); - zSig2 |= (zSig3 != 0); - if (LIT64(0x0002000000000000) <= zSig0) { - shift128ExtraRightJamming(zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2); - ++zExp; - } - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div(float128 a, float128 b STATUS_PARAM) { - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - bSign = extractFloat128Sign(b); - zSign = aSign ^ bSign; - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) - return propagateFloat128NaN(a, b STATUS_VAR); - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) - return propagateFloat128NaN(a, b STATUS_VAR); - goto invalid; - } - return packFloat128(zSign, 0x7FFF, 0, 0); - } - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) - return propagateFloat128NaN(a, b STATUS_VAR); - return packFloat128(zSign, 0, 0, 0); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) { - if ((aExp | aSig0 | aSig1) == 0) { - invalid: - float_raise(float_flag_invalid STATUS_VAR); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - float_raise(float_flag_divbyzero STATUS_VAR); - return packFloat128(zSign, 0x7FFF, 0, 0); - } - normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); - } - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) - return packFloat128(zSign, 0, 0, 0); - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left(aSig0 | LIT64(0x0001000000000000), aSig1, 15, &aSig0, &aSig1); - shortShift128Left(bSig0 | LIT64(0x0001000000000000), bSig1, 15, &bSig0, &bSig1); - if (le128(bSig0, bSig1, aSig0, aSig1)) { - shift128Right(aSig0, aSig1, 1, &aSig0, &aSig1); - ++zExp; - } - zSig0 = estimateDiv128To64(aSig0, aSig1, bSig0); - mul128By64To192(bSig0, bSig1, zSig0, &term0, &term1, &term2); - sub192(aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2); - while ((int64_t) rem0 < 0) { - --zSig0; - add192(rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2); - } - zSig1 = estimateDiv128To64(rem1, rem2, bSig0); - if ((zSig1 & 0x3FFF) <= 4) { - mul128By64To192(bSig0, bSig1, zSig1, &term1, &term2, &term3); - sub192(rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3); - while ((int64_t) rem1 < 0) { - --zSig1; - add192(rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3); - } - zSig1 |= ((rem1 | rem2 | rem3) != 0); - } - shift128ExtraRightJamming(zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2); - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the quadruple-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_rem(float128 a, float128 b STATUS_PARAM) { - flag aSign, zSign; - int32 aExp, bExp, expDiff; - uint64_t aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; - uint64_t allZero, alternateASig0, alternateASig1, sigMean1; - int64_t sigMean0; - float128 z; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - if (aExp == 0x7FFF) { - if ((aSig0 | aSig1) || ((bExp == 0x7FFF) && (bSig0 | bSig1))) { - return propagateFloat128NaN(a, b STATUS_VAR); - } - goto invalid; - } - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) - return propagateFloat128NaN(a, b STATUS_VAR); - return a; - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) { - invalid: - float_raise(float_flag_invalid STATUS_VAR); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); - } - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) - return a; - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } - expDiff = aExp - bExp; - if (expDiff < -1) - return a; - shortShift128Left(aSig0 | LIT64(0x0001000000000000), aSig1, 15 - (expDiff < 0), &aSig0, &aSig1); - shortShift128Left(bSig0 | LIT64(0x0001000000000000), bSig1, 15, &bSig0, &bSig1); - q = le128(bSig0, bSig1, aSig0, aSig1); - if (q) - sub128(aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1); - expDiff -= 64; - while (0 < expDiff) { - q = estimateDiv128To64(aSig0, aSig1, bSig0); - q = (4 < q) ? q - 4 : 0; - mul128By64To192(bSig0, bSig1, q, &term0, &term1, &term2); - shortShift192Left(term0, term1, term2, 61, &term1, &term2, &allZero); - shortShift128Left(aSig0, aSig1, 61, &aSig0, &allZero); - sub128(aSig0, 0, term1, term2, &aSig0, &aSig1); - expDiff -= 61; - } - if (-64 < expDiff) { - q = estimateDiv128To64(aSig0, aSig1, bSig0); - q = (4 < q) ? q - 4 : 0; - q >>= -expDiff; - shift128Right(bSig0, bSig1, 12, &bSig0, &bSig1); - expDiff += 52; - if (expDiff < 0) { - shift128Right(aSig0, aSig1, -expDiff, &aSig0, &aSig1); - } else { - shortShift128Left(aSig0, aSig1, expDiff, &aSig0, &aSig1); - } - mul128By64To192(bSig0, bSig1, q, &term0, &term1, &term2); - sub128(aSig0, aSig1, term1, term2, &aSig0, &aSig1); - } else { - shift128Right(aSig0, aSig1, 12, &aSig0, &aSig1); - shift128Right(bSig0, bSig1, 12, &bSig0, &bSig1); - } - do { - alternateASig0 = aSig0; - alternateASig1 = aSig1; - ++q; - sub128(aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1); - } while (0 <= (int64_t) aSig0); - add128(aSig0, aSig1, alternateASig0, alternateASig1, (uint64_t *) &sigMean0, &sigMean1); - if ((sigMean0 < 0) || (((sigMean0 | sigMean1) == 0) && (q & 1))) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - } - zSign = ((int64_t) aSig0 < 0); - if (zSign) - sub128(0, 0, aSig0, aSig1, &aSig0, &aSig1); - return normalizeRoundAndPackFloat128(aSign ^ zSign, bExp - 4, aSig0, aSig1 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the quadruple-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sqrt(float128 a STATUS_PARAM) { - flag aSign; - int32 aExp, zExp; - uint64_t aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; - uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) - return propagateFloat128NaN(a, a STATUS_VAR); - if (!aSign) - return a; - goto invalid; - } - if (aSign) { - if ((aExp | aSig0 | aSig1) == 0) - return a; - invalid: - float_raise(float_flag_invalid STATUS_VAR); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) - return packFloat128(0, 0, 0, 0); - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } - zExp = ((aExp - 0x3FFF) >> 1) + 0x3FFE; - aSig0 |= LIT64(0x0001000000000000); - zSig0 = estimateSqrt32(aExp, aSig0 >> 17); - shortShift128Left(aSig0, aSig1, 13 - (aExp & 1), &aSig0, &aSig1); - zSig0 = estimateDiv128To64(aSig0, aSig1, zSig0 << 32) + (zSig0 << 30); - doubleZSig0 = zSig0 << 1; - mul64To128(zSig0, zSig0, &term0, &term1); - sub128(aSig0, aSig1, term0, term1, &rem0, &rem1); - while ((int64_t) rem0 < 0) { - --zSig0; - doubleZSig0 -= 2; - add128(rem0, rem1, zSig0 >> 63, doubleZSig0 | 1, &rem0, &rem1); - } - zSig1 = estimateDiv128To64(rem1, 0, doubleZSig0); - if ((zSig1 & 0x1FFF) <= 5) { - if (zSig1 == 0) - zSig1 = 1; - mul64To128(doubleZSig0, zSig1, &term1, &term2); - sub128(rem1, 0, term1, term2, &rem1, &rem2); - mul64To128(zSig1, zSig1, &term2, &term3); - sub192(rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3); - while ((int64_t) rem1 < 0) { - --zSig1; - shortShift128Left(0, zSig1, 1, &term2, &term3); - term3 |= 1; - term2 |= doubleZSig0; - add192(rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3); - } - zSig1 |= ((rem1 | rem2 | rem3) != 0); - } - shift128ExtraRightJamming(zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2); - return roundAndPackFloat128(0, zExp, zSig0, zSig1, zSig2 STATUS_VAR); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_eq(float128 a, float128 b STATUS_PARAM) { - - if (((extractFloat128Exp(a) == 0x7FFF) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) || - ((extractFloat128Exp(b) == 0x7FFF) && (extractFloat128Frac0(b) | extractFloat128Frac1(b)))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - return (a.low == b.low) && ((a.high == b.high) || ((a.low == 0) && ((uint64_t)((a.high | b.high) << 1) == 0))); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The invalid -| exception is raised if either operand is a NaN. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_le(float128 a, float128 b STATUS_PARAM) { - flag aSign, bSign; - - if (((extractFloat128Exp(a) == 0x7FFF) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) || - ((extractFloat128Exp(b) == 0x7FFF) && (extractFloat128Frac0(b) | extractFloat128Frac1(b)))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - aSign = extractFloat128Sign(a); - bSign = extractFloat128Sign(b); - if (aSign != bSign) { - return aSign || ((((uint64_t)((a.high | b.high) << 1)) | a.low | b.low) == 0); - } - return aSign ? le128(b.high, b.low, a.high, a.low) : le128(a.high, a.low, b.high, b.low); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. The comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_lt(float128 a, float128 b STATUS_PARAM) { - flag aSign, bSign; - - if (((extractFloat128Exp(a) == 0x7FFF) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) || - ((extractFloat128Exp(b) == 0x7FFF) && (extractFloat128Frac0(b) | extractFloat128Frac1(b)))) { - float_raise(float_flag_invalid STATUS_VAR); - return 0; - } - aSign = extractFloat128Sign(a); - bSign = extractFloat128Sign(b); - if (aSign != bSign) { - return aSign && ((((uint64_t)((a.high | b.high) << 1)) | a.low | b.low) != 0); - } - return aSign ? lt128(b.high, b.low, a.high, a.low) : lt128(a.high, a.low, b.high, b.low); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. The invalid exception is raised if either -| operand is a NaN. The comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_unordered(float128 a, float128 b STATUS_PARAM) { - if (((extractFloat128Exp(a) == 0x7FFF) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) || - ((extractFloat128Exp(b) == 0x7FFF) && (extractFloat128Frac0(b) | extractFloat128Frac1(b)))) { - float_raise(float_flag_invalid STATUS_VAR); - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. The comparison is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_eq_quiet(float128 a, float128 b STATUS_PARAM) { - - if (((extractFloat128Exp(a) == 0x7FFF) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) || - ((extractFloat128Exp(b) == 0x7FFF) && (extractFloat128Frac0(b) | extractFloat128Frac1(b)))) { - if (float128_is_signaling_nan(a) || float128_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - return (a.low == b.low) && ((a.high == b.high) || ((a.low == 0) && ((uint64_t)((a.high | b.high) << 1) == 0))); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_le_quiet(float128 a, float128 b STATUS_PARAM) { - flag aSign, bSign; - - if (((extractFloat128Exp(a) == 0x7FFF) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) || - ((extractFloat128Exp(b) == 0x7FFF) && (extractFloat128Frac0(b) | extractFloat128Frac1(b)))) { - if (float128_is_signaling_nan(a) || float128_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - aSign = extractFloat128Sign(a); - bSign = extractFloat128Sign(b); - if (aSign != bSign) { - return aSign || ((((uint64_t)((a.high | b.high) << 1)) | a.low | b.low) == 0); - } - return aSign ? le128(b.high, b.low, a.high, a.low) : le128(a.high, a.low, b.high, b.low); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_lt_quiet(float128 a, float128 b STATUS_PARAM) { - flag aSign, bSign; - - if (((extractFloat128Exp(a) == 0x7FFF) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) || - ((extractFloat128Exp(b) == 0x7FFF) && (extractFloat128Frac0(b) | extractFloat128Frac1(b)))) { - if (float128_is_signaling_nan(a) || float128_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 0; - } - aSign = extractFloat128Sign(a); - bSign = extractFloat128Sign(b); - if (aSign != bSign) { - return aSign && ((((uint64_t)((a.high | b.high) << 1)) | a.low | b.low) != 0); - } - return aSign ? lt128(b.high, b.low, a.high, a.low) : lt128(a.high, a.low, b.high, b.low); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_unordered_quiet(float128 a, float128 b STATUS_PARAM) { - if (((extractFloat128Exp(a) == 0x7FFF) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) || - ((extractFloat128Exp(b) == 0x7FFF) && (extractFloat128Frac0(b) | extractFloat128Frac1(b)))) { - if (float128_is_signaling_nan(a) || float128_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return 1; - } - return 0; -} - -/* misc functions */ -float32 uint32_to_float32(uint32 a STATUS_PARAM) { - return int64_to_float32(a STATUS_VAR); -} - -float64 uint32_to_float64(uint32 a STATUS_PARAM) { - return int64_to_float64(a STATUS_VAR); -} - -uint32 float32_to_uint32(float32 a STATUS_PARAM) { - int64_t v; - uint32 res; - - v = float32_to_int64(a STATUS_VAR); - if (v < 0) { - res = 0; - float_raise(float_flag_invalid STATUS_VAR); - } else if (v > 0xffffffff) { - res = 0xffffffff; - float_raise(float_flag_invalid STATUS_VAR); - } else { - res = v; - } - return res; -} - -uint32 float32_to_uint32_round_to_zero(float32 a STATUS_PARAM) { - int64_t v; - uint32 res; - - v = float32_to_int64_round_to_zero(a STATUS_VAR); - if (v < 0) { - res = 0; - float_raise(float_flag_invalid STATUS_VAR); - } else if (v > 0xffffffff) { - res = 0xffffffff; - float_raise(float_flag_invalid STATUS_VAR); - } else { - res = v; - } - return res; -} - -uint16 float32_to_uint16_round_to_zero(float32 a STATUS_PARAM) { - int64_t v; - uint16 res; - - v = float32_to_int64_round_to_zero(a STATUS_VAR); - if (v < 0) { - res = 0; - float_raise(float_flag_invalid STATUS_VAR); - } else if (v > 0xffff) { - res = 0xffff; - float_raise(float_flag_invalid STATUS_VAR); - } else { - res = v; - } - return res; -} - -uint32 float64_to_uint32(float64 a STATUS_PARAM) { - int64_t v; - uint32 res; - - v = float64_to_int64(a STATUS_VAR); - if (v < 0) { - res = 0; - float_raise(float_flag_invalid STATUS_VAR); - } else if (v > 0xffffffff) { - res = 0xffffffff; - float_raise(float_flag_invalid STATUS_VAR); - } else { - res = v; - } - return res; -} - -uint32 float64_to_uint32_round_to_zero(float64 a STATUS_PARAM) { - int64_t v; - uint32 res; - - v = float64_to_int64_round_to_zero(a STATUS_VAR); - if (v < 0) { - res = 0; - float_raise(float_flag_invalid STATUS_VAR); - } else if (v > 0xffffffff) { - res = 0xffffffff; - float_raise(float_flag_invalid STATUS_VAR); - } else { - res = v; - } - return res; -} - -uint16 float64_to_uint16_round_to_zero(float64 a STATUS_PARAM) { - int64_t v; - uint16 res; - - v = float64_to_int64_round_to_zero(a STATUS_VAR); - if (v < 0) { - res = 0; - float_raise(float_flag_invalid STATUS_VAR); - } else if (v > 0xffff) { - res = 0xffff; - float_raise(float_flag_invalid STATUS_VAR); - } else { - res = v; - } - return res; -} - -/* FIXME: This looks broken. */ -uint64_t float64_to_uint64(float64 a STATUS_PARAM) { - int64_t v; - - v = float64_val(int64_to_float64(INT64_MIN STATUS_VAR)); - v += float64_val(a); - v = float64_to_int64(make_float64(v) STATUS_VAR); - - return v - INT64_MIN; -} - -uint64_t float64_to_uint64_round_to_zero(float64 a STATUS_PARAM) { - int64_t v; - - v = float64_val(int64_to_float64(INT64_MIN STATUS_VAR)); - v += float64_val(a); - v = float64_to_int64_round_to_zero(make_float64(v) STATUS_VAR); - - return v - INT64_MIN; -} - -#define COMPARE(s, nan_exp) \ - SINLINE int float##s##_compare_internal(float##s a, float##s b, int is_quiet STATUS_PARAM) { \ - flag aSign, bSign; \ - uint##s##_t av, bv; \ - a = float##s##_squash_input_denormal(a STATUS_VAR); \ - b = float##s##_squash_input_denormal(b STATUS_VAR); \ - \ - if (((extractFloat##s##Exp(a) == nan_exp) && extractFloat##s##Frac(a)) || \ - ((extractFloat##s##Exp(b) == nan_exp) && extractFloat##s##Frac(b))) { \ - if (!is_quiet || float##s##_is_signaling_nan(a) || float##s##_is_signaling_nan(b)) { \ - float_raise(float_flag_invalid STATUS_VAR); \ - } \ - return float_relation_unordered; \ - } \ - aSign = extractFloat##s##Sign(a); \ - bSign = extractFloat##s##Sign(b); \ - av = float##s##_val(a); \ - bv = float##s##_val(b); \ - if (aSign != bSign) { \ - if ((uint##s##_t)((av | bv) << 1) == 0) { \ - /* zero case */ \ - return float_relation_equal; \ - } else { \ - return 1 - (2 * aSign); \ - } \ - } else { \ - if (av == bv) { \ - return float_relation_equal; \ - } else { \ - return 1 - 2 * (aSign ^ (av < bv)); \ - } \ - } \ - } \ - \ - int float##s##_compare(float##s a, float##s b STATUS_PARAM) { \ - return float##s##_compare_internal(a, b, 0 STATUS_VAR); \ - } \ - \ - int float##s##_compare_quiet(float##s a, float##s b STATUS_PARAM) { \ - return float##s##_compare_internal(a, b, 1 STATUS_VAR); \ - } - -COMPARE(32, 0xff) -COMPARE(64, 0x7ff) - -SINLINE int floatx80_compare_internal(floatx80 a, floatx80 b, int is_quiet STATUS_PARAM) { - flag aSign, bSign; - - if (((extractFloatx80Exp(a) == 0x7fff) && (extractFloatx80Frac(a) << 1)) || - ((extractFloatx80Exp(b) == 0x7fff) && (extractFloatx80Frac(b) << 1))) { - if (!is_quiet || floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return float_relation_unordered; - } - aSign = extractFloatx80Sign(a); - bSign = extractFloatx80Sign(b); - if (aSign != bSign) { - - if ((((uint16_t)((a.high | b.high) << 1)) == 0) && ((a.low | b.low) == 0)) { - /* zero case */ - return float_relation_equal; - } else { - return 1 - (2 * aSign); - } - } else { - if (a.low == b.low && a.high == b.high) { - return float_relation_equal; - } else { - return 1 - 2 * (aSign ^ (lt128(a.high, a.low, b.high, b.low))); - } - } -} - -int floatx80_compare(floatx80 a, floatx80 b STATUS_PARAM) { - return floatx80_compare_internal(a, b, 0 STATUS_VAR); -} - -int floatx80_compare_quiet(floatx80 a, floatx80 b STATUS_PARAM) { - return floatx80_compare_internal(a, b, 1 STATUS_VAR); -} - -SINLINE int float128_compare_internal(float128 a, float128 b, int is_quiet STATUS_PARAM) { - flag aSign, bSign; - - if (((extractFloat128Exp(a) == 0x7fff) && (extractFloat128Frac0(a) | extractFloat128Frac1(a))) || - ((extractFloat128Exp(b) == 0x7fff) && (extractFloat128Frac0(b) | extractFloat128Frac1(b)))) { - if (!is_quiet || float128_is_signaling_nan(a) || float128_is_signaling_nan(b)) { - float_raise(float_flag_invalid STATUS_VAR); - } - return float_relation_unordered; - } - aSign = extractFloat128Sign(a); - bSign = extractFloat128Sign(b); - if (aSign != bSign) { - if ((((a.high | b.high) << 1) | a.low | b.low) == 0) { - /* zero case */ - return float_relation_equal; - } else { - return 1 - (2 * aSign); - } - } else { - if (a.low == b.low && a.high == b.high) { - return float_relation_equal; - } else { - return 1 - 2 * (aSign ^ (lt128(a.high, a.low, b.high, b.low))); - } - } -} - -int float128_compare(float128 a, float128 b STATUS_PARAM) { - return float128_compare_internal(a, b, 0 STATUS_VAR); -} - -int float128_compare_quiet(float128 a, float128 b STATUS_PARAM) { - return float128_compare_internal(a, b, 1 STATUS_VAR); -} - -/* min() and max() functions. These can't be implemented as - * 'compare and pick one input' because that would mishandle - * NaNs and +0 vs -0. - */ -#define MINMAX(s, nan_exp) \ - SINLINE float##s float##s##_minmax(float##s a, float##s b, int ismin STATUS_PARAM) { \ - flag aSign, bSign; \ - uint##s##_t av, bv; \ - a = float##s##_squash_input_denormal(a STATUS_VAR); \ - b = float##s##_squash_input_denormal(b STATUS_VAR); \ - if (float##s##_is_any_nan(a) || float##s##_is_any_nan(b)) { \ - return propagateFloat##s##NaN(a, b STATUS_VAR); \ - } \ - aSign = extractFloat##s##Sign(a); \ - bSign = extractFloat##s##Sign(b); \ - av = float##s##_val(a); \ - bv = float##s##_val(b); \ - if (aSign != bSign) { \ - if (ismin) { \ - return aSign ? a : b; \ - } else { \ - return aSign ? b : a; \ - } \ - } else { \ - if (ismin) { \ - return (aSign ^ (av < bv)) ? a : b; \ - } else { \ - return (aSign ^ (av < bv)) ? b : a; \ - } \ - } \ - } \ - \ - float##s float##s##_min(float##s a, float##s b STATUS_PARAM) { \ - return float##s##_minmax(a, b, 1 STATUS_VAR); \ - } \ - \ - float##s float##s##_max(float##s a, float##s b STATUS_PARAM) { \ - return float##s##_minmax(a, b, 0 STATUS_VAR); \ - } - -MINMAX(32, 0xff) -MINMAX(64, 0x7ff) - -/* Multiply A by 2 raised to the power N. */ -float32 float32_scalbn(float32 a, int n STATUS_PARAM) { - flag aSign; - int16_t aExp; - uint32_t aSig; - - a = float32_squash_input_denormal(a STATUS_VAR); - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) { - return propagateFloat32NaN(a, a STATUS_VAR); - } - return a; - } - if (aExp != 0) - aSig |= 0x00800000; - else if (aSig == 0) - return a; - - if (n > 0x200) { - n = 0x200; - } else if (n < -0x200) { - n = -0x200; - } - - aExp += n - 1; - aSig <<= 7; - return normalizeRoundAndPackFloat32(aSign, aExp, aSig STATUS_VAR); -} - -float64 float64_scalbn(float64 a, int n STATUS_PARAM) { - flag aSign; - int16_t aExp; - uint64_t aSig; - - a = float64_squash_input_denormal(a STATUS_VAR); - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - - if (aExp == 0x7FF) { - if (aSig) { - return propagateFloat64NaN(a, a STATUS_VAR); - } - return a; - } - if (aExp != 0) - aSig |= LIT64(0x0010000000000000); - else if (aSig == 0) - return a; - - if (n > 0x1000) { - n = 0x1000; - } else if (n < -0x1000) { - n = -0x1000; - } - - aExp += n - 1; - aSig <<= 10; - return normalizeRoundAndPackFloat64(aSign, aExp, aSig STATUS_VAR); -} - -floatx80 floatx80_scalbn(floatx80 a, int n STATUS_PARAM) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if (aSig << 1) { - return propagateFloatx80NaN(a, a STATUS_VAR); - } - return a; - } - - if (aExp == 0 && aSig == 0) - return a; - - if (n > 0x10000) { - n = 0x10000; - } else if (n < -0x10000) { - n = -0x10000; - } - - aExp += n; - return normalizeRoundAndPackFloatx80(STATUS(floatx80_rounding_precision), aSign, aExp, aSig, 0 STATUS_VAR); -} - -float128 float128_scalbn(float128 a, int n STATUS_PARAM) { - flag aSign; - int32_t aExp; - uint64_t aSig0, aSig1; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) { - return propagateFloat128NaN(a, a STATUS_VAR); - } - return a; - } - if (aExp != 0) - aSig0 |= LIT64(0x0001000000000000); - else if (aSig0 == 0 && aSig1 == 0) - return a; - - if (n > 0x10000) { - n = 0x10000; - } else if (n < -0x10000) { - n = -0x10000; - } - - aExp += n - 1; - return normalizeRoundAndPackFloat128(aSign, aExp, aSig0, aSig1 STATUS_VAR); -} diff --git a/src/base/emu-i386/simx86/softfloat/softfloat.h b/src/base/emu-i386/simx86/softfloat/softfloat.h deleted file mode 100644 index 5f0f765..0000000 --- a/src/base/emu-i386/simx86/softfloat/softfloat.h +++ /dev/null @@ -1,611 +0,0 @@ -/* - * QEMU float support - * - * Derived from SoftFloat. - */ - -/*============================================================================ - -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. - -=============================================================================*/ - -#ifndef SOFTFLOAT_H -#define SOFTFLOAT_H - -#if defined(CONFIG_SOLARIS) && defined(CONFIG_NEEDS_LIBSUNMATH) -#include -#endif - -//#include -#include - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines the most convenient type that holds -| integers of at least as many bits as specified. For example, `uint8' should -| be the most convenient type that can hold unsigned integers of as many as -| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most -| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed -| to the same as `int'. -*----------------------------------------------------------------------------*/ -typedef uint8_t flag; - -#ifdef __APPLE__ -#define uint16 qemu_uint16 -#endif - -typedef uint8_t uint8; -typedef int8_t int8; -#ifndef _AIX -typedef int uint16; -typedef int int16; -#endif -typedef unsigned int uint32; -typedef signed int int32; -typedef uint64_t uint64; -typedef int64_t int64; - -#define LIT64(a) a##LL -#define SINLINE static inline - -#define STATUS_PARAM , float_status *status -#define STATUS_VAR , status - -#if defined(CONFIG_SYMBEX) && !defined(SYMBEX_LLVM_LIB) -uint8_t RR_cpu_float_status(void *p, unsigned size); -void WR_cpu_float_status(void *p, unsigned size, int v); - -#define STATUS(field) RR_cpu_float_status(&status->field, sizeof(status->field)) -#define STATUS_W(field, v) WR_cpu_float_status(&status->field, sizeof(status->field), v) -#else -#define STATUS(field) status->field -#define STATUS_W(field, v) status->field = v -#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 }; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -/* Use structures for soft-float types. This prevents accidentally mixing - them with native int/float types. A sufficiently clever compiler and - sane ABI should be able to see though these structs. However - x86/gcc 3.x seems to struggle a bit, so leave them disabled by default. */ -//#define USE_SOFTFLOAT_STRUCT_TYPES -#ifdef USE_SOFTFLOAT_STRUCT_TYPES -typedef struct { uint16_t v; } float16; -#define float16_val(x) (((float16)(x)).v) -#define make_float16(x) \ - __extension__({ \ - float16 f16_val = {x}; \ - f16_val; \ - }) -#define const_float16(x) \ - { x } -typedef struct { uint32_t v; } float32; -/* The cast ensures an error if the wrong type is passed. */ -#define float32_val(x) (((float32)(x)).v) -#define make_float32(x) \ - __extension__({ \ - float32 f32_val = {x}; \ - f32_val; \ - }) -#define const_float32(x) \ - { x } -typedef struct { uint64_t v; } float64; -#define float64_val(x) (((float64)(x)).v) -#define make_float64(x) \ - __extension__({ \ - float64 f64_val = {x}; \ - f64_val; \ - }) -#define const_float64(x) \ - { x } -#else -typedef uint16_t float16; -typedef uint32_t float32; -typedef uint64_t float64; -#define float16_val(x) (x) -#define float32_val(x) (x) -#define float64_val(x) (x) -#define make_float16(x) (x) -#define make_float32(x) (x) -#define make_float64(x) (x) -#define const_float16(x) (x) -#define const_float32(x) (x) -#define const_float64(x) (x) -#endif -typedef struct { - uint64_t low; - uint16_t high; -} floatx80; -#define make_floatx80(exp, mant) ((floatx80){mant, exp}) -#define make_floatx80_init(exp, mant) \ - { .low = mant, .high = exp } -typedef struct { -#ifdef HOST_WORDS_BIGENDIAN - uint64_t high, low; -#else - uint64_t low, high; -#endif -} float128; -#define make_float128(high_, low_) ((float128){.high = high_, .low = low_}) -#define make_float128_init(high_, low_) \ - { .high = high_, .low = low_ } - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -enum { float_tininess_after_rounding = 0, float_tininess_before_rounding = 1 }; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -enum { 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_flag_invalid = 1, - float_flag_divbyzero = 4, - float_flag_overflow = 8, - float_flag_underflow = 16, - float_flag_inexact = 32, - float_flag_input_denormal = 64, - float_flag_output_denormal = 128 -}; - -typedef struct float_status { - signed char float_detect_tininess; - signed char float_rounding_mode; - signed char float_exception_flags; - signed char floatx80_rounding_precision; - /* should denormalised results go to zero and set the inexact flag? */ - flag flush_to_zero; - /* should denormalised inputs go to zero and set the input_denormal flag? */ - flag flush_inputs_to_zero; - flag default_nan_mode; -} float_status; - -void set_float_rounding_mode(int val STATUS_PARAM); -void set_float_exception_flags(int val STATUS_PARAM); -SINLINE void set_float_detect_tininess(int val STATUS_PARAM) { - STATUS_W(float_detect_tininess, val); -} -SINLINE void set_flush_to_zero(flag val STATUS_PARAM) { - STATUS_W(flush_to_zero, val); -} -SINLINE void set_flush_inputs_to_zero(flag val STATUS_PARAM) { - STATUS_W(flush_inputs_to_zero, val); -} -SINLINE void set_default_nan_mode(flag val STATUS_PARAM) { - STATUS_W(default_nan_mode, val); -} -SINLINE int get_float_exception_flags(float_status *status) { - return STATUS(float_exception_flags); -} -void set_floatx80_rounding_precision(int val STATUS_PARAM); - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ -void float_raise(uint8_t flags STATUS_PARAM); - -/*---------------------------------------------------------------------------- -| Options to indicate which negations to perform in float*_muladd() -| Using these differs from negating an input or output before calling -| the muladd function in that this means that a NaN doesn't have its -| sign bit inverted before it is propagated. -*----------------------------------------------------------------------------*/ -enum { - float_muladd_negate_c = 1, - float_muladd_negate_product = 2, - float_muladd_negate_result = 3, -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32(int32 STATUS_PARAM); -float64 int32_to_float64(int32 STATUS_PARAM); -float32 uint32_to_float32(uint32 STATUS_PARAM); -float64 uint32_to_float64(uint32 STATUS_PARAM); -floatx80 int32_to_floatx80(int32 STATUS_PARAM); -float128 int32_to_float128(int32 STATUS_PARAM); -float32 int64_to_float32(int64 STATUS_PARAM); -float32 uint64_to_float32(uint64 STATUS_PARAM); -float64 int64_to_float64(int64 STATUS_PARAM); -float64 uint64_to_float64(uint64 STATUS_PARAM); -floatx80 int64_to_floatx80(int64 STATUS_PARAM); -float128 int64_to_float128(int64 STATUS_PARAM); - -/*---------------------------------------------------------------------------- -| Software half-precision conversion routines. -*----------------------------------------------------------------------------*/ -float16 float32_to_float16(float32, flag STATUS_PARAM); -float32 float16_to_float32(float16, flag STATUS_PARAM); - -/*---------------------------------------------------------------------------- -| Software half-precision operations. -*----------------------------------------------------------------------------*/ -int float16_is_quiet_nan(float16); -int float16_is_signaling_nan(float16); -float16 float16_maybe_silence_nan(float16); - -/*---------------------------------------------------------------------------- -| The pattern for a default generated half-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float16 float16_default_nan; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -int16 float32_to_int16_round_to_zero(float32 STATUS_PARAM); -uint16 float32_to_uint16_round_to_zero(float32 STATUS_PARAM); -int32 float32_to_int32(float32 STATUS_PARAM); -int32 float32_to_int32_round_to_zero(float32 STATUS_PARAM); -uint32 float32_to_uint32(float32 STATUS_PARAM); -uint32 float32_to_uint32_round_to_zero(float32 STATUS_PARAM); -int64 float32_to_int64(float32 STATUS_PARAM); -int64 float32_to_int64_round_to_zero(float32 STATUS_PARAM); -float64 float32_to_float64(float32 STATUS_PARAM); -floatx80 float32_to_floatx80(float32 STATUS_PARAM); -float128 float32_to_float128(float32 STATUS_PARAM); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int(float32 STATUS_PARAM); -float32 float32_add(float32, float32 STATUS_PARAM); -float32 float32_sub(float32, float32 STATUS_PARAM); -float32 float32_mul(float32, float32 STATUS_PARAM); -float32 float32_div(float32, float32 STATUS_PARAM); -float32 float32_rem(float32, float32 STATUS_PARAM); -float32 float32_muladd(float32, float32, float32, int STATUS_PARAM); -float32 float32_sqrt(float32 STATUS_PARAM); -float32 float32_exp2(float32 STATUS_PARAM); -float32 float32_log2(float32 STATUS_PARAM); -int float32_eq(float32, float32 STATUS_PARAM); -int float32_le(float32, float32 STATUS_PARAM); -int float32_lt(float32, float32 STATUS_PARAM); -int float32_unordered(float32, float32 STATUS_PARAM); -int float32_eq_quiet(float32, float32 STATUS_PARAM); -int float32_le_quiet(float32, float32 STATUS_PARAM); -int float32_lt_quiet(float32, float32 STATUS_PARAM); -int float32_unordered_quiet(float32, float32 STATUS_PARAM); -int float32_compare(float32, float32 STATUS_PARAM); -int float32_compare_quiet(float32, float32 STATUS_PARAM); -float32 float32_min(float32, float32 STATUS_PARAM); -float32 float32_max(float32, float32 STATUS_PARAM); -int float32_is_quiet_nan(float32); -int float32_is_signaling_nan(float32); -float32 float32_maybe_silence_nan(float32); -float32 float32_scalbn(float32, int STATUS_PARAM); - -SINLINE float32 float32_abs(float32 a) { - /* Note that abs does *not* handle NaN specially, nor does - * it flush denormal inputs to zero. - */ - return make_float32(float32_val(a) & 0x7fffffff); -} - -SINLINE float32 float32_chs(float32 a) { - /* Note that chs does *not* handle NaN specially, nor does - * it flush denormal inputs to zero. - */ - return make_float32(float32_val(a) ^ 0x80000000); -} - -SINLINE int float32_is_infinity(float32 a) { - return (float32_val(a) & 0x7fffffff) == 0x7f800000; -} - -SINLINE int float32_is_neg(float32 a) { - return float32_val(a) >> 31; -} - -SINLINE int float32_is_zero(float32 a) { - return (float32_val(a) & 0x7fffffff) == 0; -} - -SINLINE int float32_is_any_nan(float32 a) { - return ((float32_val(a) & ~(1 << 31)) > 0x7f800000UL); -} - -SINLINE int float32_is_zero_or_denormal(float32 a) { - return (float32_val(a) & 0x7f800000) == 0; -} - -SINLINE float32 float32_set_sign(float32 a, int sign) { - return make_float32((float32_val(a) & 0x7fffffff) | (sign << 31)); -} - -#define float32_zero make_float32(0) -#define float32_one make_float32(0x3f800000) -#define float32_ln2 make_float32(0x3f317218) -#define float32_pi make_float32(0x40490fdb) -#define float32_half make_float32(0x3f000000) -#define float32_infinity make_float32(0x7f800000) - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float32 float32_default_nan; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int16 float64_to_int16_round_to_zero(float64 STATUS_PARAM); -uint16 float64_to_uint16_round_to_zero(float64 STATUS_PARAM); -int32 float64_to_int32(float64 STATUS_PARAM); -int32 float64_to_int32_round_to_zero(float64 STATUS_PARAM); -uint32 float64_to_uint32(float64 STATUS_PARAM); -uint32 float64_to_uint32_round_to_zero(float64 STATUS_PARAM); -int64 float64_to_int64(float64 STATUS_PARAM); -int64 float64_to_int64_round_to_zero(float64 STATUS_PARAM); -uint64 float64_to_uint64(float64 a STATUS_PARAM); -uint64 float64_to_uint64_round_to_zero(float64 a STATUS_PARAM); -float32 float64_to_float32(float64 STATUS_PARAM); -floatx80 float64_to_floatx80(float64 STATUS_PARAM); -float128 float64_to_float128(float64 STATUS_PARAM); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int(float64 STATUS_PARAM); -float64 float64_trunc_to_int(float64 STATUS_PARAM); -float64 float64_add(float64, float64 STATUS_PARAM); -float64 float64_sub(float64, float64 STATUS_PARAM); -float64 float64_mul(float64, float64 STATUS_PARAM); -float64 float64_div(float64, float64 STATUS_PARAM); -float64 float64_rem(float64, float64 STATUS_PARAM); -float64 float64_muladd(float64, float64, float64, int STATUS_PARAM); -float64 float64_sqrt(float64 STATUS_PARAM); -float64 float64_log2(float64 STATUS_PARAM); -int float64_eq(float64, float64 STATUS_PARAM); -int float64_le(float64, float64 STATUS_PARAM); -int float64_lt(float64, float64 STATUS_PARAM); -int float64_unordered(float64, float64 STATUS_PARAM); -int float64_eq_quiet(float64, float64 STATUS_PARAM); -int float64_le_quiet(float64, float64 STATUS_PARAM); -int float64_lt_quiet(float64, float64 STATUS_PARAM); -int float64_unordered_quiet(float64, float64 STATUS_PARAM); -int float64_compare(float64, float64 STATUS_PARAM); -int float64_compare_quiet(float64, float64 STATUS_PARAM); -float64 float64_min(float64, float64 STATUS_PARAM); -float64 float64_max(float64, float64 STATUS_PARAM); -int float64_is_quiet_nan(float64 a); -int float64_is_signaling_nan(float64); -float64 float64_maybe_silence_nan(float64); -float64 float64_scalbn(float64, int STATUS_PARAM); - -SINLINE float64 float64_abs(float64 a) { - /* Note that abs does *not* handle NaN specially, nor does - * it flush denormal inputs to zero. - */ - return make_float64(float64_val(a) & 0x7fffffffffffffffLL); -} - -SINLINE float64 float64_chs(float64 a) { - /* Note that chs does *not* handle NaN specially, nor does - * it flush denormal inputs to zero. - */ - return make_float64(float64_val(a) ^ 0x8000000000000000LL); -} - -SINLINE int float64_is_infinity(float64 a) { - return (float64_val(a) & 0x7fffffffffffffffLL) == 0x7ff0000000000000LL; -} - -SINLINE int float64_is_neg(float64 a) { - return float64_val(a) >> 63; -} - -SINLINE int float64_is_zero(float64 a) { - return (float64_val(a) & 0x7fffffffffffffffLL) == 0; -} - -SINLINE int float64_is_any_nan(float64 a) { - return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL); -} - -SINLINE int float64_is_zero_or_denormal(float64 a) { - return (float64_val(a) & 0x7ff0000000000000LL) == 0; -} - -SINLINE float64 float64_set_sign(float64 a, int sign) { - return make_float64((float64_val(a) & 0x7fffffffffffffffULL) | ((int64_t) sign << 63)); -} - -#define float64_zero make_float64(0) -#define float64_one make_float64(0x3ff0000000000000LL) -#define float64_ln2 make_float64(0x3fe62e42fefa39efLL) -#define float64_pi make_float64(0x400921fb54442d18LL) -#define float64_half make_float64(0x3fe0000000000000LL) -#define float64_infinity make_float64(0x7ff0000000000000LL) - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float64 float64_default_nan; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 floatx80_to_int32(floatx80 STATUS_PARAM); -int32 floatx80_to_int32_round_to_zero(floatx80 STATUS_PARAM); -int64 floatx80_to_int64(floatx80 STATUS_PARAM); -int64 floatx80_to_int64_round_to_zero(floatx80 STATUS_PARAM); -float32 floatx80_to_float32(floatx80 STATUS_PARAM); -float64 floatx80_to_float64(floatx80 STATUS_PARAM); -float128 floatx80_to_float128(floatx80 STATUS_PARAM); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int(floatx80 STATUS_PARAM); -floatx80 floatx80_add(floatx80, floatx80 STATUS_PARAM); -floatx80 floatx80_sub(floatx80, floatx80 STATUS_PARAM); -floatx80 floatx80_mul(floatx80, floatx80 STATUS_PARAM); -floatx80 floatx80_div(floatx80, floatx80 STATUS_PARAM); -floatx80 floatx80_rem(floatx80, floatx80 STATUS_PARAM); -floatx80 floatx80_sqrt(floatx80 STATUS_PARAM); -int floatx80_eq(floatx80, floatx80 STATUS_PARAM); -int floatx80_le(floatx80, floatx80 STATUS_PARAM); -int floatx80_lt(floatx80, floatx80 STATUS_PARAM); -int floatx80_unordered(floatx80, floatx80 STATUS_PARAM); -int floatx80_eq_quiet(floatx80, floatx80 STATUS_PARAM); -int floatx80_le_quiet(floatx80, floatx80 STATUS_PARAM); -int floatx80_lt_quiet(floatx80, floatx80 STATUS_PARAM); -int floatx80_unordered_quiet(floatx80, floatx80 STATUS_PARAM); -int floatx80_compare(floatx80, floatx80 STATUS_PARAM); -int floatx80_compare_quiet(floatx80, floatx80 STATUS_PARAM); -int floatx80_is_quiet_nan(floatx80); -int floatx80_is_signaling_nan(floatx80); -floatx80 floatx80_maybe_silence_nan(floatx80); -floatx80 floatx80_scalbn(floatx80, int STATUS_PARAM); - -SINLINE floatx80 floatx80_abs(floatx80 a) { - a.high &= 0x7fff; - return a; -} - -SINLINE floatx80 floatx80_chs(floatx80 a) { - a.high ^= 0x8000; - return a; -} - -SINLINE int floatx80_is_infinity(floatx80 a) { - return (a.high & 0x7fff) == 0x7fff && a.low == 0x8000000000000000LL; -} - -SINLINE int floatx80_is_neg(floatx80 a) { - return a.high >> 15; -} - -SINLINE int floatx80_is_zero(floatx80 a) { - return (a.high & 0x7fff) == 0 && a.low == 0; -} - -SINLINE int floatx80_is_zero_or_denormal(floatx80 a) { - return (a.high & 0x7fff) == 0; -} - -SINLINE int floatx80_is_any_nan(floatx80 a) { - return ((a.high & 0x7fff) == 0x7fff) && (a.low << 1); -} - -#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL) -#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL) -#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL) -#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL) -#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL) -#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL) - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ -extern const floatx80 floatx80_default_nan; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float128_to_int32(float128 STATUS_PARAM); -int32 float128_to_int32_round_to_zero(float128 STATUS_PARAM); -int64 float128_to_int64(float128 STATUS_PARAM); -int64 float128_to_int64_round_to_zero(float128 STATUS_PARAM); -float32 float128_to_float32(float128 STATUS_PARAM); -float64 float128_to_float64(float128 STATUS_PARAM); -floatx80 float128_to_floatx80(float128 STATUS_PARAM); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_round_to_int(float128 STATUS_PARAM); -float128 float128_add(float128, float128 STATUS_PARAM); -float128 float128_sub(float128, float128 STATUS_PARAM); -float128 float128_mul(float128, float128 STATUS_PARAM); -float128 float128_div(float128, float128 STATUS_PARAM); -float128 float128_rem(float128, float128 STATUS_PARAM); -float128 float128_sqrt(float128 STATUS_PARAM); -int float128_eq(float128, float128 STATUS_PARAM); -int float128_le(float128, float128 STATUS_PARAM); -int float128_lt(float128, float128 STATUS_PARAM); -int float128_unordered(float128, float128 STATUS_PARAM); -int float128_eq_quiet(float128, float128 STATUS_PARAM); -int float128_le_quiet(float128, float128 STATUS_PARAM); -int float128_lt_quiet(float128, float128 STATUS_PARAM); -int float128_unordered_quiet(float128, float128 STATUS_PARAM); -int float128_compare(float128, float128 STATUS_PARAM); -int float128_compare_quiet(float128, float128 STATUS_PARAM); -int float128_is_quiet_nan(float128); -int float128_is_signaling_nan(float128); -float128 float128_maybe_silence_nan(float128); -float128 float128_scalbn(float128, int STATUS_PARAM); - -SINLINE float128 float128_abs(float128 a) { - a.high &= 0x7fffffffffffffffLL; - return a; -} - -SINLINE float128 float128_chs(float128 a) { - a.high ^= 0x8000000000000000LL; - return a; -} - -SINLINE int float128_is_infinity(float128 a) { - return (a.high & 0x7fffffffffffffffLL) == 0x7fff000000000000LL && a.low == 0; -} - -SINLINE int float128_is_neg(float128 a) { - return a.high >> 63; -} - -SINLINE int float128_is_zero(float128 a) { - return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0; -} - -SINLINE int float128_is_zero_or_denormal(float128 a) { - return (a.high & 0x7fff000000000000LL) == 0; -} - -SINLINE int float128_is_any_nan(float128 a) { - return ((a.high >> 48) & 0x7fff) == 0x7fff && ((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0)); -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float128 float128_default_nan; - -#endif /* !SOFTFLOAT_H */ diff --git a/src/base/emu-i386/simx86/syncpu.h b/src/base/emu-i386/simx86/syncpu.h index f9fdbce..b84f2cc 100644 --- a/src/base/emu-i386/simx86/syncpu.h +++ b/src/base/emu-i386/simx86/syncpu.h @@ -54,7 +54,7 @@ typedef struct { /* ------------------------------------------------ */ /*80*/ long double *fpregs; /*84*/ PADDING32BIT(1) -/*88*/ unsigned long long reserve; +/*88*/ unsigned long long EMUtime; /*90*/ SDTR gs_cache; /*9c*/ SDTR fs_cache; /*a8*/ SDTR es_cache; @@ -102,7 +102,7 @@ typedef struct { /* ------------------------------------------------ */ /*60*/ unsigned short sigalrm_pending, sigprof_pending; /*64*/ unsigned int StackMask; -/*68*/ unsigned int reserve2; +/*68*/ unsigned int mem_base; /*6c*/ unsigned int df_increments; /* either 0x040201 or 0xfcfeff */ /* begin of cr array */ /*70*/ unsigned int cr[5]; /* only cr[0] is used in compiled code */ @@ -147,17 +147,17 @@ typedef struct { unsigned short TR_SEL; DTR TR; + /* if not NULL, points to emulated FPU state + if NULL, emulator uses FPU instructions, so flags that + dosemu needs to restore its own FPU environment. */ + fpregset_t fpstate; + void (*stub_read_8)(void); void (*stub_read_16)(void); void (*stub_read_32)(void); /* should be moved to TSS once implemented */ struct revectored_struct int_revectored; - - /* if not NULL, points to emulated FPU state - if NULL, emulator uses FPU instructions, so flags that - dosemu needs to restore its own FPU environment. */ - emu_fpregset_t fpstate; } SynCPU; union _SynCPU { @@ -208,10 +208,11 @@ extern union _SynCPU TheCPU_union; #define Ofs_CR0 (unsigned char)(offsetof(SynCPU,cr[0])-SCBASE) #define Ofs_CR2 (unsigned char)(offsetof(SynCPU,cr2)-SCBASE) #define Ofs_STACKM (unsigned char)(offsetof(SynCPU,StackMask)-SCBASE) -//#define Ofs_ETIME (unsigned char)(offsetof(SynCPU,EMUtime)-SCBASE) +#define Ofs_ETIME (unsigned char)(offsetof(SynCPU,EMUtime)-SCBASE) #define Ofs_RZERO (unsigned char)(offsetof(SynCPU,rzero)-SCBASE) #define Ofs_SIGAPEND (unsigned char)(offsetof(SynCPU,sigalrm_pending)-SCBASE) #define Ofs_SIGFPEND (unsigned char)(offsetof(SynCPU,sigprof_pending)-SCBASE) +#define Ofs_MEMBASE (unsigned char)(offsetof(SynCPU,mem_base)-SCBASE) #define Ofs_DF_INCREMENTS (unsigned char)(offsetof(SynCPU,df_increments)-SCBASE) #define Ofs_FPR (unsigned char)(offsetof(SynCPU,fpregs)-SCBASE) @@ -292,12 +293,12 @@ extern union _SynCPU TheCPU_union; #define FS_DTR TheCPU.fs_cache #define GS_DTR TheCPU.gs_cache -#define LONG_CS TheCPU.cs_cache.BoundL -#define LONG_DS TheCPU.ds_cache.BoundL -#define LONG_ES TheCPU.es_cache.BoundL -#define LONG_SS TheCPU.ss_cache.BoundL -#define LONG_FS TheCPU.fs_cache.BoundL -#define LONG_GS TheCPU.gs_cache.BoundL +#define LONG_CS (TheCPU.cs_cache.BoundL - TheCPU.mem_base) +#define LONG_DS (TheCPU.ds_cache.BoundL - TheCPU.mem_base) +#define LONG_ES (TheCPU.es_cache.BoundL - TheCPU.mem_base) +#define LONG_SS (TheCPU.ss_cache.BoundL - TheCPU.mem_base) +#define LONG_FS (TheCPU.fs_cache.BoundL - TheCPU.mem_base) +#define LONG_GS (TheCPU.gs_cache.BoundL - TheCPU.mem_base) extern char OVERR_DS, OVERR_SS; diff --git a/src/base/emu-i386/simx86/tables.c b/src/base/emu-i386/simx86/tables.c index 02d2df0..ca5678f 100644 --- a/src/base/emu-i386/simx86/tables.c +++ b/src/base/emu-i386/simx86/tables.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * ***************************************************************************/ diff --git a/src/base/emu-i386/simx86/trees.c b/src/base/emu-i386/simx86/trees.c index 022aa18..b271e90 100644 --- a/src/base/emu-i386/simx86/trees.c +++ b/src/base/emu-i386/simx86/trees.c @@ -27,7 +27,7 @@ * Additional copyright notes: * * 1. The kernel-level vm86 handling was taken out of the Linux kernel - * (linux/arch/i386/kernel/vm86.c). This code originally was written by + * (linux/arch/i386/kernel/vm86.c). This code originaly was written by * Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen. * * 2. The tree handling routines were adapted from libavl: @@ -64,7 +64,7 @@ int NodesExecd = 0; int CleanFreq = 8; int CreationIndex = 0; -#if PROFILE +#ifdef PROFILE int MaxDepth = 0; int MaxNodes = 0; int MaxNodeSize = 0; @@ -182,14 +182,14 @@ static TNode *avltr_probe (const int key, int *found) p = q; k++; /**/ if (k>=AVL_MAX_HEIGHT) leavedos_main(0x777); -#if PROFILE +#ifdef PROFILE if (debug_level('e')) if (k>MaxDepth) MaxDepth=k; #endif } tree->count++; ninodes = tree->count; -#if PROFILE +#ifdef PROFILE if (debug_level('e')) if (ninodes > MaxNodes) MaxNodes = ninodes; #endif q->bal = 0; @@ -531,7 +531,7 @@ void avltr_delete (const int key) static void avltr_init(void) { #ifdef HOST_ARCH_X86 - if (!config.cpusim) { + if (!CONFIG_CPUSIM) { int i; TNode *G; @@ -565,7 +565,7 @@ static void avltr_init(void) void avltr_destroy(void) { avltr_tree *tree; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; #endif @@ -576,7 +576,7 @@ void avltr_destroy(void) #ifdef DEBUG_TREE DumpTree (tLog); #endif -#if PROFILE +#ifdef PROFILE if (debug_level('e')) t0 = GETTSC(); #endif @@ -617,7 +617,7 @@ void avltr_destroy(void) } quit: free(InstrMeta); -#if PROFILE +#ifdef PROFILE if (debug_level('e')) { TreeCleanups++; CleanupTime += (GETTSC() - t0); @@ -671,7 +671,7 @@ static void CheckLinks(void) unsigned char *p; linkdesc *L, *T; backref *B; - int n, brt; + int n; for (;;) { /* walk to next node */ @@ -714,17 +714,15 @@ static void CheckLinks(void) goto nquit; } n = 0; - brt = 0; while (B) { if (B->ref==&G->mblock->bkptr) { n++; - brt += B->branch; if (debug_level('e')>5) e_printf(" T: backref %d from %p\n",n,GL); } B = B->next; } - if (n < 1 || n > 2 || (n == 2 && brt != 'N' + 'T')) { - error("0 or >1 backrefs1 (%i)\n", n); goto nquit; + if (n!=1) { + error("0 or >1 backrefs\n"); goto nquit; } } else { @@ -752,17 +750,15 @@ static void CheckLinks(void) goto nquit; } n = 0; - brt = 0; while (B) { if (B->ref==&G->mblock->bkptr) { n++; - brt += B->branch; if (debug_level('e')>5) e_printf(" N: backref %d from %p\n",n,GL); } B = B->next; } - if (n < 1 || n > 2 || (n == 2 && brt != 'N' + 'T')) { - error("0 or >1 backrefs2 (%i)\n", n); goto nquit; + if (n!=1) { + error("0 or >1 backrefs\n"); goto nquit; } } else if (L->nt_link.abs) { @@ -866,15 +862,16 @@ static int TraverseAndClean(void) { int cnt = 0; TNode *G; -#if PROFILE + static hitimer_t bT = 0; +#ifdef PROFILE hitimer_t t0 = 0; if (debug_level('e')) t0 = GETTSC(); #endif - if (Traverser.init == 0) { Traverser.p = G = &CollectTree.root; Traverser.init = 1; + if (debug_level('e')>2) bT = GETTSC(); } else G = Traverser.p; @@ -882,6 +879,11 @@ static int TraverseAndClean(void) /* walk to next node */ G = NEXTNODE(G); if (G == &CollectTree.root) { + if (debug_level('e')>2) { + hitimer_t bt1 = GETTSC(); + dbug_printf("*\tRestart traversing n=%d %16lld\n",ninodes,(long long)(bt1-bT)); + bT = bt1; + } G = NEXTNODE(G); if (G == &CollectTree.root) return 0; @@ -906,7 +908,7 @@ static int TraverseAndClean(void) G->key,ninodes,G->alive); Traverser.p = G; } -#if PROFILE +#ifdef PROFILE if (debug_level('e')) CleanupTime += (GETTSC() - t0); #endif return cnt; @@ -917,14 +919,14 @@ static int TraverseAndClean(void) * The code is linearly stored in the CodeBuf and its associated structures * are in the InstrMeta array. We allocate a buffer and copy the code, then * we copy the sequence data from the head element of InstrMeta. In this - * process we lose all the correspondences between original code and compiled + * process we lose all the correspondances between original code and compiled * code addresses. At the end, we reset both CodeBuf and InstrMeta to prepare * for a new sequence. */ TNode *Move2Tree(IMeta *I0, CodeBuf *GenCodeBuf) { TNode *nG = NULL; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; if (debug_level('e')) t0 = GETTSC(); #endif @@ -975,7 +977,7 @@ TNode *Move2Tree(IMeta *I0, CodeBuf *GenCodeBuf) nG->seqbase = I0->seqbase; nG->seqlen = I0->seqlen; nG->seqnum = I0->ncount; -#if PROFILE +#ifdef PROFILE if (debug_level('e')) if (nG->len > MaxNodeSize) MaxNodeSize = nG->len; #endif nG->len = len = I0->totlen; @@ -984,7 +986,7 @@ TNode *Move2Tree(IMeta *I0, CodeBuf *GenCodeBuf) findtree_cache[key&FINDTREE_CACHE_HASH_MASK] = nG; /* allocate the extra memory used by the node. This includes the - * translated code plus the table of correspondences between source + * translated code plus the table of correspondances between source * and translated addresses. * The first longword of the memory block is special; it stores a * back-pointer to the node. This because nodes can be moved in @@ -1045,7 +1047,7 @@ TNode *Move2Tree(IMeta *I0, CodeBuf *GenCodeBuf) #endif CurrIMeta = -1; memset(&InstrMeta[0],0,sizeof(IMeta)); -#if PROFILE +#ifdef PROFILE if (debug_level('e')) AddTime += (GETTSC() - t0); #endif return nG; @@ -1056,7 +1058,7 @@ TNode *FindTree(int key) { TNode *I; static int tccount=0; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; #endif @@ -1072,7 +1074,7 @@ TNode *FindTree(int key) if (debug_level('e')) { if (debug_level('e')>4) e_printf("Found key %08x via cache\n", key); -#if PROFILE +#ifdef PROFILE NodesFastFound++; #endif } @@ -1082,7 +1084,7 @@ TNode *FindTree(int key) if (!e_querymark(key, 1)) return NULL; -#if PROFILE +#ifdef PROFILE if (debug_level('e')) t0 = GETTSC(); #endif I = CollectTree.root.link[0]; @@ -1106,7 +1108,7 @@ TNode *FindTree(int key) if (debug_level('e')>3) e_printf("Found key %08x\n",key); I->alive = NODELIFE(I); findtree_cache[key&FINDTREE_CACHE_HASH_MASK] = I; -#if PROFILE +#ifdef PROFILE if (debug_level('e')) { NodesFound++; SearchTime += (GETTSC() - t0); @@ -1116,7 +1118,7 @@ TNode *FindTree(int key) } endsrch: -#if PROFILE +#ifdef PROFILE if (debug_level('e')) SearchTime += (GETTSC() - t0); #endif if ((ninodes>500) && (((++tccount) >= CleanFreq) || NodesCleaned)) { @@ -1129,7 +1131,7 @@ endsrch: if (debug_level('e')) { if (debug_level('e')>4) e_printf("Not found key %08x\n",key); -#if PROFILE +#ifdef PROFILE NodesNotFound++; #endif } @@ -1180,11 +1182,10 @@ static void BreakNode(TNode *G, unsigned char *eip) e_printf("============ Node %08x break failed\n",G->key); } -static TNode *DoDelNode(TNode *G) +static TNode *DoDelNode(int key) { - if (Traverser.p == G) - Traverser.p = NEXTNODE(G); - avltr_delete(G->key); + avltr_delete(key); + Traverser.init = 0; return CollectTree.root.link[0]; } @@ -1193,7 +1194,7 @@ int InvalidateNodeRange(int al, int len, unsigned char *eip) TNode *G; int ah; int cleaned = 0; -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; if (debug_level('e')) t0 = GETTSC(); @@ -1218,7 +1219,7 @@ int InvalidateNodeRange(int al, int len, unsigned char *eip) if (G2 == &CollectTree.root || G2->key > al) { if (G->alive <= 0) { /* remove dead node as it may be overlapped by good one */ - G = DoDelNode(G); + G = DoDelNode(G->key); continue; } break; @@ -1226,7 +1227,7 @@ int InvalidateNodeRange(int al, int len, unsigned char *eip) } else { if (G->alive <= 0) { - G = DoDelNode(G); + G = DoDelNode(G->key); continue; } break; @@ -1270,7 +1271,7 @@ quit: if (debug_level('e') && e_querymark(al, len)) error("simx86: InvalidateNodeRange did not clear all code for %#08x, len=%x\n", al, len); -#if PROFILE +#ifdef PROFILE if (debug_level('e')) CleanupTime += (GETTSC() - t0); #endif return cleaned; @@ -1281,55 +1282,25 @@ quit: ///////////////////////////////////////////////////////////////////////////// -static void do_invalidate(unsigned data, int cnt) -{ - cnt = PAGE_ALIGN(data+cnt-1) - (data & _PAGE_MASK); - data &= _PAGE_MASK; -#ifdef HOST_ARCH_X86 - /* e_querymprotrange prevents coming here for sim */ - assert (!config.cpusim); - InvalidateNodeRange(data, cnt, 0); -#endif -} void e_invalidate(unsigned data, int cnt) { - if (!IS_EMU_JIT()) + if (!IS_EMU()) return; /* nothing to invalidate if there are no page protections */ if (!e_querymprotrange(data, cnt)) return; /* for low mappings only invalidate if code, not if data */ - if (data < LOWMEM_SIZE + HMASIZE) { + if (LINEAR2UNIX(data) != MEM_BASE32(data)) { #ifdef HOST_ARCH_X86 - /* e_querymprotrange prevents coming here for sim */ - assert (!config.cpusim); - if (e_querymark(data, cnt)) { + if (!CONFIG_CPUSIM && e_querymark(data, cnt)) // no need to invalidate the whole page here, // as the page does not need to be unprotected InvalidateNodeRange(data, cnt, 0); - return; - } #endif return; } - do_invalidate(data, cnt); -} - -void e_invalidate_pa(unsigned pa, int cnt) -{ - dosaddr_t addr = physaddr_to_dosaddr(pa, cnt); - if (addr == (dosaddr_t)-1) - return; - e_invalidate(addr, cnt); -} - -void e_invalidate_full_pa(unsigned pa, int cnt) -{ - dosaddr_t addr = physaddr_to_dosaddr(pa, cnt); - if (addr == (dosaddr_t)-1) - return; - e_invalidate_full(addr, cnt); + e_invalidate_full(data, cnt); } /* invalidate and unprotect even if we hit only data. @@ -1337,25 +1308,15 @@ void e_invalidate_full_pa(unsigned pa, int cnt) * Otherwise use e_invalidate() */ void e_invalidate_full(unsigned data, int cnt) { - if (!IS_EMU_JIT()) + if (!IS_EMU()) return; - /* nothing to invalidate if there are no page protections */ - if (!e_querymprotrange(data, cnt)) - return; - do_invalidate(data, cnt); -} - -int e_invalidate_page_full(unsigned data) -{ - int cnt = PAGE_SIZE; - if (!IS_EMU_JIT()) - return 0; - data &= _PAGE_MASK; - /* nothing to invalidate if there are no page protections */ - if (!e_querymprotrange(data, cnt)) - return 0; - do_invalidate(data, cnt); - return 1; + cnt = PAGE_ALIGN(data+cnt-1) - (data & PAGE_MASK); + data &= PAGE_MASK; +#ifdef HOST_ARCH_X86 + if (!CONFIG_CPUSIM) + InvalidateNodeRange(data, cnt, 0); +#endif + invalidate_unprotected_page_cache(data, cnt); } ///////////////////////////////////////////////////////////////////////////// @@ -1365,23 +1326,27 @@ int e_invalidate_page_full(unsigned data) static void CleanIMeta(void) { -#if PROFILE +#ifdef PROFILE hitimer_t t0 = 0; if (debug_level('e')) t0 = GETTSC(); #endif memset(InstrMeta,0,sizeof(IMeta)); -#if PROFILE +#ifdef PROFILE if (debug_level('e')) CleanupTime += (GETTSC() - t0); #endif } +#endif // HOST_ARCH_X86 + ///////////////////////////////////////////////////////////////////////////// int NewIMeta(int npc, int *rc) { -#if PROFILE +#ifdef HOST_ARCH_X86 + if (!CONFIG_CPUSIM) { +#ifdef PROFILE hitimer_t t0 = 0; if (debug_level('e')) t0 = GETTSC(); @@ -1419,7 +1384,7 @@ int NewIMeta(int npc, int *rc) e_printf("Metadata %03d PC=%08x flags=%x(%x) ng=%d\n", CurrIMeta,I->npc,I->flags,I0->flags,I->ngen); } -#if PROFILE +#ifdef PROFILE if (debug_level('e')) AddTime += (GETTSC() - t0); #endif CurrIMeta++; @@ -1430,13 +1395,23 @@ int NewIMeta(int npc, int *rc) } *rc = 0; quit: -#if PROFILE +#ifdef PROFILE if (debug_level('e')) AddTime += (GETTSC() - t0); #endif return -1; + } +#endif // HOST_ARCH_X86 + if (CurrIMeta==0) { // no open code sequences + if (debug_level('e')>2) e_printf("============ Opening sequence at %08x\n",npc); + } + if (CurrIMeta >= MAXINODES) { + *rc = -1; + return -1; + } + CurrIMeta++; InstrMeta[CurrIMeta].ngen=0; InstrMeta[CurrIMeta].flags=0; + return CurrIMeta; } -#endif // HOST_ARCH_X86 ///////////////////////////////////////////////////////////////////////////// @@ -1459,7 +1434,7 @@ void CollectStat (void) int i, m = 0; #ifdef SHOW_STAT int csm = config.CPUSpeedInMhz*1000; -// xCST[cstx].a = TheCPU.EMUtime; + xCST[cstx].a = TheCPU.EMUtime; xCST[cstx].s = TheCPU.sigprof_pending; xCST[cstx].b = ninodes; xCST[cstx].c = NodesParsed; @@ -1512,14 +1487,14 @@ void InitTrees(void) { g_printf("InitTrees\n"); #ifdef HOST_ARCH_X86 - if (!config.cpusim) + if (!CONFIG_CPUSIM) TNodePool = calloc(NODES_IN_POOL, sizeof(TNode)); #endif avltr_init(); #ifdef HOST_ARCH_X86 - if (!config.cpusim && debug_level('e')>1) { + if (!CONFIG_CPUSIM && debug_level('e')>1) { e_printf("Root tree node at %p\n",&CollectTree.root); e_printf("TNode pool at %p\n",TNodePool); } @@ -1528,7 +1503,7 @@ void InitTrees(void) CleanFreq = 8; cstx = xCS1 = 0; CreationIndex = 0; -#if PROFILE +#ifdef PROFILE if (debug_level('e')) { MaxDepth = MaxNodes = MaxNodeSize = 0; TotalNodesParsed = TotalNodesExecd = 0; @@ -1545,12 +1520,12 @@ void EndGen(void) int csm = config.CPUSpeedInMhz*1000; #endif #ifdef HOST_ARCH_X86 - if (!config.cpusim) + if (!CONFIG_CPUSIM) CleanIMeta(); #endif CurrIMeta = -1; #ifdef HOST_ARCH_X86 - if (!config.cpusim) { + if (!CONFIG_CPUSIM) { avltr_destroy(); free(TNodePool); TNodePool=NULL; } diff --git a/src/base/init/Makefile b/src/base/init/Makefile index 3ad9b95..c21c6de 100644 --- a/src/base/init/Makefile +++ b/src/base/init/Makefile @@ -22,6 +22,10 @@ OBJS=parser.o lex.yy.o $(CFILES:.c=.o) all: lib +init.o: $(top_builddir)/src/base/bios/x86/bios_data.xxd + +install: + dosemu_c.c : $(top_srcdir)/etc/dosemu.conf echo 'char dosemu_conf[] = \' > $@ sed -e 's/^# $$_/$$_/g' \ diff --git a/src/base/init/config.c b/src/base/init/config.c index 13a5fe9..5e500ff 100644 --- a/src/base/init/config.c +++ b/src/base/init/config.c @@ -60,20 +60,20 @@ char **dosemu_argv; char *dosemu_proc_self_exe = NULL; int dosemu_proc_self_maps_fd = -1; +static void check_for_env_autoexec_or_config(void); static void usage(char *basename); const char *config_script_name = DEFAULT_CONFIG_SCRIPT; const char *dosemu_loglevel_file_path = "/etc/" DOSEMU_LOGLEVEL; -char *dosemu_rundir_path; -char *dosemu_localdir_path; +const char *dosemu_rundir_path = "~/" LOCALDIR_BASE_NAME "/run"; +const char *dosemu_localdir_path = "~/" LOCALDIR_BASE_NAME; -char *dosemu_lib_dir_path; -const char *dosemu_exec_dir_path = DOSEMUEXEC_DEFAULT; -char *dosemu_plugin_dir_path; -char *commands_path; -char *dosemu_image_dir_path; -char *dosemu_drive_c_path; -char keymaploadbase_default[] = PREFIX "/share/"; +const char *dosemu_lib_dir_path = DOSEMULIB_DEFAULT; +const char *dosemu_plugin_dir_path = DOSEMUPLUGINDIR; +const char *commands_path = DOSEMUCMDS_DEFAULT; +const char *dosemu_image_dir_path = DOSEMUIMAGE_DEFAULT; +const char *dosemu_drive_c_path = DRIVE_C_DEFAULT; +char keymaploadbase_default[] = DOSEMULIB_DEFAULT "/"; char *keymap_load_base_path = keymaploadbase_default; const char *keymap_dir_path = "keymap/"; const char *owner_tty_locks = "uucp"; @@ -86,7 +86,6 @@ char *fddir_default; char *comcom_dir; char *fddir_boot; char *xbat_dir; -static char *dosemu_uid; struct config_info config; #define STRING_STORE_SIZE 10 @@ -113,10 +112,10 @@ int cpu_override (int cpu) return CPU_286; case 5: case 6: return CPU_586; - /* fall through */ + /* fall thru */ case 4: return CPU_486; - /* fall through */ + /* fall thru */ case 3: return CPU_386; } @@ -169,8 +168,8 @@ void dump_config_status(void (*printfunc)(const char *, ...)) (*print)("CPUclock %g MHz\ncpu_spd 0x%lx\ncpu_tick_spd 0x%lx\n", (((double)LLF_US)/config.cpu_spd), config.cpu_spd, config.cpu_tick_spd); - (*print)("pci %d\nmathco %d\nsmp %d\n", - config.pci, config.mathco, config.smp); + (*print)("pci %d\nrdtsc %d\nmathco %d\nsmp %d\n", + config.pci, config.rdtsc, config.mathco, config.smp); (*print)("cpuspeed %d\n", config.CPUSpeedInMhz); if (config_check_only) mapping_init(); @@ -182,10 +181,8 @@ void dump_config_status(void (*printfunc)(const char *, ...)) config.mem_size, config.ext_mem); (*print)("ems_size 0x%x\nems_frame 0x%x\n", config.ems_size, config.ems_frame); - (*print)("umb_a0 %i\numb_b0 %i\numb_f0 %i\ndos_up %i\n", - config.umb_a0, config.umb_b0, config.umb_f0, config.dos_up); - (*print)("dpmi 0x%x\ndpmi_base 0x%x\npm_dos_api %i\nignore_djgpp_null_derefs %i\n", - config.dpmi, config.dpmi_base, config.pm_dos_api, config.no_null_checks); + (*print)("umb_a0 %i\numb_b0 %i\numb_f0 %i\ndpmi 0x%x\ndpmi_lin_rsv_base 0x%x\ndpmi_lin_rsv_size 0x%x\npm_dos_api %i\nignore_djgpp_null_derefs %i\n", + config.umb_a0, config.umb_b0, config.umb_f0, config.dpmi, config.dpmi_lin_rsv_base, config.dpmi_lin_rsv_size, config.pm_dos_api, config.no_null_checks); (*print)("mapped_bios %d\nvbios_file %s\n", config.mapped_bios, (config.vbios_file ? config.vbios_file :"")); (*print)("vbios_copy %d\nvbios_seg 0x%x\nvbios_size 0x%x\n", @@ -214,15 +211,12 @@ void dump_config_status(void (*printfunc)(const char *, ...)) config.vgaemu_memsize); (*print)("SDL_hwrend %d\nSDL_fonts \"%s\"\n", config.sdl_hwrend, config.sdl_fonts); - (*print)("SDL_clip_native %d\n", - config.sdl_clip_native); (*print)("vesamode_list %p\nX_lfb %d\nX_pm_interface %d\n", config.vesamode_list, config.X_lfb, config.X_pm_interface); (*print)("X_font \"%s\"\n", config.X_font); (*print)("vga_fonts %i\n", config.vga_fonts); (*print)("X_mgrab_key \"%s\"\n", config.X_mgrab_key); (*print)("X_background_pause %d\n", config.X_background_pause); - (*print)("X_noclose %d\n", config.X_noclose); switch (config.chipset) { case PLAINVGA: s = "plainvga"; break; @@ -316,7 +310,6 @@ void dump_config_status(void (*printfunc)(const char *, ...)) (*print)("pcm_hpf %i\nmidi_file %s\nwav_file %s\n", config.pcm_hpf, config.midi_file, config.wav_file); (*print)("\ncli_timeout %d\n", config.cli_timeout); - (*print)("\ntimer_tweaks %d\n", config.timer_tweaks); (*print)("\nJOYSTICK:\njoy_device0 \"%s\"\njoy_device1 \"%s\"\njoy_dos_min %i\njoy_dos_max %i\njoy_granularity %i\njoy_latency %i\n", config.joy_device[0], config.joy_device[1], config.joy_dos_min, config.joy_dos_max, config.joy_granularity, config.joy_latency); (*print)("\nFS:\nset_int_hooks %i\nforce_int_revect %i\nforce_fs_redirect %i\n\n", @@ -363,62 +356,45 @@ static void our_envs_init(void) setenv("DOSEMU_EUID", buf, 1); sprintf(buf, "%d", getuid()); setenv("DOSEMU_UID", buf, 1); - sprintf(buf, "%d", get_orig_uid()); - dosemu_uid = strdup(buf); } static int check_comcom(const char *dir) { - char buf[1024]; char *path; int err; - ssize_t res; path = assemble_path(dir, "command.com"); err = access(path, R_OK); - res = readlink(path, buf, sizeof(buf) - 1); free(path); - if (err == 0) { - if (res == -1) - return 1; - /* have symlink */ - buf[res] = '\0'; - if (strncmp(buf, "comcom64.exe", res) == 0) { -#ifndef USE_DJDEV64 - error("comcom64 support not compiled in\n"); - return 0; -#endif - dbug_printf("booting with comcom64\n"); - } + if (err == 0) return 1; - } - path = assemble_path(dir, "comcom64.exe"); - err = access(path, R_OK); - free(path); - if (err == 0) { - error("comcom64 found in %s but command.com symlink is missing\n", dir); - return 0; - } path = assemble_path(dir, "comcom32.exe"); err = access(path, R_OK); free(path); - if (err == 0) { + if (err == 0) error("comcom32 found in %s but command.com symlink is missing\n", dir); - return 0; - } return 0; } static void comcom_hook(struct sys_dsc *sfiles, fatfs_t *fat) { + char buf[1024]; + char *comcom; + ssize_t res; const char *dir = fatfs_get_host_dir(fat); if (strcmp(dir, comcom_dir) == 0) { - if (strstr(dir, "32") != NULL) - sfiles[CMD_IDX].flags |= FLG_COMCOM32; - else - sfiles[CMD_IDX].flags |= FLG_COMCOM64; + sfiles[CMD_IDX].flags |= FLG_COMCOM32; + return; } + comcom = assemble_path(dir, "command.com"); + res = readlink(comcom, buf, sizeof(buf)); + free(comcom); + if (res == -1) + return; + if (strncmp(buf, comcom_dir, strlen(comcom_dir)) != 0) + return; + sfiles[CMD_IDX].flags |= FLG_COMCOM32; } static int check_freedos(const char *xdir) @@ -509,10 +485,6 @@ static void set_freedos_dir(void) comcom_dir = strdup(ccdir); } else { const char *comcom[] = { -#ifdef USE_DJDEV64 - "/usr/share/comcom64", - "/usr/local/share/comcom64", -#endif "/usr/share/comcom32", "/usr/local/share/comcom32", "/opt/comcom32", /* gentoo */ @@ -543,45 +515,14 @@ static void set_freedos_dir(void) } } -void move_dosemu_local_dir(void) -{ - const char *localdir = getenv("_local_dir"); - if (localdir && !dosemu_localdir_path) { - char *ldir = expand_path(localdir); - if (ldir) - dosemu_localdir_path = ldir; - else - error("local dir %s does not exist\n", localdir); - } - if (!dosemu_localdir_path) - dosemu_localdir_path = get_dosemu_local_home(); - if (!dosemu_localdir_path) - exit(1); - - if (!dosemu_image_dir_path) - dosemu_image_dir_path = dosemu_localdir_path; - setenv("DOSEMU_IMAGE_DIR", dosemu_image_dir_path, 1); - - if (!dosemu_drive_c_path) - dosemu_drive_c_path = assemble_path(dosemu_localdir_path, DRIVE_C_DIR); -} - static void move_dosemu_lib_dir(void) { char *old_cmd_path; - char *rp; - if (!dosemu_plugin_dir_path) - dosemu_plugin_dir_path = prefix(DOSEMUPLUGINDIR); - if (!dosemu_lib_dir_path) - dosemu_lib_dir_path = prefix(DOSEMULIB_DEFAULT); setenv("DOSEMU_LIB_DIR", dosemu_lib_dir_path, 1); set_freedos_dir(); - if (!commands_path) - commands_path = prefix(DOSEMUCMDS_DEFAULT); if (access(commands_path, R_OK | X_OK) != 0) { error("dosemu2 commands not found at %s\n", commands_path); - free(commands_path); commands_path = NULL; } old_cmd_path = assemble_path(dosemu_lib_dir_path, "dosemu2-cmds-0.1"); @@ -595,13 +536,11 @@ static void move_dosemu_lib_dir(void) free(keymap_load_base_path); keymap_load_base_path = assemble_path(dosemu_lib_dir_path, ""); - rp = assemble_path(RUNDIR_PREFIX, dosemu_uid); - dosemu_rundir_path = mkdir_under(rp, "dosemu2"); - free(rp); - if (dosemu_rundir_path) { - dosemu_midi_path = assemble_path(dosemu_rundir_path, DOSEMU_MIDI); - dosemu_midi_in_path = assemble_path(dosemu_rundir_path, DOSEMU_MIDI_IN); - } + setenv("DOSEMU_IMAGE_DIR", dosemu_image_dir_path, 1); + LOCALDIR = get_dosemu_local_home(); + RUNDIR = mkdir_under(LOCALDIR, "run"); + DOSEMU_MIDI_PATH = assemble_path(RUNDIR, DOSEMU_MIDI); + DOSEMU_MIDI_IN_PATH = assemble_path(RUNDIR, DOSEMU_MIDI_IN); } static int find_option(const char *option, int argc, char **argv) @@ -686,7 +625,7 @@ void secure_option_preparse(int *argc, char **argv) if (opt && opt[0]) { char *opt1 = path_expand(opt); if (opt1) { - free(dosemu_lib_dir_path); + replace_string(CFG_STORE, dosemu_lib_dir_path, opt1); dosemu_lib_dir_path = opt1; cnt++; } else { @@ -696,25 +635,11 @@ void secure_option_preparse(int *argc, char **argv) free(opt); } - opt = get_option("--Fexecdir", 1, argc, argv); - if (opt && opt[0]) { - char *opt1 = path_expand(opt); - if (opt1) { - replace_string(CFG_STORE, dosemu_exec_dir_path, opt1); - dosemu_exec_dir_path = opt1; - cnt++; - } else { - error("--Fexecdir: %s does not exist\n", opt); - config.exitearly = 1; - } - free(opt); - } - opt = get_option("--Fplugindir", 1, argc, argv); if (opt && opt[0]) { char *opt1 = path_expand(opt); if (opt1) { - free(dosemu_plugin_dir_path); + replace_string(CFG_STORE, dosemu_plugin_dir_path, opt1); dosemu_plugin_dir_path = opt1; cnt++; } else { @@ -728,7 +653,7 @@ void secure_option_preparse(int *argc, char **argv) if (opt && opt[0]) { char *opt1 = path_expand(opt); if (opt1) { - free(commands_path); + replace_string(CFG_STORE, commands_path, opt1); commands_path = opt1; cnt++; } else { @@ -742,7 +667,7 @@ void secure_option_preparse(int *argc, char **argv) if (opt && opt[0]) { char *opt1 = path_expand(opt); if (opt1) { - free(dosemu_image_dir_path); + replace_string(CFG_STORE, dosemu_image_dir_path, opt1); dosemu_image_dir_path = opt1; cnt++; } else { @@ -756,7 +681,7 @@ void secure_option_preparse(int *argc, char **argv) if (opt && opt[0]) { char *opt1 = path_expand(opt); if (opt1) { - free(dosemu_drive_c_path); + replace_string(CFG_STORE, dosemu_drive_c_path, opt1); dosemu_drive_c_path = opt1; config.alt_drv_c = 1; cnt++; @@ -766,21 +691,6 @@ void secure_option_preparse(int *argc, char **argv) } free(opt); } - - opt = get_option("--Flocal_dir", 1, argc, argv); - if (opt && opt[0]) { - char *opt1 = path_expand(opt); - if (opt1) { - free(dosemu_localdir_path); - dosemu_localdir_path = opt1; - cnt++; - } else { - error("--Flocal_dir: %s does not exist\n", opt); - config.exitearly = 1; - } - free(opt); - } - } while (cnt); } @@ -788,11 +698,8 @@ static void read_cpu_info(void) { char *cpuflags, *cpu; int k = 3; - int err; - err = open_proc_scan("/proc/cpuinfo"); - if (err) - return; + open_proc_scan("/proc/cpuinfo"); cpu = get_proc_string_by_key("cpu family"); if (cpu) { k = atoi(cpu); @@ -802,18 +709,13 @@ static void read_cpu_info(void) if (cpu) k = atoi(cpu) / 100; } if (k > 5) k = 5; - - cpuflags = get_proc_string_by_key("features"); - if (!cpuflags) - cpuflags = get_proc_string_by_key("flags"); - if (cpuflags && strstr(cpuflags, "umip")) - config.umip = 1; - else - warn("Your CPU doesn't support UMIP\n"); - switch (k) { case 5: config.realcpu = CPU_586; + cpuflags = get_proc_string_by_key("features"); + if (!cpuflags) { + cpuflags = get_proc_string_by_key("flags"); + } #ifdef X86_EMULATOR if (cpuflags && (strstr(cpuflags, "mmxext") || strstr(cpuflags, "sse"))) { @@ -821,7 +723,8 @@ static void read_cpu_info(void) } #endif #ifdef __i386__ - if (cpuflags && (strstr(cpuflags, "fxsr"))) { + if (cpuflags && (strstr(cpuflags, "fxsr")) && + sizeof(*vm86_fpu_state) == (112+512)) { config.cpufxsr = 1; if (cpuflags && strstr(cpuflags, "sse")) config.cpusse = 1; @@ -871,10 +774,15 @@ static void read_cpu_info(void) } else cpuflags=0; + if (!cpuflags) { + if (!bogospeed(&config.cpu_spd, &config.cpu_tick_spd)) { + break; + } + } } - /* fall through */ + /* fall thru */ case 4: config.realcpu = CPU_486; - /* fall through */ + /* fall thru */ case 3: break; default: @@ -902,7 +810,6 @@ static void config_post_process(void) #ifdef X86_EMULATOR char buf[256]; size_t n; - char *di; FILE *f = popen("uname -r", "r"); n = fread(buf, 1, sizeof(buf) - 1, f); buf[n >= 0 ? n : 0] = 0; @@ -915,7 +822,7 @@ static void config_post_process(void) pclose(f); #endif config.realcpu = CPU_386; - if (vm86s.cpu_type > config.realcpu || config.mathco) + if (vm86s.cpu_type > config.realcpu || config.rdtsc || config.mathco) read_cpu_info(); if (vm86s.cpu_type > config.realcpu) { vm86s.cpu_type = config.realcpu; @@ -926,9 +833,21 @@ static void config_post_process(void) "adjust $_cpu_vm_dpmi\n"); c_printf("CONF: V86 cpu vm set to %d\n", config.cpu_vm); c_printf("CONF: DPMI cpu vm set to %d\n", config.cpu_vm_dpmi); + if (config.rdtsc) { + if (config.smp) { + c_printf("CONF: Denying use of pentium timer on SMP machine\n"); + config.rdtsc = 0; + } + if (config.realcpu < CPU_586) { + c_printf("CONF: Ignoring 'rdtsc' statement\n"); + config.rdtsc = 0; + } + } + if (!config.dpmi) + config.dpmi_lin_rsv_size = 0; /* console scrub */ - if (!Video && (di = getenv("DISPLAY")) && *di && !config.X && !config.term && + if (!Video && getenv("DISPLAY") && !config.X && !config.term && config.cardtype != CARD_NONE) { config.console_video = 0; config.emuretrace = 0; /* already emulated */ @@ -964,18 +883,16 @@ static void config_post_process(void) config.console_keyb = #ifdef USE_SLANG /* Slang will take over KEYB_OTHER */ - KEYB_OTHER; - load_plugin("term"); + KEYB_OTHER #else - KEYB_TTY; + KEYB_TTY #endif + ; } config.console_video = 0; -#if 0 if (config.speaker == SPKR_NATIVE) { config.speaker = SPKR_EMULATED; } -#endif } if (!config.console_video) config.vga = config.mapped_bios = 0; @@ -997,10 +914,6 @@ static void config_post_process(void) } #endif } - if (config.umb_b0 == -1) - config.umb_b0 = config.dumb_video; - if (config.umb_b8) - config.umb_b8 = config.dumb_video; /* page-align memory sizes */ config.ext_mem &= ~3; @@ -1026,6 +939,14 @@ static void config_post_process(void) } #endif + /* for now they can't work together */ + if (config.ne2k && config.pktdrv) { + c_printf("CONF: Warning: disabling packet driver because of ne2k\n"); + config.pktdrv = 0; + } + + check_for_env_autoexec_or_config(); + if (config.pci && !can_do_root_stuff) { c_printf("CONF: Warning: PCI requires root, disabled\n"); config.pci = 0; @@ -1141,11 +1062,12 @@ config_init(int argc, char **argv) int nodosrc = 0; char *basename; int err; - int was_exec = 0, was_T1 = 0; const char * const getopt_string = - "23456ABC::c::D:d:E:e:f:H:hi:I:K:k::L:M:mNno:P:qSsT::t::VvwXx:Y" + "23456ABC::c::D:d:E:e:f:H:hI:K:k::L:M:mNno:P:qSsTt::VvwXx:Y" "gp"/*NOPs kept for compat (not documented in usage())*/; + if (getenv("DOSEMU_INVOKED_NAME")) + argv[0] = getenv("DOSEMU_INVOKED_NAME"); basename = strrchr(argv[0], '/'); /* parse the program name */ basename = basename ? basename + 1 : argv[0]; @@ -1157,9 +1079,6 @@ config_init(int argc, char **argv) memcheck_type_init(); our_envs_init(); parse_debugflags("+cw", 1); -#ifdef USE_DJDEV64 - register_debug_class('J', NULL, "dj64"); -#endif Video = NULL; /* options get parsed twice so show our own errors and only once */ @@ -1178,10 +1097,6 @@ config_init(int argc, char **argv) break; case 'f': dosrcname = path_expand(optarg); - if (!dosrcname) { - error("%s is missing\n", optarg); - leavedos(2); - } break; case 'I': assert(i_found < I_MAX); @@ -1234,9 +1149,6 @@ config_init(int argc, char **argv) case 'n': nodosrc = 1; break; - case 'q': - config.quiet = 1; - break; case 'v': printf("dosemu2-" VERSTR "\n"); printf("Revision: %i\n", REVISION); @@ -1256,33 +1168,45 @@ config_init(int argc, char **argv) if (config_check_only) set_debug_level('c',1); move_dosemu_lib_dir(); - if (nodosrc && dosrcname) { - c_printf("CONF: using %s as primary config\n", dosrcname); - confname = dosrcname; - dosrcname = NULL; - } else { - confname = assemble_path(DOSEMU_CONF_DIR, DOSEMU_CONF); - if (access(confname, R_OK) == -1) { - free(confname); - confname = NULL; - } + confname = assemble_path(DOSEMU_CONF_DIR, DOSEMU_CONF); + if (access(confname, R_OK) == -1) { + free(confname); + confname = NULL; } - parse_config(confname, dosrcname, nodosrc); + if (!nodosrc) { + if (!dosrcname) { + dosrcname = assemble_path(dosemu_localdir_path, DOSEMU_RC); + if (access(dosrcname, R_OK) == -1) { + free(dosrcname); + dosrcname = get_path_in_HOME(DOSEMU_RC); + } + } + if (access(dosrcname, R_OK) == -1) { + free(dosrcname); + dosrcname = NULL; + } + } + parse_config(confname, dosrcname); free(confname); free(dosrcname); if (config.exitearly && !config_check_only) exit(0); + /* default settings before processing cmdline */ + config.exit_on_cmd = 1; + i_cur = 0; - GETOPT_RESET(); +#ifdef __linux__ + optind = 0; +#endif + opterr = 0; while ((c = getopt(argc, argv, getopt_string)) != EOF) { switch (c) { case 'f': case 'c': case 'o': case 'n': - case 'q': case 's': break; case 'L': @@ -1325,9 +1249,6 @@ config_init(int argc, char **argv) #endif break; } - case 'i': - append_pre_strokes(optarg); - break; case 'I': assert(i_cur < i_found); optind += i_incr[i_cur++]; @@ -1365,14 +1286,7 @@ config_init(int argc, char **argv) config.console_keyb = KEYB_STDIO; break; case 't': - config.console_keyb = -#ifdef USE_SLANG - /* Slang will take over KEYB_OTHER */ - KEYB_OTHER; - load_plugin("term"); -#else - KEYB_TTY; -#endif + config.console_keyb = KEYB_TTY; break; case 'r': config.console_keyb = KEYB_RAW; @@ -1392,17 +1306,10 @@ config_init(int argc, char **argv) config.term = 1; } if (optarg) { - char *opt_e; - if (strchr(optarg, 'c')) - config.clip_term = 1; if (strchr(optarg, 'd')) config.dumb_video = 1; - if ((opt_e = strchr(optarg, 'e'))) { - if (isdigit(opt_e[1])) - config.tty_stderr = opt_e[1] - '0'; - else - config.tty_stderr = 1; - } + if (strchr(optarg, 'e')) + config.tty_stderr = 1; } break; case 'X': @@ -1460,7 +1367,6 @@ config_init(int argc, char **argv) case 'E': g_printf("DOS command given on command line: %s\n", optarg); config.dos_cmd = optarg; - was_exec++; break; case 'K': { char *p; @@ -1470,13 +1376,8 @@ config_init(int argc, char **argv) if (p) { *p = '\0'; config.dos_path = strdup(p + 1); - if (p == config.unix_path) { - free(config.unix_path); - config.unix_path = NULL; - } } - if (config.unix_path && !exists_dir(config.unix_path) && - !exists_file(config.unix_path)) { + if (!exists_dir(config.unix_path) && !exists_file(config.unix_path)) { error("Path %s does not exist\n", config.unix_path); config.exitearly = 1; break; @@ -1484,10 +1385,10 @@ config_init(int argc, char **argv) break; } case 'T': - if (!optarg || strchr(optarg, '1')) - was_T1++; - if (!optarg || strchr(optarg, 'h')) - misc_e6_store_options("SHELL_LOADHIGH_DEFAULT=1"); + config.exit_on_cmd = 0; + break; + case 'q': + config.quiet = 1; break; case '?': @@ -1497,56 +1398,17 @@ config_init(int argc, char **argv) exit(1); } } - /* make-style env vars passing */ while (optind < argc) { - char *p, *p1; if (strchr(argv[optind], '=') == NULL) { - char *fpath; - if (config.dos_cmd || config.unix_path) - break; - fpath = expand_path(argv[optind]); - if (!fpath) { - error("%s not found\n", argv[optind]); - break; - } - p = strrchr(fpath, '/'); - assert(p); // expand_path() should add some slashes - config.unix_path = strdup(fpath); - p1 = config.unix_path + (p - fpath); - *p1 = '\0'; - p++; - if (!*p) { - free(fpath); - break; - } - config.dos_cmd = strdup(p); - free(fpath); - optind++; - /* collect args */ - while (argv[optind]) { - g_printf("DOS command given on command line: %s\n", argv[optind]); - config.dos_cmd = realloc(config.dos_cmd, - strlen(config.dos_cmd) + strlen(argv[optind]) + 2); - strcat(config.dos_cmd, " "); - strcat(config.dos_cmd, argv[optind]); - optind++; - } - was_exec++; - break; + fprintf(stderr, "unrecognized argument: %s\n\r", argv[optind]); + fprintf(stderr, "For passing DOS command use -E\n\r"); + exit(1); } - g_printf("ENV given on command line: %s\n", argv[optind]); + g_printf("DOS command given on command line: %s\n", argv[optind]); misc_e6_store_options(argv[optind]); optind++; } - if (argv[optind]) { - fprintf(stderr, "unrecognized argument: %s\n\r", argv[optind]); - exit(1); - } - - if (was_exec && !was_T1) - misc_e6_store_options("DOSEMU_EXIT=1"); - config_post_process(); config_scrub(); if (config_check_only) { @@ -1559,6 +1421,29 @@ config_init(int argc, char **argv) } } + +static void +check_for_env_autoexec_or_config(void) +{ + char *cp; + cp = getenv("CONFIG"); + if (cp) { + free(config.emusys); + config.emusys = strdup(cp); + } + + + /* + * The below is already reported in the conf. It is in no way an error + * so why the messages? + */ + +#if 0 + if (config.emusys) + fprintf(stderr, "config extension = %s\n", config.emusys); +#endif +} + /* * Please keep "getopt_string", secure_option_preparse(), config_init(), * usage() and the manpage in sync! @@ -1603,7 +1488,7 @@ usage(char *basename) " -P copy debugging output to FILE\n" " -p stop for prompting with a non-fatal configuration problem\n" " -s enable direct hardware access (full feature) (!%%)\n" - " -T set flags for -E or -K options\n" + " -T don't exit after executing -E command\n" " -t use terminal (S-Lang) mode\n" " -V use BIOS-VGA video modes (!#%%)\n" " -v display version\n" @@ -1654,7 +1539,7 @@ void set_external_charset(const char *charset_name) } } - config.external_cset = strdup(charset_name); + config.external_cset = charset_name; } void set_internal_charset(const char *charset_name) @@ -1681,7 +1566,7 @@ void set_internal_charset(const char *charset_name) trconfig.dos_charset = charset_config; } - config.internal_cset = strdup(charset_name); + config.internal_cset = charset_name; } void set_country_code(int cntry) diff --git a/src/base/init/dev_list.c b/src/base/init/dev_list.c index 64cdf28..655ac2b 100644 --- a/src/base/init/dev_list.c +++ b/src/base/init/dev_list.c @@ -42,10 +42,6 @@ #include "emm.h" #include "xms.h" #include "emudpmi.h" -#include "virq.h" -#include "vint.h" -#include "vtmr.h" -#include "dos2linux.h" struct io_dev_struct { const char *name; @@ -64,17 +60,16 @@ struct owned_devices_struct { static int current_device = -1; static struct io_dev_struct io_devices[MAX_IO_DEVICES] = { + { "pit", NULL, pit_reset, NULL }, { "cmos", cmos_init, cmos_reset, NULL }, { "video", video_post_init, NULL, NULL }, { "internal_mouse", dosemu_mouse_init, NULL, dosemu_mouse_close }, { "serial", serial_init, serial_reset, serial_close }, { "pic", pic_init, pic_reset, NULL }, { "chipset", chipset_init, NULL, NULL }, - { "virq", virq_init, virq_reset, NULL }, - { "vint", vint_init, NULL, NULL }, - { "vtmr", vtmr_init, vtmr_reset, vtmr_done }, - { "pit", pit_init, pit_reset, pit_done }, - { "rtc", rtc_init, NULL, NULL }, +#if 0 + { "pos", pos_init, pos_reset, NULL }, +#endif { "lpt", printer_init, NULL, NULL }, { "dma", dma_init, dma_reset, NULL }, #if 0 @@ -83,7 +78,6 @@ static struct io_dev_struct io_devices[MAX_IO_DEVICES] = { #endif { "disks", disk_init, disk_reset, NULL }, { "sound", sound_init, sound_reset, sound_done }, - { "mt32", mt32_init, mt32_reset, mt32_done }, { "joystick", joy_init, joy_reset, joy_term }, #ifdef IPX { "ipx", ipx_init, NULL, ipx_close }, @@ -91,11 +85,9 @@ static struct io_dev_struct io_devices[MAX_IO_DEVICES] = { { "packet driver", pkt_init, pkt_reset, pkt_term }, { "ne2000", ne2000_init, ne2000_reset, ne2000_done }, { "ems", ems_init, ems_reset, NULL }, - { "xms", xms_init, xms_reset, xms_done }, + { "xms", xms_init, xms_reset, NULL }, { "dpmi", dpmi_setup, dpmi_reset, NULL }, - { "mfs", NULL, mfs_reset, mfs_done }, { "cdrom", NULL, NULL, cdrom_done }, - { "dos2tty", dos2tty_init, NULL, dos2tty_done }, { NULL, NULL, NULL, NULL } }; @@ -140,7 +132,7 @@ void iodev_register(const char *name, for(ptr = io_devices; ptr < &io_devices[MAX_IO_DEVICES -1]; ptr++) { if (ptr->name) { if (strcmp(ptr->name, name) == 0) { - g_printf("IODEV: %s already registered\n", + g_printf("IODEV: %s already registred\n", name); return; } diff --git a/src/base/init/init.c b/src/base/init/init.c index 8eec5a3..23b13a6 100644 --- a/src/base/init/init.c +++ b/src/base/init/init.c @@ -13,7 +13,6 @@ #include #endif -#include "init.h" #include "version.h" #include "emu.h" #include "memory.h" @@ -34,18 +33,16 @@ #include "xms.h" #include "lowmem.h" #include "iodev.h" +#include "priv.h" #include "doshelpers.h" #include "cpu-emu.h" #include "kvm.h" #include "mapping.h" -#include "smalloc.h" #include "vgaemu.h" #include "cpi.h" #define GFX_CHARS 0xffa6e -smpool main_pool; - #if 0 static inline void dbug_dumpivec(void) { @@ -81,7 +78,7 @@ void stdio_init(void) strcat(config.debugout, debugout); } } - if (config.debugout && config.debugout[0] != '-') { + if (config.debugout != NULL) { dbg_fd = fopen(config.debugout, "we"); if (!dbg_fd) error("can't open \"%s\" for writing\n", config.debugout); @@ -90,12 +87,25 @@ void stdio_init(void) } real_stderr = stderr; -#if defined(HAVE_ASSIGNABLE_STDERR) && defined(HAVE_FOPENCOOKIE) +#ifdef HAVE_ASSIGNABLE_STDERR if (dbg_fd) stderr = fstream_tee(stderr, dbg_fd); #endif } +/* + * DANG_BEGIN_FUNCTION time_setting_init + * + * description: + * Beats me + * + * DANG_END_FUNCTION + */ +void time_setting_init(void) +{ + initialize_timers(); +} + /* * DANG_BEGIN_FUNCTION timer_interrupt_init * @@ -209,6 +219,9 @@ static void setup_fonts(void) * * DANG_END_FUNCTION */ + +#include "bios_data.xxd" + void map_custom_bios(void) { unsigned int ptr; @@ -218,7 +231,7 @@ void map_custom_bios(void) /* Copy the BIOS into DOS memory */ ptr = SEGOFF2LINEAR(BIOSSEG, bios_data_start); e_invalidate(ptr, DOSEMU_BIOS_SIZE()); - MEMCPY_2DOS(ptr, _binary_bios_o_bin_start, DOSEMU_BIOS_SIZE()); + MEMCPY_2DOS(ptr, bios_data, DOSEMU_BIOS_SIZE()); setup_fonts(); /* Initialise the ROM-BIOS graphic font (lower half only) */ MEMCPY_2DOS(GFX_CHARS, vga_rom_08, 128 * 8); @@ -253,36 +266,75 @@ void memory_init(void) */ void device_init(void) { + pit_init(); /* for native speaker */ video_config_init(); /* privileged part of video init */ keyb_priv_init(); mouse_priv_init(); } +static void *mem_reserve_contig(uint32_t size, uint32_t dpmi_size, + void **base2) +{ + void *result; + int cap = MAPPING_INIT_LOWRAM | MAPPING_SCRATCH | MAPPING_DPMI; + result = mmap_mapping_ux(cap, (void *)-1, size + dpmi_size, PROT_NONE); + if (result == MAP_FAILED) + return result; + + *base2 = result + size; + return result; +} + +static void *mem_reserve_split(uint32_t size, uint32_t dpmi_size, void **base2) +{ + void *result; + void *dpmi_base; + + /* lowmem_base is not yet available, so use _ux version */ + result = mmap_mapping_ux(MAPPING_INIT_LOWRAM | MAPPING_SCRATCH, + (void *)-1, size, PROT_NONE); + if (result == MAP_FAILED) + return result; + if (!config.dpmi) + return result; + assert(config.dpmi_lin_rsv_base != (dosaddr_t)-1); + dpmi_base = (void*)(((uintptr_t)result + config.dpmi_lin_rsv_base) & 0xffffffff); + dpmi_base = mmap_mapping_ux(MAPPING_DPMI | MAPPING_SCRATCH | + MAPPING_NOOVERLAP, dpmi_base, dpmi_size, PROT_NONE); + if (dpmi_base == MAP_FAILED) { + perror ("DPMI mmap"); + exit(EXIT_FAILURE); + } + + *base2 = dpmi_base; + return result; +} + /* * DANG_BEGIN_FUNCTION mem_reserve * * description: * reserves address space seen by DOS and DPMI apps - * There are two possibilities: - * 1) 0-based mapping: one map at 0 of 1088k, and the combined map - * below. + * There are three possibilities: + * 1) 0-based mapping: one map at 0 of 1088k, the rest below 1G * This is only used for i386 + vm86() (not KVM/CPUEMU) - * 2) non-zero-based mapping: one combined mmap. - * Everything needs to be below 4G for native DPMI - * (intrinsically) and JIT CPUEMU (for now) + * 2) non-zero-based mapping: one combined mmap, everything below 4G + * 3) config.dpmi_lin_rsv_base is set: honour it * * DANG_END_FUNCTION */ -static void *mem_reserve(uint32_t memsize) +static void *mem_reserve(void **base2, void **r_dpmi_base) { void *result; - int cap = MAPPING_INIT_LOWRAM | MAPPING_SCRATCH | MAPPING_DPMI; - int prot = PROT_NONE; + void *dpmi_base; + uint32_t memsize = LOWMEM_SIZE + HMASIZE; + uint32_t dpmi_size = PAGE_ALIGN(config.dpmi_lin_rsv_size * 1024); + uint32_t dpmi_memsize = dpmi_mem_size(); #ifdef __i386__ if (config.cpu_vm == CPUVM_VM86) { - result = mmap_mapping(MAPPING_NULL | MAPPING_SCRATCH, - NULL, LOWMEM_SIZE + HMASIZE, PROT_NONE); + result = mmap_mapping_ux(MAPPING_NULL | MAPPING_SCRATCH, + NULL, memsize, PROT_NONE); if (result == MAP_FAILED) { const char *msg = "You can most likely avoid this problem by running\n" @@ -309,147 +361,60 @@ static void *mem_reserve(uint32_t memsize) } #endif - result = mmap_mapping_huge_page_aligned(cap, memsize, prot); + if (config.dpmi && config.dpmi_lin_rsv_base == (dosaddr_t)-1) { /* contiguous memory */ + result = mem_reserve_contig(memsize, dpmi_size + dpmi_memsize, base2); + dpmi_base = *base2 + dpmi_size; + } else { + result = mem_reserve_split(memsize + dpmi_memsize, dpmi_size, base2); + dpmi_base = result + memsize; + } if (result == MAP_FAILED) { perror ("LOWRAM mmap"); exit(EXIT_FAILURE); } + if (!config.dpmi) + dpmi_base = NULL; + *r_dpmi_base = dpmi_base; return result; } -static void low_mem_init_config_scrub(void) +/* + * DANG_BEGIN_FUNCTION low_mem_init + * + * description: + * Initializes the lower 1Meg via mmap & sets up the HMA region + * + * DANG_END_FUNCTION + */ +void low_mem_init(void) { - const uint32_t mem_1M = 1024 * 1024; - /* 16Mb limit is for being in reach of DMAc */ - const uint32_t mem_16M = mem_1M * 16; - uint32_t min_phys_rsv = LOWMEM_SIZE + EXTMEM_SIZE; - - if (EXTMEM_SIZE < HMASIZE) - config.ext_mem = 64; - if (config.xms_size) { - /* reserve 1Mb for XMS mappings */ - min_phys_rsv += mem_1M; - if (min_phys_rsv > mem_16M) { - error("$_ext_mem too large, please set to (%d) or lower, or set $_xms=(0)\n", - (EXTMEM_SIZE - (min_phys_rsv - mem_16M)) / 1024); - config.exitearly = 1; - return; - } - } - - min_phys_rsv = roundUpToNextPowerOfTwo(LOWMEM_SIZE + EXTMEM_SIZE + XMS_SIZE); - if (config.dpmi && min_phys_rsv > config.dpmi_base) { - error("$_dpmi_base is too small, please set to at least (0x%x)\n", min_phys_rsv); - config.exitearly = 1; - return; - } -} - -static void do_sm_error(int prio, const char *fmt, ...) -{ - char buf[16384]; - va_list al; - - va_start(al, fmt); - vsnprintf(buf, sizeof(buf), fmt, al); - va_end(al); - if (prio >= 3) - dosemu_error("%s", buf); - else if (prio == 2) - error("%s", buf); - else - dbug_printf("%s", buf); -} - -void map_memory_space(void) -{ - unsigned char *lowmem, *ptr, *ptr2; + void *lowmem, *base2 = MAP_FAILED, *dpmi_base = MAP_FAILED; int result; - uint32_t memsize; - int32_t phys_rsv, phys_low; - smregister_default_error_notifier(do_sm_error); open_mapping(MAPPING_INIT_LOWRAM); g_printf ("DOS+HMA memory area being mapped in\n"); - lowmem = alloc_mapping_huge_page_aligned(MAPPING_INIT_LOWRAM, LOWMEM_SIZE + - EXTMEM_SIZE); + lowmem = alloc_mapping(MAPPING_INIT_LOWRAM, LOWMEM_SIZE + HMASIZE); if (lowmem == MAP_FAILED) { perror("LOWRAM alloc"); leavedos(98); } - phys_low = roundUpToNextPowerOfTwo(LOWMEM_SIZE + EXTMEM_SIZE + XMS_SIZE); - memsize = phys_low; - if (config.dpmi) - /* LOWMEM_SIZE accounted twice for alignment */ - memsize += config.dpmi_base + HUGE_PAGE_ALIGN(dpmi_mem_size()); - mem_base = mem_reserve(memsize); - mem_base_mask = ~(uintptr_t)0; -#ifdef __x86_64__ - if (_MAP_32BIT) mem_base_mask = 0xffffffffu; -#endif - register_hardware_ram_virtual('L', 0, LOWMEM_SIZE + HMASIZE, 0); - result = alias_mapping(MAPPING_LOWMEM, 0, LOWMEM_SIZE + HMASIZE, + mem_base = mem_reserve(&base2, &dpmi_base); + if (config.cpu_vm == CPUVM_KVM || config.cpu_vm_dpmi == CPUVM_KVM) + init_kvm_monitor(); + result = alias_mapping(MAPPING_INIT_LOWRAM, 0, LOWMEM_SIZE + HMASIZE, PROT_READ | PROT_WRITE | PROT_EXEC, lowmem); if (result == -1) { perror ("LOWRAM mmap"); exit(EXIT_FAILURE); } c_printf("Conventional memory mapped from %p to %p\n", lowmem, mem_base); - - if (config.xms_size) - memcheck_reserve('x', LOWMEM_SIZE + EXTMEM_SIZE, XMS_SIZE); - - sminit_comu(&main_pool, mem_base, memsize, mcommit, muncommit); - ptr = smalloc(&main_pool, LOWMEM_SIZE + HMASIZE); - assert(ptr == mem_base); - /* smalloc uses PROT_READ | PROT_WRITE, needs to add PROT_EXEC here */ - mprotect_mapping(MAPPING_LOWMEM, 0, LOWMEM_SIZE + HMASIZE, PROT_READ | PROT_WRITE | - PROT_EXEC); - /* we have an uncommitted hole up to phys_low */ - ptr += phys_low; - phys_rsv = phys_low - (LOWMEM_SIZE + HMASIZE); - /* create non-identity mapping up to phys_low */ - ptr2 = smalloc_topdown(&main_pool, config.dpmi ? phys_low : phys_rsv); - assert(ptr2); - if (config.dpmi) { - void *dptr = smalloc_fixed(&main_pool, MEM_BASE32(config.dpmi_base), - dpmi_mem_size()); - assert(dptr); - if (config.cpu_vm_dpmi == CPUVM_KVM) { - /* map dpmi+uncommitted space to kvm */ - int prot = PROT_READ | PROT_WRITE | PROT_EXEC; - mmap_kvm(MAPPING_INIT_LOWRAM, phys_low, ptr2 - ptr, ptr, phys_low, prot); - } - /* unused hole for alignment */ - ptr2 += LOWMEM_SIZE + HMASIZE; - } - - /* LOWMEM_SIZE + HMASIZE == base */ - memcheck_addtype('X', "EXT MEM"); - memcheck_reserve('X', LOWMEM_SIZE + HMASIZE, EXTMEM_SIZE - HMASIZE); - x_printf("Ext.Mem of size 0x%x at %#x\n", EXTMEM_SIZE - HMASIZE, - LOWMEM_SIZE + HMASIZE); - - /* establish ext_mem alias access for int15 */ - register_hardware_ram_virtual('X', LOWMEM_SIZE + HMASIZE, phys_rsv, - DOSADDR_REL(ptr2)); - if (config.dpmi) { - register_hardware_ram_virtual('U', DOSADDR_REL(ptr2), phys_rsv, - LOWMEM_SIZE + HMASIZE); - /* create ext_mem alias for dpmi */ - result = alias_mapping(MAPPING_EXTMEM, DOSADDR_REL(ptr2), - EXTMEM_SIZE - HMASIZE, - PROT_READ | PROT_WRITE, - lowmem + LOWMEM_SIZE + HMASIZE); - assert(result != -1); - } + if (config.dpmi) + dpmi_set_mem_bases(base2, dpmi_base); /* R/O protect 0xf0000-0xf4000 */ - if (!config.umb_f0) { - memcheck_addtype('R', "ROM at f000:0000 for $_umb_f0 = (off)"); - memcheck_reserve('R', 0xF0000, 0x4000); - } + if (!config.umb_f0) + mprotect_mapping(MAPPING_LOWMEM, 0xf0000, 0x4000, PROT_READ); } /* @@ -507,8 +472,3 @@ void print_version(void) warn("CFLAGS: %s\n", _S(CFLAGS_STR)); #endif } - -CONSTRUCTOR(static void init(void)) -{ - register_config_scrub(low_mem_init_config_scrub); -} diff --git a/src/base/init/lexer.l b/src/base/init/lexer.l index 0e78895..fff3622 100644 --- a/src/base/init/lexer.l +++ b/src/base/init/lexer.l @@ -319,18 +319,17 @@ emuretrace RETURN(EMURETRACE); mathco RETURN(MATHCO); cpu RETURN(CPU); cpuspeed RETURN(CPUSPEED); +rdtsc RETURN(RDTSC); bootdrive RETURN(BOOTDRIVE); swap_bootdrive RETURN(SWAP_BOOTDRIVE); xms RETURN(L_XMS); umb_a0 RETURN(UMB_A0); umb_b0 RETURN(UMB_B0); -umb_b8 RETURN(UMB_B8); umb_f0 RETURN(UMB_F0); -hma RETURN(HMA); -dos_up RETURN(DOS_UP); ems RETURN(L_EMS); dpmi RETURN(L_DPMI); -dpmi_base RETURN(DPMI_BASE); +dpmi_lin_rsv_base RETURN(DPMI_LIN_RSV_BASE); +dpmi_lin_rsv_size RETURN(DPMI_LIN_RSV_SIZE); pm_dos_api RETURN(PM_DOS_API); ignore_djgpp_null_derefs RETURN(NO_NULL_CHECKS); dosmem RETURN(DOSMEM); @@ -388,7 +387,6 @@ image RETURN(HDIMAGE); partition RETURN(L_PARTITION); wholedisk RETURN(WHOLEDISK); readonly RETURN(READONLY); -ro RETURN(READONLY); threeinch RETURN(THREEINCH); threeinch_2880 RETURN(THREEINCH_2880); threeinch_720 RETURN(THREEINCH_720); @@ -448,10 +446,6 @@ pseudo RETURN(PSEUDO); rtscts RETURN(RTSCTS); low_latency RETURN(LOWLAT); pccom RETURN(PCCOM); -exec RETURN(EXEC); -pts RETURN(PTS); -wrfile RETURN(WRFILE); -nullmodem RETURN(NULLMM); /* lock file stuff */ directory RETURN(DIRECTORY); @@ -481,7 +475,6 @@ imps2 RETURN(IMPS2); internaldriver RETURN(INTERNALDRIVER); emulate3buttons RETURN(EMULATE3BUTTONS); cleardtr RETURN(CLEARDTR); -mouse_ungrab_tweak RETURN(UNGRAB_TWEAK); /* video stuff - sorry for Matrox but MGA was already used */ @@ -536,14 +529,10 @@ pm_interface RETURN(X_PM_INTERFACE); mgrab_key RETURN(X_MGRAB_KEY); background_pause RETURN(X_BACKGROUND_PAUSE); fullscreen RETURN(X_FULLSCREEN); -noclose RETURN(X_NOCLOSE); -noresize RETURN(X_NORESIZE); /* SDL stuff */ sdl_hwrend RETURN(SDL_HWREND); sdl_fonts RETURN(SDL_FONTS); -sdl_wcontrols RETURN(SDL_WCONTROLS); -sdl_clip_native RETURN(SDL_CLIP_NATIVE); /* Sound stuff */ @@ -552,14 +541,11 @@ sb_irq RETURN(SB_IRQ); sb_dma RETURN(SB_DMA); sb_hdma RETURN(SB_HDMA); mpu_base RETURN(MPU_BASE); -mpu_base_mt32 RETURN(MPU_BASE_MT32); midi_synth RETURN(MIDI_SYNTH); mpu_irq RETURN(MPU_IRQ); mpu_irq_mt32 RETURN(MPU_IRQ_MT32); sound_driver RETURN(SOUND_DRIVER); midi_driver RETURN(MIDI_DRIVER); -fluid_sfont RETURN(FLUID_SFONT); -fluid_volume RETURN(FLUID_VOLUME); munt_roms RETURN(MUNT_ROMS); opl2lpt_dev RETURN(OPL2LPT_DEV); opl2lpt_type RETURN(OPL2LPT_TYPE); @@ -582,7 +568,6 @@ ethdev RETURN(ETHDEV); tapdev RETURN(TAPDEV); vdeswitch RETURN(VDESWITCH); slirpargs RETURN(SLIRPARGS); -netsock RETURN(NETSOCK); vnet RETURN(VNET); /* debug flags */ @@ -626,7 +611,6 @@ target RETURN(TARGET); /* hacks */ cli_timeout RETURN(CLI_TIMEOUT); timemode RETURN(TIMEMODE); -timer_tweaks RETURN(TIMER_TWEAKS); /* charset stuff */ external RETURN(EXTERNAL); @@ -714,8 +698,8 @@ static void enter_includefile(char * fname) */ if (fname[0] != '/') { int i; - if (!strncmp(fname, keymap_dir_path, strlen(keymap_dir_path))) - strcpy(fname_, keymap_load_base_path); + if (!strncmp(fname, KEYMAP_DIR, strlen(KEYMAP_DIR))) + strcpy(fname_, KEYMAP_LOAD_BASE_PATH); else strcpy(fname_, include_fnames[include_stack_ptr]); i=strlen(fname_); diff --git a/src/base/init/memcheck.c b/src/base/init/memcheck.c index e743622..9fb0236 100644 --- a/src/base/init/memcheck.c +++ b/src/base/init/memcheck.c @@ -5,8 +5,6 @@ #include "emu.h" #include "utilities.h" #include "memory.h" -#include "kvm.h" -#include "mapping.h" /* Notes: * 1. leavedos() needs a real parameter @@ -21,7 +19,8 @@ */ #define GRAN_SIZE 1024 /* Size of granularity in KB */ -#define MAX_PAGE (LOWMEM_SIZE/GRAN_SIZE) /* Number of 'pages' in memory */ +#define MEM_SIZE (1024*1024) /* Size of memory in KB */ +#define MAX_PAGE (MEM_SIZE/GRAN_SIZE) /* Number of 'pages' in memory */ static unsigned char mem_map[MAX_PAGE]; /* Map of memory contents */ static const char *mem_names[256]; /* List of id. strings */ @@ -43,7 +42,7 @@ int memcheck_addtype(unsigned char map_char, const char *name) { if (mem_names[map_char] != NULL) { if (strcmp(mem_names[map_char], name) != 0) { - error("CONF: memcheck, conflicting map type '%c' defined for '%s' \ + c_printf("CONF: memcheck, conflicting map type '%c' defined for '%s' \ & '%s'\n", map_char, mem_names[map_char], name); config.exitearly = 1; } @@ -101,19 +100,11 @@ int memcheck_map_reserve(unsigned char map_char, dosaddr_t addr_start, void memcheck_e820_reserve(dosaddr_t addr_start, uint32_t size, int reserved) { struct system_memory_map *entry; - int len = system_memory_map_size / sizeof(*system_memory_map); - int i; system_memory_map_size += sizeof(*system_memory_map); system_memory_map = realloc(system_memory_map, system_memory_map_size); - for (i = 0; i < len; i++) { - if (addr_start < system_memory_map[i].base) - break; - } - if (i < len) - memmove(&system_memory_map[i + 1], &system_memory_map[i], - sizeof(*system_memory_map) * (len - i)); - entry = system_memory_map + i; + entry = system_memory_map + + system_memory_map_size / sizeof(*system_memory_map) - 1; entry->base = addr_start; entry->hibase = 0; entry->length = size; @@ -135,14 +126,8 @@ void memcheck_reserve(unsigned char map_char, dosaddr_t addr_start, } return; } - /* 'r' is dosemu heap. It is normally reserved, but fdpp can drill - * the UMB holes in it, so mark as available. */ memcheck_e820_reserve(addr_start, size, - !(map_char == 'd' || map_char == 'U' || map_char == 'X' || - map_char == 'H' || map_char == 'r')); - - if (memcheck_is_rom(addr_start)) - mprotect_mapping(MAPPING_LOWMEM, addr_start, size, PROT_READ | PROT_EXEC); + !(map_char == 'd' || map_char == 'U' || map_char == 'x')); } void memcheck_map_free(unsigned char map_char) @@ -174,6 +159,8 @@ void memcheck_init(void) { memcheck_type_init(); memcheck_reserve('d', 0x00000, config.mem_size*1024); /* dos memory */ + if (!config.umb_f0) + memcheck_reserve('r', 0xF0000, DOSEMU_LMHEAP_OFF); memcheck_reserve('r', 0xF0000 + DOSEMU_LMHEAP_OFF, DOSEMU_LMHEAP_SIZE); assert(DOSEMU_LMHEAP_OFF + DOSEMU_LMHEAP_SIZE == bios_data_start); /* dosemu bios */ @@ -216,29 +203,6 @@ int memcheck_is_reserved(dosaddr_t addr_start, uint32_t size, return TRUE; } -int memcheck_is_rom(dosaddr_t addr) -{ - round_addr(&addr); - if (addr >= LOWMEM_SIZE) - return 0; - return strchr("R", mem_map[addr / GRAN_SIZE]) != NULL; -} - -int memcheck_is_hardware_ram(dosaddr_t addr) -{ - round_addr(&addr); - if (addr >= LOWMEM_SIZE) - return 0; - return strchr("evh", mem_map[addr / GRAN_SIZE]) != NULL; -} - -int memcheck_is_system_ram(dosaddr_t addr) -{ - round_addr(&addr); - return !memcheck_is_rom(addr) && - !memcheck_is_hardware_ram(addr); -} - int memcheck_findhole(dosaddr_t *start_addr, uint32_t min_size, uint32_t max_size) { diff --git a/src/base/init/parser.y b/src/base/init/parser.y index f9980e2..1f503a8 100644 --- a/src/base/init/parser.y +++ b/src/base/init/parser.y @@ -100,9 +100,12 @@ static int ports_permission = IO_RDWR; static unsigned int ports_ormask = 0; static unsigned int ports_andmask = 0xFFFF; static unsigned int portspeed = 0; +static char dev_name[255]= ""; static int errors = 0; static int warnings = 0; +static int priv_lvl = 0; + static char *file_being_parsed; @@ -231,13 +234,12 @@ enum { /* main options */ %token FASTFLOPPY HOGTHRESH SPEAKER IPXSUPPORT IPXNETWORK NOVELLHACK -%token ETHDEV TAPDEV VDESWITCH SLIRPARGS NETSOCK VNET +%token ETHDEV TAPDEV VDESWITCH SLIRPARGS VNET %token DEBUG MOUSE SERIAL COM KEYBOARD TERMINAL VIDEO EMURETRACE TIMER -%token MATHCO CPU CPUSPEED BOOTDRIVE SWAP_BOOTDRIVE -%token L_XMS L_DPMI DPMI_BASE PM_DOS_API NO_NULL_CHECKS +%token MATHCO CPU CPUSPEED RDTSC BOOTDRIVE SWAP_BOOTDRIVE +%token L_XMS L_DPMI DPMI_LIN_RSV_BASE DPMI_LIN_RSV_SIZE PM_DOS_API NO_NULL_CHECKS %token PORTS DISK DOSMEM EXT_MEM -%token L_EMS UMB_A0 UMB_B0 UMB_B8 UMB_F0 HMA DOS_UP -%token EMS_SIZE EMS_FRAME EMS_UMA_PAGES EMS_CONV_PAGES +%token L_EMS UMB_A0 UMB_B0 UMB_F0 EMS_SIZE EMS_FRAME EMS_UMA_PAGES EMS_CONV_PAGES %token TTYLOCKS L_SOUND L_SND_OSS L_JOYSTICK FILE_LOCK_LIMIT %token ABORT WARN ERROR %token L_FLOPPY EMUSYS L_X L_SDL @@ -257,18 +259,16 @@ enum { /* lock files */ %token DIRECTORY NAMESTUB BINARY /* serial */ -%token BASE IRQ DEVICE CHARSET BAUDRATE VIRTUAL VMODEM PSEUDO RTSCTS LOWLAT -%token PCCOM EXEC PTS WRFILE NULLMM +%token BASE IRQ DEVICE CHARSET BAUDRATE VIRTUAL VMODEM PSEUDO RTSCTS LOWLAT PCCOM /* mouse */ %token MICROSOFT MS3BUTTON LOGITECH MMSERIES MOUSEMAN HITACHI MOUSESYSTEMS BUSMOUSE PS2 IMPS2 -%token INTERNALDRIVER EMULATE3BUTTONS CLEARDTR UNGRAB_TWEAK +%token INTERNALDRIVER EMULATE3BUTTONS CLEARDTR /* x-windows */ %token L_DISPLAY L_TITLE X_TITLE_SHOW_APPNAME ICON_NAME X_BLINKRATE X_SHARECMAP X_MITSHM X_FONT -%token X_FIXED_ASPECT X_ASPECT_43 X_LIN_FILT X_BILIN_FILT X_MODE13FACT -%token X_WINSIZE X_NOCLOSE X_NORESIZE +%token X_FIXED_ASPECT X_ASPECT_43 X_LIN_FILT X_BILIN_FILT X_MODE13FACT X_WINSIZE %token X_GAMMA X_FULLSCREEN VGAEMU_MEMSIZE VESAMODE X_LFB X_PM_INTERFACE X_MGRAB_KEY X_BACKGROUND_PAUSE /* sdl */ -%token SDL_HWREND SDL_FONTS SDL_WCONTROLS SDL_CLIP_NATIVE +%token SDL_HWREND SDL_FONTS /* video */ %token VGA MGA CGA EGA NONE CONSOLE GRAPHICS CHIPSET FULLREST PARTREST %token MEMSIZE VBIOS_SIZE_TOK VBIOS_SEG VGAEMUBIOS_FILE VBIOS_FILE @@ -300,10 +300,8 @@ enum { /* hardware ram mapping */ %token HARDWARE_RAM /* Sound Emulation */ -%token SB_BASE SB_IRQ SB_DMA SB_HDMA MPU_BASE MPU_BASE_MT32 -%token MPU_IRQ MPU_IRQ_MT32 MIDI_SYNTH -%token SOUND_DRIVER MIDI_DRIVER FLUID_SFONT FLUID_VOLUME -%token MUNT_ROMS OPL2LPT_DEV OPL2LPT_TYPE +%token SB_BASE SB_IRQ SB_DMA SB_HDMA MPU_BASE MPU_IRQ MPU_IRQ_MT32 MIDI_SYNTH +%token SOUND_DRIVER MIDI_DRIVER MUNT_ROMS OPL2LPT_DEV OPL2LPT_TYPE %token SND_PLUGIN_PARAMS PCM_HPF MIDI_FILE WAV_FILE /* CD-ROM */ %token CDROM @@ -314,7 +312,8 @@ enum { /* joystick */ %token JOYSTICK JOY_DEVICE JOY_DOS_MIN JOY_DOS_MAX JOY_GRANULARITY JOY_LATENCY /* Hacks */ -%token CLI_TIMEOUT TIMEMODE TIMER_TWEAKS +%token CLI_TIMEOUT +%token TIMEMODE /* we know we have 1 shift/reduce conflict :-( * and tell the parser to ignore that */ @@ -421,8 +420,7 @@ line: CHARSET '{' charset_flags '}' {} } | DOSEMUMAP string_expr { - free(dosemu_map_file_name); - dosemu_map_file_name = $2; + DOSEMU_MAP_PATH = $2; c_printf("CONF: dosemu.map path = '%s'\n", $2); } | MAPPINGDRIVER string_expr @@ -485,7 +483,7 @@ line: CHARSET '{' charset_flags '}' {} #ifdef X86_EMULATOR config.cpusim = $2; c_printf("CONF: CPUEMU set to %s\n", - config.cpusim ? "sim" : "jit"); + CONFIG_CPUSIM ? "sim" : "jit"); #endif } | CPUSPEED real_expression @@ -508,6 +506,12 @@ line: CHARSET '{' charset_flags '}' {} } #endif } + | RDTSC bool + { + config.rdtsc = ($2!=0); + c_printf("CONF: %sabling use of pentium timer\n", + (config.rdtsc?"En":"Dis")); + } | PCI bool { config.pci_video = ($2!=0); @@ -584,6 +588,8 @@ line: CHARSET '{' charset_flags '}' {} } | EMURETRACE bool { + if ($2 && !config.emuretrace && priv_lvl) + yyerror("Can not modify video port access in user config file"); config.emuretrace = ($2!=0); c_printf("CONF: emu_retrace %s\n", ($2) ? "on" : "off"); } @@ -600,38 +606,28 @@ line: CHARSET '{' charset_flags '}' {} } | UMB_B0 bool { - config.umb_b0 = $2; + config.umb_b0 = ($2!=0); if ($2 > 0) c_printf("CONF: umb at 0b0000: %s\n", ($2) ? "on" : "off"); } - | UMB_B8 bool - { - config.umb_b8 = $2; - if ($2 > 0) c_printf("CONF: umb at 0b8000: %s\n", ($2) ? "on" : "off"); - } | UMB_F0 bool { config.umb_f0 = ($2!=0); if ($2 > 0) c_printf("CONF: umb at 0f0000: %s\n", ($2) ? "on" : "off"); } - | HMA bool - { - config.hma = ($2!=0); - if ($2 > 0) c_printf("CONF: HMA is: %s\n", ($2) ? "on" : "off"); - } - | DOS_UP bool - { - config.dos_up = $2; - if ($2 > 0) c_printf("CONF: dos_up: %s\n", ($2) ? "on" : "off"); - } | L_DPMI int_bool { if ($2>=0) config.dpmi = $2; c_printf("CONF: DPMI-Server %s (%#x)\n", ($2) ? "on" : "off", ($2)); } - | DPMI_BASE int_bool + | DPMI_LIN_RSV_BASE int_bool { - config.dpmi_base = $2; - c_printf("CONF: DPMI base addr = %#x\n", $2); + config.dpmi_lin_rsv_base = $2; + c_printf("CONF: DPMI linear reserve base addr = %#x\n", $2); + } + | DPMI_LIN_RSV_SIZE int_bool + { + config.dpmi_lin_rsv_size = $2; + c_printf("CONF: DPMI linear reserve size = %#x\n", $2); } | PM_DOS_API bool { @@ -647,11 +643,6 @@ line: CHARSET '{' charset_flags '}' {} | EXT_MEM int_bool { if ($2>=0) config.ext_mem = $2; - if ($2 > 0) c_printf("CONF: %dk bytes int15 ext memory\n", $2); - } - | L_XMS int_bool - { - if ($2>=0) config.xms_size = $2; if ($2 > 0) c_printf("CONF: %dk bytes XMS memory\n", $2); } | MATHCO bool { config.mathco = ($2!=0); } @@ -677,7 +668,6 @@ line: CHARSET '{' charset_flags '}' {} | TAPDEV string_expr { free(config.tapdev); config.tapdev = $2; } | VDESWITCH string_expr { free(config.vdeswitch); config.vdeswitch = $2; } | SLIRPARGS string_expr { free(config.slirp_args); config.slirp_args = $2; } - | NETSOCK string_expr { free(config.netsock); config.netsock = $2; } | NOVELLHACK bool { config.pktflags = ($2!=0); } | VNET string_expr { start_vnet($2); free($2); } | SPEAKER speaker @@ -748,7 +738,7 @@ line: CHARSET '{' charset_flags '}' {} '{' trace_mmio_flags '}' | DISK { start_disk(); } - '{' disk_type disk_flags '}' + '{' disk_flags '}' { stop_disk(DISK); } | L_FLOPPY { start_floppy(); } @@ -798,6 +788,10 @@ line: CHARSET '{' charset_flags '}' {} } } | HARDWARE_RAM + { + if (priv_lvl) + yyerror("Can not change hardware ram access settings in user config file"); + } '{' hardware_ram_flags '}' | FEATURE '{' expression '=' expression '}' { @@ -811,8 +805,6 @@ line: CHARSET '{' charset_flags '}' {} c_printf("CONF: time mode = '%s'\n", $2); free($2); } - | TIMER_TWEAKS bool - { config.timer_tweaks = ($2 != 0); } | UEXEC string_expr { free(config.unix_exec); config.unix_exec = $2; } | LPATHS string_expr @@ -1097,8 +1089,6 @@ x_flag : L_DISPLAY string_expr { free(config.X_display); config.X_display = $2; } | X_GAMMA expression { config.X_gamma = $2; } | X_FULLSCREEN bool { config.X_fullscreen = $2; } - | X_NOCLOSE bool { config.X_noclose = ($2!=0); } - | X_NORESIZE bool { config.X_noresize = ($2!=0); } | VGAEMU_MEMSIZE expression { config.vgaemu_memsize = $2; } | VESAMODE INTEGER INTEGER { set_vesamodes($2,$3,0);} | VESAMODE INTEGER INTEGER INTEGER { set_vesamodes($2,$3,$4);} @@ -1117,8 +1107,6 @@ sdl_flags : sdl_flag ; sdl_flag : SDL_HWREND expression { config.sdl_hwrend = ($2!=0); } | SDL_FONTS string_expr { free(config.sdl_fonts); config.sdl_fonts = $2; } - | SDL_WCONTROLS expression { config.sdl_wcontrols = ($2!=0); } - | SDL_CLIP_NATIVE bool { config.sdl_clip_native = ($2!=0); } ; /* sb emulation */ @@ -1131,24 +1119,21 @@ sound_flag : SB_BASE expression { config.sb_base = $2; } | SB_HDMA expression { config.sb_hdma = $2; } | SB_IRQ expression { config.sb_irq = $2; } | MPU_BASE expression { config.mpu401_base = $2; } - | MPU_BASE_MT32 expression { config.mpu401_base_mt32 = $2; } | MIDI_SYNTH string_expr { free(config.midi_synth); config.midi_synth = $2; } | MPU_IRQ int_bool { config.mpu401_irq = $2; } | MPU_IRQ_MT32 expression { config.mpu401_irq_mt32 = $2; } | SOUND_DRIVER string_expr { free(config.sound_driver); config.sound_driver = $2; } | MIDI_DRIVER string_expr { free(config.midi_driver); config.midi_driver = $2; } - | FLUID_SFONT string_expr { free(config.fluid_sfont); config.fluid_sfont = $2; } - | FLUID_VOLUME expression { config.fluid_volume = $2; } | MUNT_ROMS string_expr { free(config.munt_roms_dir); - config.munt_roms_dir = concat_dir(dosemu_localdir_path, $2); + config.munt_roms_dir = concat_dir(LOCALDIR, $2); free($2); } | OPL2LPT_DEV string_expr { free(config.opl2lpt_device); - config.opl2lpt_device = $2; + config.opl2lpt_device = strlen($2) ? $2 : NULL; } | OPL2LPT_TYPE string_expr { @@ -1369,10 +1354,6 @@ mouse_flag : DEVICE string_expr { free(mptr->dev); mptr->dev = $2; } mptr->dev_type = MOUSE_BUSMOUSE; mptr->flags = 0; } - | UNGRAB_TWEAK bool - { - mptr->ignore_speed = ($2!=0); - } | STRING { yyerror("unrecognized mouse flag '%s'", $1); free($1); } | error @@ -1456,9 +1437,6 @@ serial_flag : DEVICE string_expr { free(sptr->dev); sptr->dev = $2; } sptr->pseudo = TRUE; no_local_video = 1; sptr->dev = strdup(ttyname(0)); - config.dumb_video = 1; - if (!config.tty_stderr) // can be 2 - config.tty_stderr = 1; } else { error("FD 0 is not a tty, can't " "use a virtual com port\n"); @@ -1475,14 +1453,6 @@ serial_flag : DEVICE string_expr { free(sptr->dev); sptr->dev = $2; } | IRQ expression { sptr->irq = $2; } | MOUSE { sptr->mouse = 1; config.num_serial_mices++; } - | EXEC string_expr { free(sptr->exec); - sptr->exec = $2; } - | PTS string_expr { free(sptr->pts); - sptr->pts = $2; } - | WRFILE string_expr { free(sptr->wrfile); - sptr->wrfile = $2; } - | NULLMM string_expr { sptr->nullmm = atoi($2); free($2); } - | READONLY { sptr->ro = 1; } | STRING { yyerror("unrecognized serial flag '%s'", $1); free($1); } | error @@ -1557,7 +1527,7 @@ floppy_flag : READONLY { dptr->rdonly = 1; } | error ; -disk_flags : +disk_flags : disk_flag | disk_flags disk_flag ; disk_flag : READONLY { dptr->rdonly = 1; } @@ -1570,13 +1540,20 @@ disk_flag : READONLY { dptr->rdonly = 1; } | TRACKS expression { dptr->tracks = $2; } | HEADS expression { dptr->heads = $2; } | OFFSET expression { dptr->header = $2; } - | L_PARTITION { dptr->part_image = 1; } - | STRING - { yyerror("unrecognized disk flag '%s'\n", $1); free($1); } - | error - ; - -disk_type : HDIMAGE string_expr + | DEVICE string_expr + { + if (dptr->dev_name != NULL) + yyerror("Two names for a disk-image file or device given."); + free(dptr->dev_name); + dptr->dev_name = $2; + } + | L_FILE string_expr + { + if (dptr->dev_name != NULL) + yyerror("Two names for a disk-image file or device given."); + dptr->dev_name = $2; + } + | HDIMAGE string_expr { if (dptr->dev_name != NULL) yyerror("Two names for a harddisk-image file given."); @@ -1606,7 +1583,7 @@ disk_type : HDIMAGE string_expr dptr->dev_name = $2; } | STRING - { yyerror("unrecognized disk type '%s'\n", $1); free($1); } + { yyerror("unrecognized disk flag '%s'\n", $1); free($1); } | error ; @@ -1619,13 +1596,13 @@ port_flag : INTEGER { c_printf("CONF: I/O port 0x%04x\n", (unsigned short)$1); allow_io($1, 1, ports_permission, ports_ormask, - ports_andmask, portspeed); + ports_andmask, portspeed, (char*)dev_name); if (portspeed) portspeed += ((portspeed>0) ? 1 : -1); } | '(' expression ')' { allow_io($2, 1, ports_permission, ports_ormask, - ports_andmask, portspeed); + ports_andmask, portspeed, (char*)dev_name); if (portspeed) portspeed += ((portspeed>0) ? 1 : -1); } | RANGE INTEGER INTEGER @@ -1634,8 +1611,9 @@ port_flag : INTEGER c_printf("CONF: range of I/O ports 0x%04x-0x%04x\n", (unsigned short)$2, (unsigned short)$3); allow_io($2, $3 - $2 + 1, ports_permission, ports_ormask, - ports_andmask, portspeed); + ports_andmask, portspeed, (char*)dev_name); portspeed=0; + strcpy(dev_name,""); } | RANGE expression ',' expression { @@ -1643,8 +1621,9 @@ port_flag : INTEGER c_printf("CONF: range of I/O ports 0x%04x-0x%04x\n", (unsigned short)$2, (unsigned short)$4); allow_io($2, $4 - $2 + 1, ports_permission, ports_ormask, - ports_andmask, portspeed); + ports_andmask, portspeed, (char*)dev_name); portspeed=0; + strcpy(dev_name,""); } | RDONLY { ports_permission = IO_READ; } | WRONLY { ports_permission = IO_WRITE; } @@ -1653,7 +1632,7 @@ port_flag : INTEGER | ANDMASK expression { ports_andmask = $2; } | FAST { portspeed = 1; } | SLOW { portspeed = -1; } - | DEVICE string_expr { /* compatibility */ free($2); } + | DEVICE string_expr { strcpy(dev_name,$2); free($2); } | STRING { yyerror("unrecognized port command '%s'", $1); free($1); } @@ -1946,6 +1925,8 @@ static void stop_mouse(void) static void start_ports(void) { + if (priv_lvl) + yyerror("Can not change port privileges in user config file"); ports_permission = IO_RDWR; ports_ormask = 0; ports_andmask = 0xFFFF; @@ -1980,6 +1961,9 @@ static void start_video(void) static void stop_video(void) { + if (priv_lvl) + config.console_video = 0; + if ((config.cardtype != CARD_VGA) || !config.console_video) { config.vga = 0; } @@ -2014,7 +1998,7 @@ static void detect_vbios(void) if (c[0]==0x55 && c[1]==0xaa && c[0x1e]=='I' && c[0x1f]=='B' && c[0x20]=='M') { auto_vbios_seg = foffset >> 4; - auto_vbios_size = PAGE_ALIGN(c[2] * 0x200); + auto_vbios_size = c[2]*0x200; break; } } @@ -2270,9 +2254,6 @@ static void stop_disk(int token) #endif } - if (dptr->type == IMAGE && dptr->part_image) - dptr->type = PARTITION; // image of a partition - if (dptr->type == IMAGE) { char buf[HEADER_SIZE]; struct image_header *header = (struct image_header *)&buf; @@ -2483,7 +2464,7 @@ static void set_hdimage(struct disk *dptr, char *name) c_printf("Setting up hdimage %s\n", name); if (l && strlen(l) == 4) { - const char *tmpl = "eval printf `cat %s`"; + const char *tmpl = "eval echo -n `cat %s`"; char *cmd, path[1024], *rname; FILE *f; size_t ret; @@ -2555,7 +2536,7 @@ static void set_drive_c(void) } if (config.alt_drv_c && c_hdisks) { error("wrong mapping of Group 0 to %c\n", 'C' + c_hdisks); - dosemu_drive_c_path = strdup(DRIVE_C_DEFAULT); + dosemu_drive_c_path = DRIVE_C_DEFAULT; config.alt_drv_c = 0; } config.drive_c_num = c_hdisks | 0x80; @@ -2654,15 +2635,18 @@ static void do_parse(FILE *fp, const char *confname, const char *errtx) free(file_being_parsed); } -int parse_config(const char *confname, const char *dosrcname, int nodosrc) +int parse_config(const char *confname, const char *dosrcname) { - char *dosrc = NULL; FILE *fd; #if YYDEBUG != 0 yydebug = 1; #endif define_config_variable(PARSER_VERSION_STRING); + + /* privileged options allowed? */ + priv_lvl = !under_root_login && can_do_root_stuff; + define_config_variable("c_system"); yy_vbuffer = dosemu_conf; @@ -2676,51 +2660,15 @@ int parse_config(const char *confname, const char *dosrcname, int nodosrc) } do_parse(fd, confname, "error in configuration file %s"); } - move_dosemu_local_dir(); - if (!nodosrc) { - char *newdosrc = NULL; - if (!dosrcname) { - dosrcname = getenv("_dosemurc"); - newdosrc = assemble_path(dosemu_localdir_path, dosrcname); - if (access(newdosrc, R_OK) == -1) - dosrcname = NULL; - else - dosrcname = newdosrc; - } - if (!dosrcname) { - dosrc = assemble_path(dosemu_localdir_path, DOSEMU_RC); - if (access(dosrc, R_OK) == -1) { - free(dosrc); - dosrc = get_path_in_HOME(DOSEMU_RC); - } else if (newdosrc) { - error("config file %s missing.\n\tUsing %s\n" - "\tExecute `mv %s %s`\n\tto silence this error.\n", - newdosrc, dosrc, dosrc, newdosrc); - } - if (access(dosrc, R_OK) == -1) { - free(dosrc); - dosrc = NULL; - } - } else { - dosrc = strdup(dosrcname); - } - if (newdosrc) { - free(newdosrc); - newdosrc = NULL; - } - } - if (dosrc) { + if (dosrcname) { define_config_variable("c_user"); yy_vbuffer = NULL; - fd = open_file(dosrc); + fd = open_file(dosrcname); if (!fd) { - fprintf(stderr, "Cannot open base config file %s, Aborting DOSEMU.\n", - dosrc); - free(dosrc); + fprintf(stderr, "Cannot open base config file %s, Aborting DOSEMU.\n", dosrcname); exit(1); } - do_parse(fd, dosrc, "error in configuration file %s"); - free(dosrc); + do_parse(fd, dosrcname, "error in configuration file %s"); } yy_vbuffer = global_conf; do_parse(NULL, "built-in global.conf", "error in built-in global.conf"); @@ -2728,6 +2676,8 @@ int parse_config(const char *confname, const char *dosrcname, int nodosrc) undefine_config_variable("c_system"); /* Now we parse any commandline statements from option '-I' + * We do this under priv_lvl set above, so we have the same secure level + * as with .dosrc */ if (commandline_statements) { @@ -2769,6 +2719,12 @@ char *get_config_variable(const char *name) int define_config_variable(const char *name) { + if (priv_lvl) { + if (strcmp(name, CONFNAME_V3USED) && strncmp(name, "u_", 2)) { + c_printf("CONF: not enough privilege to define config variable %s\n", name); + return 0; + } + } if (!get_config_variable(name)) { if (config_variables_count < MAX_CONFIGVARIABLES) { config_variables[config_variables_count++] = strdup(name); @@ -2784,6 +2740,12 @@ int define_config_variable(const char *name) static int undefine_config_variable(const char *name) { + if (priv_lvl) { + if (strncmp(name, "u_", 2)) { + c_printf("CONF: not enough privilege to undefine config variable %s\n", name); + return 0; + } + } if (get_config_variable(name)) { int i; if (!strcmp(name, CONFNAME_V3USED)) parser_version_3_style_used = 0; diff --git a/src/base/kbd_unicode/getfd.c b/src/base/kbd_unicode/getfd.c index d32df8d..b7af6c7 100644 --- a/src/base/kbd_unicode/getfd.c +++ b/src/base/kbd_unicode/getfd.c @@ -91,7 +91,7 @@ int open_console(void) return cons_fd; } -int getfd(void) +int getfd() { return cons_fd; } diff --git a/src/base/kbd_unicode/keyb_clients.c b/src/base/kbd_unicode/keyb_clients.c index 7e3e5b9..56497ae 100644 --- a/src/base/kbd_unicode/keyb_clients.c +++ b/src/base/kbd_unicode/keyb_clients.c @@ -20,7 +20,6 @@ static t_unicode *paste_buffer = NULL; static int paste_len = 0, paste_idx = 0; struct keyboard_client *Keyboard; -static struct keyboard_client *Kbd_root; static int paste_unicode_text(const t_unicode *text, int len) { @@ -102,10 +101,10 @@ void register_keyboard_client(struct keyboard_client *keyboard) struct keyboard_client *k; keyboard->next = NULL; - if (Kbd_root == NULL) - Kbd_root = keyboard; + if (Keyboard == NULL) + Keyboard = keyboard; else { - for (k = Kbd_root; k->next; k = k->next); + for (k = Keyboard; k->next; k = k->next); k->next = keyboard; } } @@ -117,7 +116,7 @@ void register_keyboard_client(struct keyboard_client *keyboard) * First it calls the probe method to see if it should use the client, * Then it call init to set that client up. * - * If probe or init fails it tries another client. + * If probe or init fails it trys another client. * * Eventually falling back to Keyboard_none a dummy client, which does nothing. * @@ -128,9 +127,8 @@ int keyb_client_init(void) int ok; register_keyboard_client(&Keyboard_raw); - register_keyboard_client(&Keyboard_stdio); register_keyboard_client(&Keyboard_none); - for (Keyboard = Kbd_root; Keyboard; Keyboard = Keyboard->next) { + while(Keyboard) { k_printf("KBD: probing '%s' mode keyboard client\n", Keyboard->name); ok = Keyboard->probe(); @@ -150,6 +148,7 @@ int keyb_client_init(void) Keyboard->name); } } + Keyboard = Keyboard->next; } sigalrm_register_handler(paste_run); diff --git a/src/base/kbd_unicode/keyb_none.c b/src/base/kbd_unicode/keyb_none.c index f097e35..51c68d4 100644 --- a/src/base/kbd_unicode/keyb_none.c +++ b/src/base/kbd_unicode/keyb_none.c @@ -11,77 +11,48 @@ */ #include -#include "ioselect.h" #include "keyb_clients.h" -static void stdio_kbd_run(int fd, void *arg); +static void none_run(void *arg); -/* DANG_BEGIN_FUNCTION stdio_kbd_probe +/* DANG_BEGIN_FUNCTION none_probe * * Succeed if we can run the dummy keyboard client, (we always can). * * DANG_END_FUNCTION */ -static int stdio_kbd_probe(void) +static int none_probe(void) { - if (no_local_video) - return 0; return 1; } -static int stdio_kbd_init(void) +static int none_init(void) { - add_to_io_select(STDIN_FILENO, stdio_kbd_run, NULL); + add_to_io_select(STDIN_FILENO, none_run, NULL); return 1; } -static void stdio_kbd_close(void) +static void none_close(void) { remove_from_io_select(STDIN_FILENO); } -static void stdio_kbd_run(int fd, void *arg) +static void none_run(void *arg) { char buf[256]; int rc; rc = read(STDIN_FILENO, buf, sizeof(buf)); - ioselect_complete(fd); if (rc > 0) paste_text(buf, rc, "utf8"); } -struct keyboard_client Keyboard_stdio = -{ - "stdio", /* name */ - stdio_kbd_probe, /* probe */ - stdio_kbd_init, /* init */ - NULL, /* reset */ - stdio_kbd_close, /* close */ - NULL, /* set_leds */ -}; - - -static int none_kbd_probe(void) -{ - return 1; -} - -static int none_kbd_init(void) -{ - return 1; -} - -static void none_kbd_close(void) -{ -} - struct keyboard_client Keyboard_none = { - "none", /* name */ - none_kbd_probe, /* probe */ - none_kbd_init, /* init */ + "stdio", /* name */ + none_probe, /* probe */ + none_init, /* init */ NULL, /* reset */ - none_kbd_close, /* close */ + none_close, /* close */ NULL, /* set_leds */ }; diff --git a/src/base/kbd_unicode/keyb_raw.c b/src/base/kbd_unicode/keyb_raw.c index 32bccac..f53c5bb 100644 --- a/src/base/kbd_unicode/keyb_raw.c +++ b/src/base/kbd_unicode/keyb_raw.c @@ -14,7 +14,7 @@ #endif #include -#include "ioselect.h" +#include "emu.h" #include "keyboard.h" #include "keyb_clients.h" #include "translate/keysym_attributes.h" @@ -96,13 +96,12 @@ static int use_move_key(t_keysym key) return result; } -static void do_raw_getkeys(int fd, void *arg) +static void do_raw_getkeys(void *arg) { int i,count; char buf[KBBUF_SIZE]; count = RPT_SYSCALL(read(kbd_fd, buf, KBBUF_SIZE - 1)); - ioselect_complete(fd); k_printf("KBD(raw): do_raw_getkeys() found %d characters (Raw)\n", count); if (count == -1) { k_printf("KBD(raw): do_raw_getkeys(): keyboard read failed!\n"); @@ -149,25 +148,20 @@ static void print_termios(struct termios term) } #endif -static int set_raw_mode(void) +static inline void set_raw_mode(void) { struct termios buf = save_termios; -#ifdef HAVE_SYS_KD_H - int err; +#ifdef HAVE_SYS_KD_H if (config.console_keyb == KEYB_RAW) { k_printf("KBD(raw): Setting keyboard to RAW mode\n"); - err = ioctl(kbd_fd, KDSKBMODE, K_RAW); - if (err) - return err; + ioctl(kbd_fd, KDSKBMODE, K_RAW); } #endif cfmakeraw(&buf); k_printf("KBD(raw): Setting TERMIOS Structure.\n"); - if (tcsetattr(kbd_fd, TCSAFLUSH, &buf) < 0) { + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &buf) < 0) k_printf("KBD(raw): Setting TERMIOS structure failed.\n"); - return -1; - } #if 0 /* debug code */ if (tcgetattr(kbd_fd, &buf) < 0) { @@ -175,7 +169,6 @@ static int set_raw_mode(void) } print_termios(buf); #endif - return 0; } /* @@ -203,8 +196,7 @@ static int raw_keyboard_init(void) return FALSE; } - if (set_raw_mode() == -1) - return FALSE; + set_raw_mode(); add_to_io_select(kbd_fd, do_raw_getkeys, NULL); @@ -252,8 +244,6 @@ static void raw_keyboard_close(void) static int raw_keyboard_probe(void) { - if (no_local_video) - return 0; return isatty(STDIN_FILENO); } diff --git a/src/base/kbd_unicode/keymaps.c b/src/base/kbd_unicode/keymaps.c index bdbe91b..33b43dd 100644 --- a/src/base/kbd_unicode/keymaps.c +++ b/src/base/kbd_unicode/keymaps.c @@ -2080,7 +2080,7 @@ static char* pretty_keysym(t_keysym d) * with the X keymap (if X is available) and chose the * best one. */ -void setup_default_keytable(void) +void setup_default_keytable() { static const char *dt_name = "auto"; static t_keysym diff --git a/src/base/kbd_unicode/prestroke.c b/src/base/kbd_unicode/prestroke.c index c16b00f..ddb6f70 100644 --- a/src/base/kbd_unicode/prestroke.c +++ b/src/base/kbd_unicode/prestroke.c @@ -19,7 +19,6 @@ static int default_stroke_pause = -1; static int stroke_pause; -static int stroke_started; #define GETNUMBER(s) ({ \ @@ -133,10 +132,6 @@ static t_unicode *type_one_key(t_unicode *in) move_key(RELEASE, keynum); return in; } - case '_': /* space */ - move_key(PRESS, DKY_SPACE); - move_key(RELEASE, DKY_SPACE); - return in; default: ; /* fall through */ @@ -158,9 +153,6 @@ static t_unicode *pre_stroke = 0, *pre_stroke_mem = 0; int type_in_pre_strokes(void) { struct char_set *keyb_charset = trconfig.keyb_charset; - - if (!stroke_started) - return stroke_pause; if (config.pre_stroke && !pre_stroke) { size_t characters, src_len; const char *ptr; @@ -190,6 +182,8 @@ int type_in_pre_strokes(void) return stroke_pause; } + + void append_pre_strokes(char *s) { if (config.pre_stroke) { @@ -207,8 +201,3 @@ void append_pre_strokes(char *s) config.pre_stroke = strdup(s); } } - -void start_pre_strokes(void) -{ - stroke_started++; -} diff --git a/src/base/kbd_unicode/serv_backend.c b/src/base/kbd_unicode/serv_backend.c index b1de586..a6fcc2c 100644 --- a/src/base/kbd_unicode/serv_backend.c +++ b/src/base/kbd_unicode/serv_backend.c @@ -44,7 +44,7 @@ * Interface to DOS (BIOS keyboard buffer/shiftstate flags) */ -void clear_bios_keybuf(void) +void clear_bios_keybuf() { WRITE_WORD(BIOS_KEYBOARD_BUFFER_START,0x001e); WRITE_WORD(BIOS_KEYBOARD_BUFFER_END, 0x003e); diff --git a/src/base/kbd_unicode/serv_xlat.c b/src/base/kbd_unicode/serv_xlat.c index 68253da..e9b43a3 100644 --- a/src/base/kbd_unicode/serv_xlat.c +++ b/src/base/kbd_unicode/serv_xlat.c @@ -38,7 +38,7 @@ /* Note: * While it is very bad to hard code keys, dos has already * hard coded the shift keys, the number pad keys, and - * virtually everything but the letter keys. Dosemu cannot + * virtually everthing but the letter keys. Dosemu cannot * remove this hard coding without confusing dos programs. * The point of dosemu's configurability is primarily to * allow non-us keyboards to work as they would in dos. Not @@ -382,7 +382,6 @@ static void init_misc_shift_altgr_map(t_keysym *rule) static void init_misc_ctrl_alt_map(t_keysym *rule) { rule[NUM_PAD_AST] = DKY_DOSEMU_REBOOT; - rule[NUM_8] = DKY_DOSEMU_REBOOT; /* C-A-D is disabled */ // rule[NUM_DEL] = DKY_DOSEMU_REBOOT; @@ -511,7 +510,7 @@ static void dump_translate_rules(struct scancode_translate_rules *rules) #endif /* FIXME: I need external input for ctrl mappings! - * I have a clever hack that gets it right most of the time, + * I have a clever hack that get's it right most of the time, * but it's not quite right. Also some ctrl keys are hardwired to * their position on a US keyboard. */ @@ -868,7 +867,7 @@ static Bit16u make_bios_code_r(Boolean make, t_keynum key, /* Note: * While it is very bad to hard code keys, dos has already * hard coded the shift keys, the number pad keys, and - * virtually everything but the letter keys. Dosemu cannot + * virtually everthing but the letter keys. Dosemu cannot * remove this hard coding without confusing dos programs. * The point of dosemu's configurability is primarily to * allow non-us keyboards to work as they would in dos. Not @@ -1311,7 +1310,7 @@ t_keynum compute_functional_keynum(Boolean make, t_keynum keynum, { unsigned char *keys = keystate->keys; Boolean old_make; - /* first handle the virtual keys */ + /* first handle the virutal keys */ switch(keynum) { case NUM_PRTSCR_SYSRQ: /* If the key is already pressed find out what key it @@ -1403,7 +1402,7 @@ static void update_keypressed_state(Boolean make, t_keynum keynum, } } -/* additionally strings */ +/* additionaly strings */ #define SCN_FAKE_L_SHIFT 0xe02a #define SCN_FAKE_R_SHIFT 0xe036 #define SCN_PAUSE 0xe11d45 @@ -1517,7 +1516,7 @@ static void put_keynum_r(Boolean make, t_keynum input_keynum, struct keyboard_st * the numlock state. Since I depend on being able to * pretranslate the keyboard for cut and paste, I'll just use * my expected numlock state. - * At any rate this is just a heuristic, and not guaranteed to + * At any rate this is just a heuristic, and not garanteed to * be correct so any reasonable approximation should be fine. */ Boolean num_state = !!(state->shiftstate & NUM_LOCK); @@ -1746,7 +1745,7 @@ t_keynum compute_keynum(Boolean *make_ret, * translate_key takes a keysym event and calculates the appropriate * bios translation. * - * As a side effect translate_key updates the appropriate pieces of state + * As a side effect translate_key updates the apropriate pieces of state * to reflect the current keyboard state. * * Calling translate_key twice on the same data is likely to be hazardous. @@ -1803,7 +1802,7 @@ Bit16u translate_key(Boolean make, t_keynum key, -/* typing a specific character */ +/* typing a specifc character */ /* get the logical modifiers from the keyboard state */ @@ -2132,7 +2131,7 @@ void put_rawkey(t_rawkeycode code) * * Applications using int16h will always see the appropriate ASCII code * for the given keyboard key and the current keyboard state. All the - * character translation is done for you to keep from reporting + * chracter translation is done for you to keep from reporting * inconsistent key events. * * An emulated hardware scancode is also sent to port60h. @@ -2220,7 +2219,7 @@ t_keynum keysym_to_keynum(t_keysym key, t_modifiers * modifiers) * * Applications using int16h will always see the appropriate ASCII code * for the given keyboard key and the current keyboard state. All the - * character translation is done for you to keep from reporting + * chracter translation is done for you to keep from reporting * inconsistent key events. * * An emulated hardware scancode is also sent to port60h. @@ -2298,7 +2297,7 @@ void put_symbol(Boolean make, t_keysym sym) * * For cases where the symbol can only be created by an alt# combination * or by pressing a dead key (Basically any case where more than one - * key is required, after setting the shiftstate) it gives up and just + * key is requried, after setting the shiftstate) it gives up and just * sends the symbol. * * Note that you have to send both MAKE (press) and BREAK (release) events. @@ -2323,8 +2322,8 @@ void put_modified_symbol(Boolean make, t_modifiers modifiers, t_keysym sym) * This is intended to be used in conjunction with set_shiftstate * to sync up a shiftstate with a source of key events. * - * With the addition of this function the keyboard interface is clean enough - * so if needed a completely different translation engine can be dropped in + * With the addition of this function the keyboard inteface is clean enough + * so if needed a completly different translation engine can be dropped in * to support a totally different environment (windows or whatever). * * DANG_END_FUNCTION diff --git a/src/base/lib/libpcl/pcl.h b/src/base/lib/libpcl/pcl.h index 1b468c2..ad4e063 100644 --- a/src/base/lib/libpcl/pcl.h +++ b/src/base/lib/libpcl/pcl.h @@ -32,20 +32,9 @@ typedef void *coroutine_t; typedef void *cohandle_t; -#define _WANT_UCONTEXT 0 -#if _WANT_UCONTEXT || !defined(MCONTEXT) #define WANT_UCONTEXT 1 -#else -#define WANT_UCONTEXT 0 -#endif -enum CoBackend { -#ifdef MCONTEXT - PCL_C_MC, -#else -/* our libmcontext doesn't yet support aarch64 */ -#define PCL_C_MC PCL_C_UC -#endif +enum CoBackend {PCL_C_MC, #if WANT_UCONTEXT PCL_C_UC, #endif diff --git a/src/base/lib/libpcl/pcl_ctx.c b/src/base/lib/libpcl/pcl_ctx.c index c0c0da2..3d6b8bb 100644 --- a/src/base/lib/libpcl/pcl_ctx.c +++ b/src/base/lib/libpcl/pcl_ctx.c @@ -22,9 +22,7 @@ #include #include -#ifdef MCONTEXT #include "mcontext.h" -#endif #include "pcl.h" #include "pcl_private.h" #include "pcl_ctx.h" @@ -69,7 +67,6 @@ static struct pcl_ctx_ops ctx_ops = { }; #endif -#ifdef MCONTEXT static int mctx_get_context(struct s_co_ctx *ctx) { return getmcontext((m_ucontext_t *)ctx->cc); @@ -107,12 +104,9 @@ static struct pcl_ctx_ops mctx_ops = { .set_context = mctx_set_context, .swap_context = mctx_swap_context, }; -#endif static struct pcl_ctx_ops *ops_arr[] = { -#ifdef MCONTEXT /*[PCL_C_MC] = */&mctx_ops, -#endif #if WANT_UCONTEXT /*[PCL_C_UC] = */&ctx_ops, #endif @@ -130,10 +124,8 @@ int ctx_init(enum CoBackend b, struct pcl_ctx_ops **ops) int ctx_sizeof(enum CoBackend b) { switch (b) { -#ifdef MCONTEXT case PCL_C_MC: return sizeof(m_ucontext_t); -#endif #if WANT_UCONTEXT case PCL_C_UC: return sizeof(ucontext_t); diff --git a/src/base/lib/libpcl/pcl_private.h b/src/base/lib/libpcl/pcl_private.h index 21f0ba1..e99fffd 100644 --- a/src/base/lib/libpcl/pcl_private.h +++ b/src/base/lib/libpcl/pcl_private.h @@ -60,7 +60,7 @@ typedef struct s_co_base { void *tmp; int stack_size; char *stack; - unsigned int exited:1; + int exited:1; } co_base; typedef diff --git a/src/base/lib/mapping/mapashm.c b/src/base/lib/mapping/mapashm.c deleted file mode 100644 index aeb361b..0000000 --- a/src/base/lib/mapping/mapashm.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: memory mapping library, anon-SHM backend. - * - * Authors: Stas Sergeev, Bart Oldeman. - */ - -#if defined(__linux__) || defined(__APPLE__) - -#include -#include - -#ifdef __APPLE__ -#include -#include -#endif - -#include "dosemu_debug.h" -#include "mapping.h" - -/* ------------------------------------------------------------ */ - -static void *alias_mapping_ashm(int cap, void *target, size_t mapsize, int protect, void *source) -{ - int flags; -#ifdef __APPLE__ - mach_vm_address_t targetaddr; - vm_prot_t cur, max; - - if (target != (void *)-1) { - flags = VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE; - targetaddr = (vm_address_t)target; - } else { - flags = VM_FLAGS_ANYWHERE; - targetaddr = (vm_address_t)NULL; - } - if (mach_vm_remap(mach_task_self(), &targetaddr, mapsize, 0, flags, - mach_task_self(), (mach_vm_address_t)source, FALSE, &cur, &max, VM_INHERIT_NONE) - != KERN_SUCCESS) - return MAP_FAILED; - - target = (void *)targetaddr; -#else - flags = MREMAP_MAYMOVE; - if (target != (void *)-1) - flags |= MREMAP_FIXED; - else - target = NULL; - target = mremap(source, 0, mapsize, flags, target); - if (target == MAP_FAILED) return MAP_FAILED; -#endif - mprotect(target, mapsize, protect); - return target; -} - -static int open_mapping_ashm(int cap) -{ - if (cap) Q_printf("MAPPING: open, cap=%s\n", - decode_mapping_cap(cap)); - return 1; -} - -static void close_mapping_ashm(int cap) -{ - Q_printf("MAPPING: close, cap=%s\n", decode_mapping_cap(cap)); -} - -static void *alloc_mapping_ashm(int cap, size_t mapsize, void *target) -{ - int fixed = 0; - - Q__printf("MAPPING: alloc, cap=%s, mapsize=%zx\n", cap, mapsize); - if (target != (void *)-1) - fixed = MAP_FIXED; - else - target = NULL; - return mmap(target, mapsize, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANONYMOUS | fixed, -1, 0); -} - -static void free_mapping_ashm(int cap, void *addr, size_t mapsize) -/* NOTE: addr needs to be the same as what was supplied by alloc_mapping_ashm */ -{ - Q__printf("MAPPING: free, cap=%s, addr=%p, mapsize=%zx\n", - cap, addr, mapsize); - munmap(addr, mapsize); -} - -static void *resize_mapping_ashm(int cap, void *addr, size_t oldsize, size_t newsize) -{ - void *ret = addr; - Q__printf("MAPPING: resize, cap=%s, addr=%p, oldsize=%zx, newsize=%zx\n", - cap, addr, oldsize, newsize); - - if (newsize < oldsize) { -#ifdef HAVE_MREMAP - ret = mremap(addr, oldsize, newsize, 0); - assert(ret == addr); -#else - /* ensure page-aligned */ - assert(!(oldsize & (PAGE_SIZE - 1))); - assert(!(newsize & (PAGE_SIZE - 1))); - if (munmap((unsigned char *)addr + newsize, oldsize - newsize) == -1) - ret = MAP_FAILED; -#endif - } else if (newsize > oldsize) { - ret = alloc_mapping_ashm(cap, newsize, NULL); - if (ret != MAP_FAILED) { - memcpy(ret, addr, oldsize); - free_mapping_ashm(cap, addr, oldsize); - } - } - return ret; -} - -struct mappingdrivers mappingdriver_ashm = { - "mapashm", - "anonymous non-expandable shared memory mapping", - open_mapping_ashm, - close_mapping_ashm, - alloc_mapping_ashm, - free_mapping_ashm, - resize_mapping_ashm, - alias_mapping_ashm -}; -#endif diff --git a/src/base/lib/mapping/mapfile.c b/src/base/lib/mapping/mapfile.c deleted file mode 100644 index 8180726..0000000 --- a/src/base/lib/mapping/mapfile.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: memory mapping library, posix SHM and file backends. - * - * Authors: Stas Sergeev, Bart Oldeman. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dosemu_debug.h" -#include "mapping.h" - -/* ------------------------------------------------------------ */ - -/* There are 255 EMS handles, 65 XMS handles, + 2 for lowmem + vgaemu - So 512 is definitely sufficient */ -#define MAX_FILE_MAPPINGS 512 -static struct file_mapping { - unsigned char *addr; /* pointer to allocated shared memory */ - size_t size; - size_t fsize; - int fd; - int prot; -} file_mappings[MAX_FILE_MAPPINGS]; - -typedef int (*open_cb_t)(void); -static open_cb_t open_cb; - -static struct file_mapping *find_file_mapping(unsigned char *target) -{ - int i; - struct file_mapping *p = file_mappings; - - for (i = 0; i < MAX_FILE_MAPPINGS; i++, p++) - if (p->size && target >= p->addr && target < &p->addr[p->size]) - break; - assert(i < MAX_FILE_MAPPINGS); - return p; -} - -/* Do not create mapping nodes for aliases, so can't alias the alias. - * This is the simplest design. */ -static void *alias_mapping_file(int cap, void *target, size_t mapsize, int protect, void *source) -{ - int fixed = 0; - struct file_mapping *p = find_file_mapping(source); - off_t offs = (unsigned char *)source - p->addr; - void *addr; - - if (offs + mapsize > p->size) { - Q_printf("MAPPING: alias_map to address outside of temp file\n"); - errno = EINVAL; - return MAP_FAILED; - } - if (target != (void *)-1) - fixed = MAP_FIXED; - else - target = NULL; - /* /dev/shm may be mounted noexec, and then mounting PROT_EXEC fails. - However mprotect may work around this (maybe not in future kernels) - alloc_mappings can just be rw though. - */ - addr = mmap(target, mapsize, protect, MAP_SHARED | fixed, p->fd, offs); - if (addr == MAP_FAILED) { - addr = mmap(target, mapsize, protect & ~PROT_EXEC, MAP_SHARED | fixed, - p->fd, offs); - if (addr != MAP_FAILED) { - int ret = mprotect(addr, mapsize, protect); - if (ret == -1) { - perror("mprotect()"); - error("shared memory mprotect failed, exiting\n"); - exit(2); - } - } else - perror("mmap()"); - } -#if 1 - Q_printf("MAPPING: alias_map, fileoffs %llx to %p size %zx, result %p\n", - (long long)offs, target, mapsize, addr); -#endif - return addr; -} - -static int do_open_file(void) -{ - char tmp[] = "/tmp/dosemu2_mapfile_XXXXXX"; - int fd = mkstemp(tmp); - if (fd == -1) { - perror("mkstemp()"); - return -1; - } - unlink(tmp); - return fd; -} - -static int open_mapping_file(int cap) -{ - if (cap == MAPPING_PROBE) { - open_cb_t o = do_open_file; - int fd = o(); - if (fd == -1) - return 0; - close(fd); - open_cb = o; - } - return 1; -} - -#ifdef HAVE_SHM_OPEN -static int do_open_pshm(void) -{ - char *name; - int ret, fd; - - ret = asprintf(&name, "/dosemu_%d", getpid()); - assert(ret != -1); - /* FD_CLOEXEC is set by default */ - fd = shm_open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); - if (fd == -1) { - free(name); - return -1; - } - shm_unlink(name); - free(name); - return fd; -} - -static int open_mapping_pshm(int cap) -{ - if (cap == MAPPING_PROBE) { - open_cb_t o = do_open_pshm; - int fd = o(); - if (fd == -1) - return 0; - close(fd); - open_cb = o; - } - return 1; -} -#endif - -#ifdef HAVE_MEMFD_CREATE -static int do_open_mshm(void) -{ - char *name; - int ret, fd; - - ret = asprintf(&name, "dosemu_%d", getpid()); - assert(ret != -1); - - fd = memfd_create(name, MFD_CLOEXEC); - free(name); - return fd; -} - -static int open_mapping_mshm(int cap) -{ - if (cap == MAPPING_PROBE) { - open_cb_t o = do_open_mshm; - int fd = o(); - if (fd == -1) - return 0; - close(fd); - open_cb = o; - } - return 1; -} -#endif - -static void do_free_mapping(struct file_mapping *p) -{ - munmap(p->addr, p->size); - close(p->fd); - p->size = 0; -} - -static void close_mapping_file(int cap) -{ - Q_printf("MAPPING: close, cap=%s\n", decode_mapping_cap(cap)); - if (cap == MAPPING_ALL) { - int i; - struct file_mapping *p; - for (i = 0, p = file_mappings; i < MAX_FILE_MAPPINGS; i++, p++) { - if (p->size) - do_free_mapping(p); - } - } -} - -static void *alloc_mapping_file(int cap, size_t mapsize, void *target) -{ - int i, fixed = 0, prot = PROT_READ | PROT_WRITE; - struct file_mapping *p; - int fd, rc; - - Q__printf("MAPPING: alloc, cap=%s, mapsize=%zx\n", cap, mapsize); - for (i = 0, p = file_mappings; i < MAX_FILE_MAPPINGS; i++, p++) - if (p->size == 0) - break; - assert(i < MAX_FILE_MAPPINGS); - fd = open_cb(); - if (fd < 0) - return MAP_FAILED; - rc = ftruncate(fd, mapsize); - assert(rc != -1); - - if (target != (void *)-1) - fixed = MAP_FIXED; - else - target = NULL; - target = mmap(target, mapsize, prot, MAP_SHARED | fixed, fd, 0); - if (target == MAP_FAILED) - return MAP_FAILED; -#if HAVE_DECL_MADV_POPULATE_WRITE - { - int err = madvise(target, mapsize, MADV_POPULATE_WRITE); - if (err) - perror("madvise()"); - } -#endif - p->addr = target; - p->size = mapsize; - p->fsize = mapsize; - p->fd = fd; - p->prot = prot; - return target; -} - -static void free_mapping_file(int cap, void *addr, size_t mapsize) -/* NOTE: addr needs to be the same as what was supplied by alloc_mapping_file */ -{ - struct file_mapping *p; - - Q__printf("MAPPING: free, cap=%s, addr=%p, mapsize=%zx\n", - cap, addr, mapsize); - p = find_file_mapping(addr); - do_free_mapping(p); -} - -/* - * NOTE: DPMI relies on realloc_mapping() _not_ changing the address ('addr'), - * when shrinking the memory region. - */ -/* We resize only from the beginning of the mapping. - * This is the simplest design. */ -static void *resize_mapping_file(int cap, void *addr, size_t oldsize, size_t newsize) -{ - Q__printf("MAPPING: realloc, cap=%s, addr=%p, oldsize=%zx, newsize=%zx\n", - cap, addr, oldsize, newsize); - if (cap & (MAPPING_EMS | MAPPING_DPMI)) { - struct file_mapping *p = find_file_mapping(addr); - int size = p->size; - - if (!size || size != oldsize || addr != p->addr) return (void *)-1; - if (size == newsize) return addr; - if (newsize < size) { - p->size = newsize; -#ifdef HAVE_MREMAP - p->addr = mremap(addr, oldsize, newsize, 0); - assert(p->addr == addr); -#else - /* ensure page-aligned */ - assert(!(oldsize & (PAGE_SIZE - 1))); - assert(!(newsize & (PAGE_SIZE - 1))); - munmap(addr + newsize, oldsize - newsize); -#endif - } else { - if (newsize > p->fsize) { - int rc = ftruncate(p->fd, newsize); - assert(rc != -1); - p->fsize = newsize; - } - p->size = newsize; -#if HAVE_DECL_MREMAP_MAYMOVE - p->addr = mremap(addr, oldsize, newsize, MREMAP_MAYMOVE); -#else - p->addr = mmap(NULL, newsize, p->prot, MAP_SHARED, p->fd, 0); - munmap(addr, oldsize); -#endif - } - return p->addr; - } - return (void *)-1; -} - -#ifdef HAVE_SHM_OPEN -struct mappingdrivers mappingdriver_shm = { - "mapshm", - "Posix SHM mapping", - open_mapping_pshm, - close_mapping_file, - alloc_mapping_file, - free_mapping_file, - resize_mapping_file, - alias_mapping_file -}; -#endif - -#ifdef HAVE_MEMFD_CREATE -struct mappingdrivers mappingdriver_mshm = { - "mapmshm", - "memfd mapping", - open_mapping_mshm, - close_mapping_file, - alloc_mapping_file, - free_mapping_file, - resize_mapping_file, - alias_mapping_file -}; -#endif - -struct mappingdrivers mappingdriver_file = { - "mapfile", - "temp file mapping", - open_mapping_file, - close_mapping_file, - alloc_mapping_file, - free_mapping_file, - resize_mapping_file, - alias_mapping_file -}; diff --git a/src/base/lib/mcontext/Makefile b/src/base/lib/mcontext/Makefile index 6abcd7b..2b1d85f 100644 --- a/src/base/lib/mcontext/Makefile +++ b/src/base/lib/mcontext/Makefile @@ -2,8 +2,8 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.conf CFILES = context.c -SSFILES = asm.SS +SFILES = asm.S -all: lib +all: lib include $(REALTOPDIR)/src/Makefile.common diff --git a/src/base/lib/mcontext/aarch64-ucontext.h b/src/base/lib/mcontext/aarch64-ucontext.h deleted file mode 100644 index 6c30910..0000000 --- a/src/base/lib/mcontext/aarch64-ucontext.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (C) 1998-2022 Free Software Foundation, Inc. - - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -/* System V/AArch64 ABI compliant context switching support. */ - -/* Context to describe whole processor state. This only describes - the core registers; coprocessor registers get saved elsewhere - (e.g. in uc_regspace, or somewhere unspecified on the stack - during non-RT signal handlers). */ -struct m_mcontext - { - unsigned long long int fault_address; - unsigned long long int regs[31]; - unsigned long long int sp; - unsigned long long int pc; - unsigned long long int pstate; - /* This field contains extension records for additional processor - state such as the FP/SIMD state. It has to match the definition - of the corresponding field in the sigcontext struct, see the - arch/arm64/include/uapi/asm/sigcontext.h linux header for details. */ - unsigned char __reserved[4096] __attribute__ ((__aligned__ (16))); - }; diff --git a/src/base/lib/mcontext/arm-ucontext.h b/src/base/lib/mcontext/arm-ucontext.h deleted file mode 100644 index c801cc9..0000000 --- a/src/base/lib/mcontext/arm-ucontext.h +++ /dev/null @@ -1,4 +0,0 @@ -struct m_mcontext { - int gregs[16]; -}; - diff --git a/src/base/lib/mcontext/asm.S b/src/base/lib/mcontext/asm.S new file mode 100644 index 0000000..e14e803 --- /dev/null +++ b/src/base/lib/mcontext/asm.S @@ -0,0 +1,110 @@ +/* This code is taken from libtask library. + * Rip-off done by stsp for dosemu2 project. + * Original copyrights below. */ + +/* Copyright (c) 2005-2006 Russ Cox, MIT; see COPYRIGHT */ + +#if defined(__i386__) +.globl _setmcontext +_setmcontext: + movl 4(%esp), %eax + + mov 8(%eax), %fs + mov 12(%eax), %es + mov 16(%eax), %ds + mov 76(%eax), %ss + movl 20(%eax), %edi + movl 24(%eax), %esi + movl 28(%eax), %ebp + movl 36(%eax), %ebx + movl 40(%eax), %edx + movl 44(%eax), %ecx + + movl 72(%eax), %esp + pushl 60(%eax) /* new %eip */ + movl 48(%eax), %eax + ret + +.globl _getmcontext +_getmcontext: + movl 4(%esp), %eax + + mov %fs, 8(%eax) + mov %es, 12(%eax) + mov %ds, 16(%eax) + mov %ss, 76(%eax) + movl %edi, 20(%eax) + movl %esi, 24(%eax) + movl %ebp, 28(%eax) + movl %ebx, 36(%eax) + movl %edx, 40(%eax) + movl %ecx, 44(%eax) + + movl $1, 48(%eax) /* %eax */ + movl (%esp), %ecx /* %eip */ + movl %ecx, 60(%eax) + leal 4(%esp), %ecx /* %esp */ + movl %ecx, 72(%eax) + + movl 44(%eax), %ecx /* restore %ecx */ + movl $0, %eax + ret + +#ifdef __ELF__ +.section .note.GNU-stack,"",%progbits +#endif +#endif + +#if defined(__x86_64__) +.globl _setmcontext +_setmcontext: + movq 16(%rdi), %rsi + movq 24(%rdi), %rdx + movq 32(%rdi), %rcx + movq 40(%rdi), %r8 + movq 48(%rdi), %r9 + movq 56(%rdi), %rax + movq 64(%rdi), %rbx + movq 72(%rdi), %rbp + movq 80(%rdi), %r10 + movq 88(%rdi), %r11 + movq 96(%rdi), %r12 + movq 104(%rdi), %r13 + movq 112(%rdi), %r14 + movq 120(%rdi), %r15 + movq 184(%rdi), %rsp + pushq 160(%rdi) /* new %eip */ + movq 8(%rdi), %rdi + ret + +.globl _getmcontext +_getmcontext: + movq %rdi, 8(%rdi) + movq %rsi, 16(%rdi) + movq %rdx, 24(%rdi) + movq %rcx, 32(%rdi) + movq %r8, 40(%rdi) + movq %r9, 48(%rdi) + movq $1, 56(%rdi) /* %rax */ + movq %rbx, 64(%rdi) + movq %rbp, 72(%rdi) + movq %r10, 80(%rdi) + movq %r11, 88(%rdi) + movq %r12, 96(%rdi) + movq %r13, 104(%rdi) + movq %r14, 112(%rdi) + movq %r15, 120(%rdi) + + movq (%rsp), %rcx /* %rip */ + movq %rcx, 160(%rdi) + leaq 8(%rsp), %rcx /* %rsp */ + movq %rcx, 184(%rdi) + + movq 32(%rdi), %rcx /* restore %rcx */ + movq $0, %rax + ret + +#ifdef __ELF__ +.section .note.GNU-stack,"",%progbits +#endif +#endif diff --git a/src/base/lib/mcontext/asm.SS b/src/base/lib/mcontext/asm.SS deleted file mode 100644 index fefe877..0000000 --- a/src/base/lib/mcontext/asm.SS +++ /dev/null @@ -1,464 +0,0 @@ -/* Copyright (c) 2005-2006 Russ Cox, MIT; see COPYRIGHT */ - -#if defined(__FreeBSD__) && defined(__i386__) && __FreeBSD__ < 5 -#define NEEDX86CONTEXT 1 -#define SET setmcontext -#define GET getmcontext -#else -#if defined(__FreeBSD__) && defined(__x86_64__) -#define NEEDAMD64CONTEXT 1 -#define SET _setmcontext -#define GET _getmcontext -#endif -#endif - -#if defined(__OpenBSD__) && defined(__i386__) -#define NEEDX86CONTEXT 1 -#define SET setmcontext -#define GET getmcontext -#endif - -#if defined(__APPLE__) -#if defined(__i386__) -#define NEEDX86CONTEXT 1 -#define SET _setmcontext -#define GET _getmcontext -#elif defined(__x86_64__) -#define NEEDAMD64CONTEXT 1 -#define SET __setmcontext -#define GET __getmcontext -#elif defined(__arm__) -#define NEEDARMCONTEXT 1 -#define SET _setmcontext -#define GET _getmcontext -#else -#define NEEDPOWERCONTEXT 1 -#define SET __setmcontext -#define GET __getmcontext -#endif -#endif - -#if defined(__linux__) -#if defined(__i386__) -#define NEEDX86CONTEXT 1 -#define SET _setmcontext -#define GET _getmcontext -#elif defined(__x86_64__) -#define NEEDAMD64CONTEXT 1 -#define SET _setmcontext -#define GET _getmcontext -#elif defined(__aarch64__) -#define NEEDAARCH64CONTEXT 1 -#define SET _setmcontext -#define GET _getmcontext -#elif defined(__arm__) -#define NEEDARMCONTEXT 1 -#define SET _setmcontext -#define GET _getmcontext -#elif defined(__mips__) -#define NEEDMIPSCONTEXT 1 -#define SET setmcontext -#define GET getmcontext -#else -#define NEEDPOWERCONTEXT 1 -#define SET __setmcontext -#define GET __getmcontext -#endif -#endif - -#ifdef NEEDX86CONTEXT -.globl SET -SET: - movl 4(%esp), %eax - - mov 8(%eax), %fs - mov 12(%eax), %es - mov 16(%eax), %ds - mov 76(%eax), %ss - movl 20(%eax), %edi - movl 24(%eax), %esi - movl 28(%eax), %ebp - movl 36(%eax), %ebx - movl 40(%eax), %edx - movl 44(%eax), %ecx - - movl 72(%eax), %esp - pushl 60(%eax) /* new %eip */ - movl 48(%eax), %eax - ret - -.globl GET -GET: - movl 4(%esp), %eax - - mov %fs, 8(%eax) - mov %es, 12(%eax) - mov %ds, 16(%eax) - mov %ss, 76(%eax) - movl %edi, 20(%eax) - movl %esi, 24(%eax) - movl %ebp, 28(%eax) - movl %ebx, 36(%eax) - movl %edx, 40(%eax) - movl %ecx, 44(%eax) - - movl $1, 48(%eax) /* %eax */ - movl (%esp), %ecx /* %eip */ - movl %ecx, 60(%eax) - leal 4(%esp), %ecx /* %esp */ - movl %ecx, 72(%eax) - - movl 44(%eax), %ecx /* restore %ecx */ - movl $0, %eax - ret -#endif - -#ifdef NEEDAMD64CONTEXT -.globl SET -SET: - movq 16(%rdi), %rsi - movq 24(%rdi), %rdx - movq 32(%rdi), %rcx - movq 40(%rdi), %r8 - movq 48(%rdi), %r9 - movq 56(%rdi), %rax - movq 64(%rdi), %rbx - movq 72(%rdi), %rbp - movq 80(%rdi), %r10 - movq 88(%rdi), %r11 - movq 96(%rdi), %r12 - movq 104(%rdi), %r13 - movq 112(%rdi), %r14 - movq 120(%rdi), %r15 - movq 184(%rdi), %rsp - pushq 160(%rdi) /* new %eip */ - movq 8(%rdi), %rdi - ret - -.globl GET -GET: - movq %rdi, 8(%rdi) - movq %rsi, 16(%rdi) - movq %rdx, 24(%rdi) - movq %rcx, 32(%rdi) - movq %r8, 40(%rdi) - movq %r9, 48(%rdi) - movq $1, 56(%rdi) /* %rax */ - movq %rbx, 64(%rdi) - movq %rbp, 72(%rdi) - movq %r10, 80(%rdi) - movq %r11, 88(%rdi) - movq %r12, 96(%rdi) - movq %r13, 104(%rdi) - movq %r14, 112(%rdi) - movq %r15, 120(%rdi) - - movq (%rsp), %rcx /* %rip */ - movq %rcx, 160(%rdi) - leaq 8(%rsp), %rcx /* %rsp */ - movq %rcx, 184(%rdi) - - movq 32(%rdi), %rcx /* restore %rcx */ - movq $0, %rax - ret -#endif - -#ifdef NEEDPOWERCONTEXT -/* get FPR and VR use flags with sc 0x7FF3 */ -/* get vsave with mfspr reg, 256 */ - -.text -.align 2 - -.globl GET -GET: /* xxx: instruction scheduling */ - mflr r0 - mfcr r5 - mfctr r6 - mfxer r7 - stw r0, 0*4(r3) - stw r5, 1*4(r3) - stw r6, 2*4(r3) - stw r7, 3*4(r3) - - stw r1, 4*4(r3) - stw r2, 5*4(r3) - li r5, 1 /* return value for setmcontext */ - stw r5, 6*4(r3) - - stw r13, (0+7)*4(r3) /* callee-save GPRs */ - stw r14, (1+7)*4(r3) /* xxx: block move */ - stw r15, (2+7)*4(r3) - stw r16, (3+7)*4(r3) - stw r17, (4+7)*4(r3) - stw r18, (5+7)*4(r3) - stw r19, (6+7)*4(r3) - stw r20, (7+7)*4(r3) - stw r21, (8+7)*4(r3) - stw r22, (9+7)*4(r3) - stw r23, (10+7)*4(r3) - stw r24, (11+7)*4(r3) - stw r25, (12+7)*4(r3) - stw r26, (13+7)*4(r3) - stw r27, (14+7)*4(r3) - stw r28, (15+7)*4(r3) - stw r29, (16+7)*4(r3) - stw r30, (17+7)*4(r3) - stw r31, (18+7)*4(r3) - - li r3, 0 /* return */ - blr - -.globl SET -SET: - lwz r13, (0+7)*4(r3) /* callee-save GPRs */ - lwz r14, (1+7)*4(r3) /* xxx: block move */ - lwz r15, (2+7)*4(r3) - lwz r16, (3+7)*4(r3) - lwz r17, (4+7)*4(r3) - lwz r18, (5+7)*4(r3) - lwz r19, (6+7)*4(r3) - lwz r20, (7+7)*4(r3) - lwz r21, (8+7)*4(r3) - lwz r22, (9+7)*4(r3) - lwz r23, (10+7)*4(r3) - lwz r24, (11+7)*4(r3) - lwz r25, (12+7)*4(r3) - lwz r26, (13+7)*4(r3) - lwz r27, (14+7)*4(r3) - lwz r28, (15+7)*4(r3) - lwz r29, (16+7)*4(r3) - lwz r30, (17+7)*4(r3) - lwz r31, (18+7)*4(r3) - - lwz r1, 4*4(r3) - lwz r2, 5*4(r3) - - lwz r0, 0*4(r3) - mtlr r0 - lwz r0, 1*4(r3) - mtcr r0 /* mtcrf 0xFF, r0 */ - lwz r0, 2*4(r3) - mtctr r0 - lwz r0, 3*4(r3) - mtxer r0 - - lwz r3, 6*4(r3) - blr -#endif - -#ifdef NEEDARMCONTEXT -.globl GET -GET: - str r1, [r0,#4] - str r2, [r0,#8] - str r3, [r0,#12] - str r4, [r0,#16] - str r5, [r0,#20] - str r6, [r0,#24] - str r7, [r0,#28] - str r8, [r0,#32] - str r9, [r0,#36] - str r10, [r0,#40] - str r11, [r0,#44] - str r12, [r0,#48] - str r13, [r0,#52] - str r14, [r0,#56] - /* store 1 as r0-to-restore */ - mov r1, #1 - str r1, [r0] - /* return 0 */ - mov r0, #0 - mov pc, lr - -.globl SET -SET: - ldr r1, [r0,#4] - ldr r2, [r0,#8] - ldr r3, [r0,#12] - ldr r4, [r0,#16] - ldr r5, [r0,#20] - ldr r6, [r0,#24] - ldr r7, [r0,#28] - ldr r8, [r0,#32] - ldr r9, [r0,#36] - ldr r10, [r0,#40] - ldr r11, [r0,#44] - ldr r12, [r0,#48] - ldr r13, [r0,#52] - ldr r14, [r0,#56] - ldr r0, [r0] - mov pc, lr -#endif - -#ifdef NEEDAARCH64CONTEXT - -/* Size of an X regiser in bytes. */ -#define SZREG 8 - -/* Size of a V register in bytes. */ -#define SZVREG 16 - -#define oX0 8 -#define oSP 8*32 -#define oPC 8*33 -#define oPSTATE 8*34 - -/* Save current context. - - Copyright (C) 2009-2022 Free Software Foundation, Inc. - - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ -.globl GET -GET: - /* The saved context will return to the getcontext() call point - with a return value of 1 -stsp (glibc uses 0) */ - mov x2, 1 - str x2, [x0, oX0 + 0 * SZREG] - - /* x0-x18 seems to be caller-save, glibc doesn't save them... - * though it does actually save x18, strange. -stsp */ - stp x18, x19, [x0, oX0 + 18 * SZREG] - stp x20, x21, [x0, oX0 + 20 * SZREG] - stp x22, x23, [x0, oX0 + 22 * SZREG] - stp x24, x25, [x0, oX0 + 24 * SZREG] - stp x26, x27, [x0, oX0 + 26 * SZREG] - stp x28, x29, [x0, oX0 + 28 * SZREG] - str x30, [x0, oX0 + 30 * SZREG] - - /* Place LR into the saved PC, this will ensure that when - switching to this saved context with setcontext() control - will pass back to the caller of getcontext(), we have - already arrange to return the appropriate return value in x0 - above. */ - str x30, [x0, oPC] - - /* Save the current SP */ - mov x2, sp - str x2, [x0, oSP] - - /* Initialize the pstate. */ - str xzr, [x0, oPSTATE] - - /* Return 0 for success */ - mov x0, 0 - ret - -/* Set current context. - - Copyright (C) 2009-2022 Free Software Foundation, Inc. - - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ -.globl SET -SET: - ldp x18, x19, [x0, oX0 + 18 * SZREG] - ldp x20, x21, [x0, oX0 + 20 * SZREG] - ldp x22, x23, [x0, oX0 + 22 * SZREG] - ldp x24, x25, [x0, oX0 + 24 * SZREG] - ldp x26, x27, [x0, oX0 + 26 * SZREG] - ldp x28, x29, [x0, oX0 + 28 * SZREG] - ldr x30, [x0, oX0 + 30 * SZREG] - ldr x2, [x0, oSP] - mov sp, x2 - - ldr x16, [x0, oPC] - /* Restore arg registers. */ - ldp x2, x3, [x0, oX0 + 2 * SZREG] - ldp x4, x5, [x0, oX0 + 4 * SZREG] - ldp x6, x7, [x0, oX0 + 6 * SZREG] - ldp x0, x1, [x0, oX0 + 0 * SZREG] - /* Jump to the new pc value. */ - br x16 -#endif - -#ifdef NEEDMIPSCONTEXT -.globl GET -GET: - sw $4, 24($4) - sw $5, 28($4) - sw $6, 32($4) - sw $7, 36($4) - - sw $16, 72($4) - sw $17, 76($4) - sw $18, 80($4) - sw $19, 84($4) - sw $20, 88($4) - sw $21, 92($4) - sw $22, 96($4) - sw $23, 100($4) - - sw $28, 120($4) /* gp */ - sw $29, 124($4) /* sp */ - sw $30, 128($4) /* fp */ - sw $31, 132($4) /* ra */ - - xor $2, $2, $2 - j $31 - nop - -.globl SET -SET: - lw $16, 72($4) - lw $17, 76($4) - lw $18, 80($4) - lw $19, 84($4) - lw $20, 88($4) - lw $21, 92($4) - lw $22, 96($4) - lw $23, 100($4) - - lw $28, 120($4) /* gp */ - lw $29, 124($4) /* sp */ - lw $30, 128($4) /* fp */ - - /* - * If we set $31 directly and j $31, - * we would loose the outer return address. - * Use a temporary register, then. - */ - lw $8, 132($4) /* ra */ - - /* bug: not setting the pc causes a bus error */ - lw $25, 132($4) /* pc */ - - lw $5, 28($4) - lw $6, 32($4) - lw $7, 36($4) - lw $4, 24($4) - - j $8 - nop -#endif - -#ifdef __ELF__ -.section .note.GNU-stack,"",%progbits -#endif diff --git a/src/base/lib/mcontext/context.c b/src/base/lib/mcontext/context.c index ebc718c..fe142a3 100644 --- a/src/base/lib/mcontext/context.c +++ b/src/base/lib/mcontext/context.c @@ -16,18 +16,6 @@ void makemcontext(m_ucontext_t *ucp, void (*func)(void*), void *arg) sp = (uintptr_t *)((unsigned char *)ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); sp = (void*)((uintptr_t)sp - (uintptr_t)sp%16); /* 16-align for OS X */ - -#ifdef __aarch64__ - ucp->uc_mcontext.regs[19] = (uintptr_t) ucp->uc_link; - ucp->uc_mcontext.sp = (uintptr_t) sp; - ucp->uc_mcontext.pc = (uintptr_t) func; - ucp->uc_mcontext.regs[0] = (uint64_t)arg; -#else -#ifdef __arm__ - ucp->uc_mcontext.gregs[13] = (uintptr_t)sp; - ucp->uc_mcontext.gregs[14] = (uintptr_t)func; - ucp->uc_mcontext.gregs[0] = (uintptr_t)arg; -#else #ifdef __i386__ sp -= 3; // alignment *--sp = (uintptr_t)arg; @@ -42,8 +30,6 @@ void makemcontext(m_ucontext_t *ucp, void (*func)(void*), void *arg) ucp->uc_mcontext.mc_rip = (uintptr_t)func; ucp->uc_mcontext.mc_rsp = (uintptr_t)sp; #endif -#endif -#endif } int swapmcontext(m_ucontext_t *oucp, const m_ucontext_t *ucp) diff --git a/src/base/lib/mcontext/mcontext.h b/src/base/lib/mcontext/mcontext.h index 718b99f..aa50b9c 100644 --- a/src/base/lib/mcontext/mcontext.h +++ b/src/base/lib/mcontext/mcontext.h @@ -20,12 +20,6 @@ typedef struct m_ucontext m_ucontext_t; # include "386-ucontext.h" # elif defined(__x86_64__) # include "amd64-ucontext.h" -# elif defined(__arm__) -# include "arm-ucontext.h" -# elif defined(__aarch64__) -# include "aarch64-ucontext.h" -# elif defined (__power__) -# include "power-ucontext.h" # else # error Unsupported arch # endif @@ -58,8 +52,7 @@ static inline int setmcontext(const struct m_ucontext *u) static inline __attribute__((always_inline)) int getmcontext(struct m_ucontext *u) { - /* called so frequently that memset() is expensive */ -// memset(&u->uc_mcontext, 0, sizeof u->uc_mcontext); + memset(&u->uc_mcontext, 0, sizeof u->uc_mcontext); return _getmcontext(&u->uc_mcontext); } extern int swapmcontext(m_ucontext_t*, const m_ucontext_t*); diff --git a/src/base/lib/mcontext/mips-ucontext.h b/src/base/lib/mcontext/mips-ucontext.h deleted file mode 100644 index 4d4429e..0000000 --- a/src/base/lib/mcontext/mips-ucontext.h +++ /dev/null @@ -1,77 +0,0 @@ -typedef struct mcontext mcontext_t; -typedef struct ucontext ucontext_t; - -extern int swapcontext(ucontext_t*, const ucontext_t*); -extern void makecontext(ucontext_t*, void(*)(), int, ...); - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell. - * - * 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. - * 4. 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. - * - * @(#)ucontext.h 8.1 (Berkeley) 6/10/93 - * JNPR: ucontext.h,v 1.2 2007/08/09 11:23:32 katta - * $FreeBSD: src/sys/mips/include/ucontext.h,v 1.2 2010/01/10 19:50:24 imp Exp $ - */ - -struct mcontext { - /* - * These fields must match the corresponding fields in struct - * sigcontext which follow 'sc_mask'. That way we can support - * struct sigcontext and ucontext_t at the same time. - */ - int mc_onstack; /* sigstack state to restore */ - int mc_pc; /* pc at time of signal */ - int mc_regs[32]; /* processor regs 0 to 31 */ - int sr; /* status register */ - int mullo, mulhi; /* mullo and mulhi registers... */ - int mc_fpused; /* fp has been used */ - int mc_fpregs[33]; /* fp regs 0 to 31 and csr */ - int mc_fpc_eir; /* fp exception instruction reg */ - void *mc_tls; /* pointer to TLS area */ - int __spare__[8]; /* XXX reserved */ -}; - -struct ucontext { - /* - * Keep the order of the first two fields. Also, - * keep them the first two fields in the structure. - * This way we can have a union with struct - * sigcontext and ucontext_t. This allows us to - * support them both at the same time. - * note: the union is not defined, though. - */ - sigset_t uc_sigmask; - mcontext_t uc_mcontext; - - struct __ucontext *uc_link; - stack_t uc_stack; - int uc_flags; - int __spare__[4]; -}; diff --git a/src/base/lib/mcontext/power-ucontext.h b/src/base/lib/mcontext/power-ucontext.h deleted file mode 100644 index 691f0f5..0000000 --- a/src/base/lib/mcontext/power-ucontext.h +++ /dev/null @@ -1,37 +0,0 @@ -#define setcontext(u) _setmcontext(&(u)->mc) -#define getcontext(u) _getmcontext(&(u)->mc) -typedef struct mcontext mcontext_t; -typedef struct ucontext ucontext_t; -struct mcontext -{ - ulong pc; /* lr */ - ulong cr; /* mfcr */ - ulong ctr; /* mfcr */ - ulong xer; /* mfcr */ - ulong sp; /* callee saved: r1 */ - ulong toc; /* callee saved: r2 */ - ulong r3; /* first arg to function, return register: r3 */ - ulong gpr[19]; /* callee saved: r13-r31 */ -/* -// XXX: currently do not save vector registers or floating-point state -// ulong pad; -// uvlong fpr[18]; / * callee saved: f14-f31 * / -// ulong vr[4*12]; / * callee saved: v20-v31, 256-bits each * / -*/ -}; - -struct ucontext -{ - struct { - void *ss_sp; - uint ss_size; - } uc_stack; - sigset_t uc_sigmask; - mcontext_t mc; -}; - -void makecontext(ucontext_t*, void(*)(void), int, ...); -int swapcontext(ucontext_t*, const ucontext_t*); -int _getmcontext(mcontext_t*); -void _setmcontext(const mcontext_t*); - diff --git a/src/base/lib/misc/Makefile b/src/base/lib/misc/Makefile index e1a40a0..856ca6d 100644 --- a/src/base/lib/misc/Makefile +++ b/src/base/lib/misc/Makefile @@ -2,8 +2,7 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.conf -CFILES = smalloc.c pgalloc.c dlmalloc.c ringbuf.c spscq.c cpi.c dis8086.c \ - shlock.c sequencr.c +CFILES = smalloc.c dlmalloc.c ringbuf.c cpi.c include $(REALTOPDIR)/src/Makefile.common diff --git a/src/base/lib/misc/dlmalloc.c b/src/base/lib/misc/dlmalloc.c index 133a3f9..62aeecd 100644 --- a/src/base/lib/misc/dlmalloc.c +++ b/src/base/lib/misc/dlmalloc.c @@ -312,7 +312,7 @@ extern void* sbrk(ptrdiff_t); #define SIZE_T_BITSIZE (sizeof(size_t) << 3) /* Some constants coerced to size_t */ -/* Annoying but necessary to avoid errors on some platforms */ +/* Annoying but necessary to avoid errors on some plaftorms */ #define SIZE_T_ZERO ((size_t)0) #define SIZE_T_ONE ((size_t)1) #define SIZE_T_TWO ((size_t)2) @@ -394,7 +394,7 @@ static void* win32direct_mmap(size_t size) { return (ptr != 0)? ptr: MFAIL; } -/* This function supports releasing coalesced segments */ +/* This function supports releasing coalesed segments */ static int win32munmap(void* ptr, size_t size) { MEMORY_BASIC_INFORMATION minfo; char* cptr = ptr; @@ -430,7 +430,7 @@ static int win32munmap(void* ptr, size_t size) { #define CALL_MORECORE(S) MFAIL #endif /* HAVE_MORECORE */ -/* mstate bit set if contiguous morecore disabled or failed */ +/* mstate bit set if continguous morecore disabled or failed */ #define USE_NONCONTIGUOUS_BIT (4U) /* segment bit set in create_mspace_with_base */ @@ -1223,7 +1223,7 @@ static void reset_on_error(mstate m); /* -------------------------- Debugging setup ---------------------------- */ -#ifndef DEBUG +#if ! DEBUG #define check_free_chunk(M,P) #define check_inuse_chunk(M,P) @@ -1579,7 +1579,7 @@ static int change_mparam(int param_number, int value) { } } -#ifdef DEBUG +#if DEBUG /* ------------------------- Debugging Support --------------------------- */ /* Check properties of any chunk, whether free, inuse, mmapped etc */ @@ -1850,8 +1850,8 @@ static void do_check_malloc_state(mstate m) { /* ----------------------------- statistics ------------------------------ */ #if !NO_MALLINFO -static struct _mallinfo internal_mallinfo(mstate m) { - struct _mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static struct mallinfo internal_mallinfo(mstate m) { + struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; if (!PREACTION(m)) { check_malloc_state(m); if (is_initialized(m)) { @@ -2347,7 +2347,7 @@ static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { msegmentptr ss = (msegmentptr)(chunk2mem(sp)); mchunkptr tnext = chunk_plus_offset(sp, ssize); mchunkptr p = tnext; -// int nfences = 0; + int nfences = 0; /* reset top to new space */ init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); @@ -2365,13 +2365,13 @@ static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { for (;;) { mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); p->head = FENCEPOST_HEAD; -// ++nfences; + ++nfences; if ((char*)(&(nextp->head)) < old_end) p = nextp; else break; } -// assert(nfences >= 2); + assert(nfences >= 2); /* Insert the rest of old top into a bin as an ordinary free chunk */ if (csp != old_top) { @@ -3065,7 +3065,7 @@ static void** ialloc(mstate m, } } -#ifdef DEBUG +#if DEBUG if (marray != chunks) { /* final element must have exactly exhausted chunk */ if (element_size != 0) { @@ -3224,7 +3224,7 @@ void* dlmalloc(size_t bytes) { void dlfree(void* mem) { /* - Consolidate freed chunks with preceding or succeeding bordering + Consolidate freed chunks with preceeding or succeeding bordering free chunks, if they exist, and then place in a bin. Intermixed with special cases for top, dv, mmapped chunks, and usage errors. */ @@ -3407,12 +3407,12 @@ size_t dlmalloc_max_footprint(void) { } #if !NO_MALLINFO -struct _mallinfo dlmallinfo(void) { +struct mallinfo dlmallinfo(void) { return internal_mallinfo(gm); } #endif /* NO_MALLINFO */ -void dlmalloc_stats(void) { +void dlmalloc_stats() { internal_malloc_stats(gm); } @@ -3842,7 +3842,7 @@ size_t mspace_max_footprint(mspace msp) { #if !NO_MALLINFO -struct _mallinfo mspace_mallinfo(mspace msp) { +struct mallinfo mspace_mallinfo(mspace msp) { mstate ms = (mstate)msp; if (!ok_magic(ms)) { USAGE_ERROR_ACTION(ms,ms); @@ -4061,10 +4061,10 @@ History: Wolfram Gloger (Gloger@lrz.uni-muenchen.de). * Use last_remainder in more cases. * Pack bins using idea from colin@nyx10.cs.du.edu - * Use ordered bins instead of best-fit threshold + * Use ordered bins instead of best-fit threshhold * Eliminate block-local decls to simplify tracing and debugging. * Support another case of realloc via move into top - * Fix error occurring when initial sbrk_base not word-aligned. + * Fix error occuring when initial sbrk_base not word-aligned. * Rely on page size for units instead of SBRK_UNIT to avoid surprises about sbrk alignment conventions. * Add mallinfo, mallopt. Thanks to Raymond Nijssen diff --git a/src/base/lib/misc/pgalloc.c b/src/base/lib/misc/pgalloc.c deleted file mode 100644 index 9124e4b..0000000 --- a/src/base/lib/misc/pgalloc.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: ultra-light page allocator - * - * Author: stsp - * - */ -#include -#include -#include "pgalloc.h" - -void *pgainit(unsigned npages) -{ - int *ret = calloc(npages + 1, sizeof(int)); - ret[0] = npages + 1; // put array len in first element - return ret; -} - -void pgadone(void *pool) -{ - free(pool); -} - -void pgareset(void *pool) -{ - int *p = pool; - int i; - - for (i = 1; i < p[0]; i++) - p[i] = 0; -} - -static int find_free(int *p, unsigned npages) -{ - int i; - - if (npages > p[0]) - return -1; - for (i = 1; i <= p[0] - npages; i++) { - if (p[i] == 0) { - int j; - if (npages == 1) - return i; - for (j = i + 1; j < p[0] && p[j] == 0; j++) { - if (j - i + 1 == npages) - return i; - } - i = j; - } - } - return -1; -} - -#define ID(x) (-(x) - 1) - -int pgaalloc(void *pool, unsigned npages, unsigned id) -{ - int *p = pool; - int idx = find_free(p, npages); - if (idx > 0) { - int i; - p[idx] = ID(id); - for (i = idx + 1; i < idx + npages; i++) - p[i] = i - idx; - } - return idx - 1; -} - -int pgaresize(void *pool, unsigned page, unsigned oldpages, unsigned newpages) -{ - int i; - int *p = pool; - page++; // skip len - assert(page + oldpages < p[0]); - assert(page + newpages < p[0]); - assert(p[page] < 0); - - if (newpages <= oldpages) { /* shrink */ - for (i = newpages; i < oldpages; i++) - p[page+i] = 0; - return page; - } - - /* check if we can expand */ - for (i = oldpages; i < newpages; i++) - if (p[page+i]) - return -1; - - /* allocate the expansion */ - for (i = oldpages; i < newpages; i++) - p[page+i] = i; - return page; -} - -void pgafree(void *pool, unsigned page) -{ - int *p = pool; - page++; // skip len - assert(page < p[0]); - assert(p[page] < 0); - do - p[page++] = 0; - while (page < p[0] && p[page] > 0); -} - -int pgaavail_largest(void *pool) -{ - int *p = pool; - int i, max = 0; - - for (i = 1; i < p[0]; i++) { - if (p[i] == 0) { - int j; - for (j = i + 1; j < p[0] && p[j] == 0; j++); - if (j - i > max) - max = j - i; - i = j; - } - } - return max; -} - -struct pgrm pgarmap(void *pool, unsigned page) -{ - struct pgrm ret = { -1, -1 }; - int *p = pool; - page++; // skip len - assert(page < p[0]); - if (p[page] == 0) - return ret; - ret.pgoff = 0; - if (p[page] > 0) { - ret.pgoff = p[page]; - page -= p[page]; - assert(page > 0 && p[page] < 0); - } - ret.id = ID(p[page]); - return ret; -} diff --git a/src/base/lib/misc/sequencr.c b/src/base/lib/misc/sequencr.c deleted file mode 100644 index 98154e9..0000000 --- a/src/base/lib/misc/sequencr.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * simple sequencer library. - * - * Author: @stsp - * - */ -#include -#include -#include -#include "dosemu_debug.h" -#include "sequencr.h" - -struct seq_tag_s { - int tag; - int data; -}; - -#define MAX_TAGS 5 -struct seq_item_s { - struct seq_item_s *next; - unsigned long long tstamp; - struct seq_tag_s tags[MAX_TAGS]; - int ntags; -}; - -struct seq_s { - struct seq_item_s *head; - struct seq_item_s *tail; - pthread_mutex_t seq_mtx; -}; - -void *sequencer_init(void) -{ - struct seq_s *s = malloc(sizeof(*s)); - assert(s); - s->head = s->tail = NULL; - pthread_mutex_init(&s->seq_mtx, NULL); - return s; -} - -static struct seq_item_s *do_get(struct seq_s *s) -{ - struct seq_item_s *ret = s->head; - if (!ret) - return NULL; - s->head = ret->next; - if (!s->head) - s->tail = NULL; - return ret; -} - -static void do_free(struct seq_item_s *i) -{ - free(i); -} - -static void do_clear(struct seq_s *s) -{ - while (s->head) { - struct seq_item_s *i = do_get(s); - do_free(i); - } -} - -void sequencer_done(void *handle) -{ - struct seq_s *s = handle; - do_clear(s); - pthread_mutex_destroy(&s->seq_mtx); - free(s); -} - -void sequencer_clear(void *handle) -{ - struct seq_s *s = handle; - pthread_mutex_lock(&s->seq_mtx); - do_clear(s); - pthread_mutex_unlock(&s->seq_mtx); -} - -struct seq_item_s *sequencer_add(void *handle, unsigned long long tstamp) -{ - struct seq_s *s = handle; - struct seq_item_s *i; - - i = malloc(sizeof(*i)); - assert(i); - i->next = NULL; - i->tstamp = tstamp; - i->ntags = 0; - - pthread_mutex_lock(&s->seq_mtx); - if (s->tail) { - if (tstamp < s->tail->tstamp) { - error("time goes backwards? %lli < %lli\n", tstamp, s->tail->tstamp); - i->tstamp = s->tail->tstamp; - } - s->tail->next = i; - } else { - assert(!s->head); - s->head = i; - } - s->tail = i; - pthread_mutex_unlock(&s->seq_mtx); - return i; -} - -void sequencer_add_tag(struct seq_item_s *i, int tag, int data) -{ - assert(i->ntags < MAX_TAGS); - i->tags[i->ntags].tag = tag; - i->tags[i->ntags].data = data; - i->ntags++; -} - -void *sequencer_get(void *handle) -{ - struct seq_s *s = handle; - struct seq_item_s *i; - - pthread_mutex_lock(&s->seq_mtx); - i = do_get(s); - pthread_mutex_unlock(&s->seq_mtx); - return i; -} - -unsigned long long sequencer_get_next(void *handle) -{ - struct seq_s *s = handle; - unsigned long long ret = 0; - - pthread_mutex_lock(&s->seq_mtx); - if (s->head) - ret = s->head->tstamp; - pthread_mutex_unlock(&s->seq_mtx); - return ret; -} - -void sequencer_free(struct seq_item_s *item) -{ - do_free(item); -} - -int sequencer_find(struct seq_item_s *item, int tag) -{ - int i; - for (i = 0; i < item->ntags; i++) { - if (item->tags[i].tag == tag) - return item->tags[i].data; - } - return -1; -} diff --git a/src/base/lib/misc/shlock.c b/src/base/lib/misc/shlock.c deleted file mode 100644 index 3b0c727..0000000 --- a/src/base/lib/misc/shlock.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * shlock - shared UUCP-style lockfile library. - * Provides inter-process read/write locks and refcounting. - * Refcounting is provided by the means of an unlock operation - * returning an indication of "no more locks on that resource". - * - * This implementation provides the lock-free operations, i.e. it - * doesn't use any locking internally. Which makes it a bit complex, - * as we lack the atomic open-and-lock operation, unlink-from-fd - * (funlink()/frmdir()) functions and a few other things to liverage - * the simple lock-free implementation. - * Also it strives to provide the race-free operations with the - * predictable behavior in all cases, but the callers are advised - * to use the synchronization to avoid locking and unlocking the - * same resources simultaneously from different processes. - * - * Author: @stsp - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "shlock.h" - -#define LOCK_DIR "/tmp" -#define LOCK_PFX "LCK.." - -struct shlck { - char *tspec; - char *fspec; - char *dir; - int excl; - int fd; - int tmp_fd; -}; - -static void do_gc(const char *fspec) -{ - char *pat; - glob_t gl; - int rc; - - asprintf(&pat, "%s/" LOCK_PFX "*", fspec); - rc = glob(pat, GLOB_ERR | GLOB_NOSORT | GLOB_NOESCAPE, NULL, &gl); - if (rc == 0) { - int i; - for (i = 0; i < gl.gl_pathc; i++) { - int fd = open(gl.gl_pathv[i], O_RDONLY); - if (fd == -1) - continue; - /* tmpfiles are not participating in locking, so we can use - * LOCK_NB safely */ - rc = flock(fd, LOCK_SH | LOCK_NB); - if (rc == 0) - unlink(gl.gl_pathv[i]); - close(fd); - } - globfree(&gl); - } - free(pat); -} - -static char *fixupspec(char *fspec, const char *dir1, const char *dir2) -{ - char *ret; - int len = strlen(dir1); - assert(fspec[len] == '/'); - asprintf(&ret, "%s%s", dir2, fspec + len); - return ret; -} - -void *shlock_open(const char *dir, const char *name, int excl, int block) -{ - struct shlck *ret; - char *fspec, *dspec, *tspec, *ttspec, *dtspec; - int fd, tmp_fd, rc; - int flg = block ? 0 : LOCK_NB; - - rc = asprintf(&dspec, LOCK_DIR "/%s", dir); - assert(rc != -1); - rc = asprintf(&fspec, "%s/%s", dspec, name); - assert(rc != -1); - rc = asprintf(&dtspec, LOCK_DIR "/%s.XXXXXX", name); - assert(rc != -1); - /* create tmp dir */ - mkdtemp(dtspec); - rc = asprintf(&ttspec, "%s/" LOCK_PFX "%i_XXXXXX", dtspec, getpid()); - assert(rc != -1); - - /* create tmp file in tmp dir */ - tmp_fd = mkstemp(ttspec); - if (tmp_fd == -1) { - perror("mkstemp()"); - rmdir(dtspec); - goto err_free_d; - } - tspec = fixupspec(ttspec, dtspec, fspec); - /* lock it before exposing */ - rc = flock(tmp_fd, LOCK_EX); - if (rc == -1) { - perror("flock(tmp)"); - rmdir(dtspec); - goto err_clotmp; - } - - rc = -1; - while (rc == -1) { - rc = mkdir(dspec, 0775); - if (rc == -1 && errno != EEXIST) { - perror("mkdir()"); - unlink(ttspec); - rmdir(dtspec); - goto err_clotmp; - } - /* Try to rename tmp dir. The idea is that fspec dir is never - * created empty, because we rename to it from non-empty one. */ - rc = rename(dtspec, fspec); - if (rc == -1) { - if (errno == ENOENT) - continue; // race, someone removed parent dir - /* couldn't rename the whole dir (fspec exists and not empty), - * so try to move tmp file alone */ - rc = rename(ttspec, tspec); - if (rc == -1) { - if (errno == ENOENT) - continue; // race, someone removed parent dir - perror("rename()"); - unlink(ttspec); - rmdir(dtspec); - goto err_rmddir; - } - rc = rmdir(dtspec); - if (rc == -1) { - perror("rmdir()"); - goto err_rmt; - } - } - } - - free(ttspec); - ttspec = NULL; // exclude from error cleanup - free(dtspec); - dtspec = NULL; // exclude from error cleanup - /* At this point our fspec directory is stable and can't disappear. - * Try collecting stalled tmpfiles. */ - do_gc(fspec); - - fd = open(fspec, O_RDONLY | O_DIRECTORY); - if (fd == -1) { - perror("open(dir)"); - goto err_rmt; - } - if (excl) { - rc = flock(fd, LOCK_EX | flg); - if (rc == -1) - goto err_close; - } else { - rc = flock(fd, LOCK_SH | flg); - if (rc == -1) { - perror("flock()"); - goto err_close; - } - } - - ret = malloc(sizeof(*ret)); - ret->tspec = tspec; - ret->fspec = fspec; - ret->dir = dspec; - ret->excl = excl; - ret->fd = fd; - ret->tmp_fd = tmp_fd; - return ret; - -err_close: - close(fd); -err_rmt: - unlink(tspec); - rmdir(fspec); -err_rmddir: - rmdir(dspec); -err_clotmp: - close(tmp_fd); - free(tspec); -err_free_d: - free(ttspec); - free(dtspec); - free(fspec); - free(dspec); - return NULL; -} - -int shlock_close(void *handle) -{ - struct shlck *s = handle; - int rc, ret = 0; - - rc = unlink(s->tspec); - if (rc == -1) - perror("unlink()"); - rc = close(s->tmp_fd); - if (rc == -1) - perror("close(tmp)"); - /* At that point someone can remove and re-create our dir. - * The creation loop is designed the way the created dir is never - * empty, so it can't be removed here in that case. - * Note that whoever removes our dir, returns the removal indication - * to the caller. So if the dir doesn't exist currently (no matter - * was it just removed, or removed then re-created then removed again, - * and so on), then we do not return the removal indication, which - * is fine, as that means 1 indication per 1 removal. */ - rc = rmdir(s->fspec); // fails if still not empty - if (rc == 0) - ret++; - /* close() drops OFD lock */ - rc = close(s->fd); - if (rc == -1) - perror("close()"); - rc = rmdir(s->dir); // fails if still not empty - if (rc == 0) - ret++; - - free(s->tspec); - free(s->fspec); - free(s->dir); - free(s); - return ret; -} diff --git a/src/base/lib/misc/smalloc.c b/src/base/lib/misc/smalloc.c index 895902e..096f30a 100644 --- a/src/base/lib/misc/smalloc.c +++ b/src/base/lib/misc/smalloc.c @@ -29,16 +29,9 @@ #include "smalloc.h" #define POOL_USED(p) (p->mn.used || p->mn.next) -#ifndef _min +#ifndef min #define _min(x, y) ((x) < (y) ? (x) : (y)) #endif -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif -#define _PAGE_MASK (~(PAGE_SIZE-1)) -#ifndef PAGE_ALIGN -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&_PAGE_MASK) -#endif static void smerror_dummy(int prio, const char *fmt, ...) FORMAT(printf, 2, 3); @@ -51,14 +44,13 @@ static void smerror_dummy(int prio, const char *fmt, ...) #define smerror(mp, ...) mp->smerr(3, __VA_ARGS__) -static int do_dump(struct mempool *mp, char *buf, int len) +static void do_dump(struct mempool *mp, char *buf, int len) { int pos = 0; struct memnode *mn; #define DO_PRN(...) do { \ - if (pos >= len) \ - return -1; \ + assert(pos < len); \ pos += snprintf(buf + pos, len - pos, __VA_ARGS__); \ } while (0) DO_PRN("Total size: %zi\n", mp->size); @@ -69,38 +61,29 @@ static int do_dump(struct mempool *mp, char *buf, int len) for (mn = &mp->mn; mn; mn = mn->next) DO_PRN("\tarea: %zi bytes, %s\n", mn->size, mn->used ? "used" : "free"); - return 0; } void smdump(struct mempool *mp) { - char buf[16384]; - int err = do_dump(mp, buf, sizeof(buf)); - if (!err) - mp->smerr(0, "%s", buf); - else - mp->smerr(3, "dump buffer overflow\n"); + char buf[1024]; + + do_dump(mp, buf, sizeof(buf)); + mp->smerr(0, "%s", buf); } static FORMAT(printf, 3, 4) void do_smerror(int prio, struct mempool *mp, const char *fmt, ...) { - char buf[16384]; - int err; - size_t pos; + char buf[1024]; + int pos; va_list al; assert(prio != -1); va_start(al, fmt); pos = vsnprintf(buf, sizeof(buf), fmt, al); va_end(al); - err = -1; - if (pos < sizeof(buf)) - err = do_dump(mp, buf + pos, sizeof(buf) - pos); - if (!err) - mp->smerr(0, "%s", buf); - else - mp->smerr(3, "dump buffer overflow\n"); + do_dump(mp, buf + pos, sizeof(buf) - pos); + mp->smerr(prio, "%s", buf); } static int get_oom_pr(struct mempool *mp, size_t size) @@ -116,16 +99,11 @@ static int get_oom_pr(struct mempool *mp, size_t size) static void sm_uncommit(struct mempool *mp, void *addr, size_t size) { - /* align address up and align down size */ - uintptr_t a = (uintptr_t)addr; - uintptr_t aa = PAGE_ALIGN(a); - size_t aligned_size = (size - (aa - a)) & _PAGE_MASK; - void *aligned_addr = (void *)aa; mp->avail += size; assert(mp->avail <= mp->size); if (!mp->uncommit) return; - mp->uncommit(aligned_addr, aligned_size); + mp->uncommit(addr, size); } static int __sm_commit(struct mempool *mp, void *addr, size_t size, @@ -145,12 +123,7 @@ static int __sm_commit(struct mempool *mp, void *addr, size_t size, static int sm_commit(struct mempool *mp, void *addr, size_t size, void *e_addr, size_t e_size) { - /* align address down and align up size */ - uintptr_t a = (uintptr_t)addr; - uintptr_t aa = a & _PAGE_MASK; - size_t aligned_size = PAGE_ALIGN(size + (a - aa)); - void *aligned_addr = (void *)aa; - int ok = __sm_commit(mp, aligned_addr, aligned_size, e_addr, e_size); + int ok = __sm_commit(mp, addr, size, e_addr, e_size); if (ok) { assert(mp->avail >= size); mp->avail -= size; @@ -241,18 +214,25 @@ static struct memnode *smfind_free_area(struct mempool *mp, size_t size) return NULL; } -static struct memnode *smfind_free_area_topdown(struct mempool *mp, - unsigned char *top, size_t size) +static struct memnode *sm_alloc_mn(struct mempool *mp, size_t size) { struct memnode *mn; - struct memnode *mn1 = NULL; - for (mn = &mp->mn; mn; mn = mn->next) { - if (top && mn->mem_area + size > top) - break; - if (!mn->used && mn->size >= size) - mn1 = mn; + if (!size) { + smerror(mp, "SMALLOC: zero-sized allocation attempted\n"); + return NULL; } - return mn1; + if (!(mn = smfind_free_area(mp, size))) { + do_smerror(get_oom_pr(mp, size), mp, + "SMALLOC: Out Of Memory on alloc, requested=%zu\n", size); + return NULL; + } + if (!sm_commit_simple(mp, mn->mem_area, size)) + return NULL; + mn->used = 1; + mntruncate(mn, size); + assert(mn->size == size); + memset(mn->mem_area, 0, size); + return mn; } static struct memnode *sm_alloc_fixed(struct mempool *mp, void *ptr, @@ -275,10 +255,7 @@ static struct memnode *sm_alloc_fixed(struct mempool *mp, void *ptr, delta = (uint8_t *)ptr - mn->mem_area; assert(delta >= 0); if (size + delta > mn->size) { - int pr = get_oom_pr(mp, size); - if (pr < 0) - pr = 0; - do_smerror(pr, mp, "SMALLOC: no space %zi at address %p\n", size, ptr); + smerror(mp, "SMALLOC: no space %zi at address %p\n", size, ptr); return NULL; } if (delta) { @@ -301,19 +278,16 @@ static struct memnode *sm_alloc_aligned(struct mempool *mp, size_t align, struct memnode *mn; int delta; uintptr_t iptr; - if (!size) { + if (!size || align < 2) { smerror(mp, "SMALLOC: zero-sized allocation attempted\n"); return NULL; } - /* power of 2 align */ - assert(__builtin_popcount(align) == 1); align--; if (!(mn = smfind_free_area(mp, size + align))) { do_smerror(get_oom_pr(mp, size), mp, "SMALLOC: Out Of Memory on alloc, requested=%zu\n", size); return NULL; } - /* insert small node to align the start */ iptr = (uintptr_t)mn->mem_area; delta = ((iptr | align) - iptr + 1) & align; if (delta) { @@ -330,61 +304,6 @@ static struct memnode *sm_alloc_aligned(struct mempool *mp, size_t align, return mn; } -static struct memnode *sm_alloc_mn(struct mempool *mp, size_t size) -{ - return sm_alloc_aligned(mp, 1, size); -} - -static struct memnode *sm_alloc_aligned_topdown(struct mempool *mp, - unsigned char *top, size_t align, size_t size) -{ - struct memnode *mn; - int delta; - uintptr_t iptr; - uintptr_t min_top; - uintptr_t iend; - if (!size) { - smerror(mp, "SMALLOC: zero-sized allocation attempted\n"); - return NULL; - } - /* power of 2 align */ - assert(__builtin_popcount(align) == 1); - align--; - if (!(mn = smfind_free_area_topdown(mp, top, size + align))) { - do_smerror(get_oom_pr(mp, size), mp, - "SMALLOC: Out Of Memory on alloc, requested=%zu\n", size); - return NULL; - } - /* use top part of the found area */ - min_top = (uintptr_t)mn->mem_area + mn->size; - if (top) - min_top = _min(min_top, (uintptr_t)top); - iptr = (min_top - size) & ~align; - iend = iptr + size; - delta = (uintptr_t)mn->mem_area + mn->size - iend; - if (delta) - mntruncate(mn, mn->size - delta); - assert(iptr >= (uintptr_t)mn->mem_area); - delta = iptr - (uintptr_t)mn->mem_area; - if (delta) { - mntruncate(mn, delta); - mn = mn->next; - assert(!mn->used && mn->size >= size); - } - if (!sm_commit_simple(mp, mn->mem_area, size)) - return NULL; - mn->used = 1; - mntruncate(mn, size); - assert(mn->size == size); - memset(mn->mem_area, 0, size); - return mn; -} - -static struct memnode *sm_alloc_topdown(struct mempool *mp, size_t size) -{ - return sm_alloc_aligned_topdown(mp, NULL, 1, size); -} - void *smalloc(struct mempool *mp, size_t size) { struct memnode *mn = sm_alloc_mn(mp, size); @@ -411,24 +330,6 @@ void *smalloc_aligned(struct mempool *mp, size_t align, size_t size) return mn->mem_area; } -void *smalloc_topdown(struct mempool *mp, size_t size) -{ - struct memnode *mn = sm_alloc_topdown(mp, size); - if (!mn) - return NULL; - return mn->mem_area; -} - -void *smalloc_aligned_topdown(struct mempool *mp, unsigned char *top, - size_t align, size_t size) -{ - struct memnode *mn = sm_alloc_aligned_topdown(mp, top, align, size); - if (!mn) - return NULL; - assert(((uintptr_t)mn->mem_area & (align - 1)) == 0); - return mn->mem_area; -} - int smfree(struct mempool *mp, void *ptr) { struct memnode *mn, *pmn; @@ -546,56 +447,6 @@ void *smrealloc(struct mempool *mp, void *ptr, size_t size) return mn->mem_area; } -void *smrealloc_aligned(struct mempool *mp, void *ptr, int align, size_t size) -{ - struct memnode *mn, *pmn; - assert(__builtin_popcount(align) == 1); - if (!ptr) - return smalloc_aligned(mp, align, size); - if (!(mn = find_mn(mp, (unsigned char *)ptr, &pmn))) { - smerror(mp, "SMALLOC: bad pointer passed to smrealloc()\n"); - return NULL; - } - if (!mn->used) { - smerror(mp, "SMALLOC: attempt to realloc the not allocated region\n"); - return NULL; - } - if (size == 0) { - smfree(mp, ptr); - return NULL; - } - if (size == mn->size) - return ptr; - if ((uintptr_t)mn->mem_area & (align - 1)) { - smerror(mp, "SMALLOC: unaligned pointer passed to smrealloc_aligned()\n"); - return NULL; - } - if (size < mn->size) { - /* shrink */ - sm_uncommit(mp, mn->mem_area + size, mn->size - size); - mntruncate(mn, size); - } else { - /* grow */ - struct memnode *nmn = mn->next; - if (nmn && !nmn->used && mn->size + nmn->size >= size) { - /* expand by shrinking next memnode */ - if (!sm_commit_simple(mp, nmn->mem_area, size - mn->size)) - return NULL; - memset(nmn->mem_area, 0, size - mn->size); - mntruncate(mn, size); - } else { - /* lazy impl */ - struct memnode *new_mn = sm_alloc_aligned(mp, align, size); - if (!new_mn) - return NULL; - memcpy(new_mn->mem_area, mn->mem_area, mn->size); - smfree(mp, mn->mem_area); - } - } - assert(mn->size == size); - return mn->mem_area; -} - int sminit(struct mempool *mp, void *start, size_t size) { mp->size = size; @@ -610,30 +461,16 @@ int sminit(struct mempool *mp, void *start, size_t size) return 0; } -static int do_sminit_com(struct mempool *mp, void *start, size_t size, - int (*commit)(void *area, size_t size), - int (*uncommit)(void *area, size_t size), int do_uncommit) -{ - sminit(mp, start, size); - mp->commit = commit; - mp->uncommit = uncommit; - if (uncommit && do_uncommit) - uncommit(start, size); - return 0; -} - int sminit_com(struct mempool *mp, void *start, size_t size, int (*commit)(void *area, size_t size), int (*uncommit)(void *area, size_t size)) { - return do_sminit_com(mp, start, size, commit, uncommit, 1); -} - -int sminit_comu(struct mempool *mp, void *start, size_t size, - int (*commit)(void *area, size_t size), - int (*uncommit)(void *area, size_t size)) -{ - return do_sminit_com(mp, start, size, commit, uncommit, 0); + sminit(mp, start, size); + mp->commit = commit; + mp->uncommit = uncommit; + if (uncommit) + uncommit(start, size); + return 0; } void smfree_all(struct mempool *mp) @@ -664,22 +501,6 @@ size_t smget_free_space(struct mempool *mp) return mp->avail; } -size_t smget_free_space_upto(struct mempool *mp, unsigned char *top) -{ - struct memnode *mn; - int cnt = 0; - for (mn = &mp->mn; mn; mn = mn->next) { - if (mn->mem_area + mn->size > top) { - if (!mn->used && mn->mem_area < top) - cnt += top - mn->mem_area; - break; - } - if (!mn->used) - cnt += mn->size; - } - return cnt; -} - size_t smget_largest_free_area(struct mempool *mp) { struct memnode *mn; diff --git a/src/base/lib/misc/spscq.c b/src/base/lib/misc/spscq.c deleted file mode 100644 index 89d1caa..0000000 --- a/src/base/lib/misc/spscq.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: single-producer single-consumer queue with locking - * - * Author: stsp - * - */ -#include -#include -#include -#include -#include "utilities.h" -#include "spscq.h" - -struct spscq { - unsigned size; - unsigned rd_pos; - unsigned fillup; - pthread_cond_t wr_cnd; - pthread_mutex_t wr_mtx; - unsigned char data[0]; -}; - -void *spscq_init(unsigned size) -{ - struct spscq *q = malloc(sizeof(*q) + size); - q->size = size; - q->rd_pos = q->fillup = 0; - pthread_cond_init(&q->wr_cnd, NULL); - pthread_mutex_init(&q->wr_mtx, NULL); - return q; -} - -void spscq_done(void *arg) -{ - free(arg); -} - -void *spscq_write_area(void *arg, unsigned *r_len) -{ - struct spscq *q = arg; - unsigned wr_pos, top; - pthread_mutex_lock(&q->wr_mtx); - while (q->fillup == q->size) - cond_wait(&q->wr_cnd, &q->wr_mtx); - wr_pos = q->rd_pos + q->fillup; - if (wr_pos >= q->size) { - wr_pos -= q->size; - top = q->rd_pos; - } else { - top = q->size; - } - pthread_mutex_unlock(&q->wr_mtx); - assert(top > wr_pos); - *r_len = top - wr_pos; - return (q->data + wr_pos); -} - -void spscq_commit_write(void *arg, unsigned len) -{ - struct spscq *q = arg; - pthread_mutex_lock(&q->wr_mtx); - q->fillup += len; - pthread_mutex_unlock(&q->wr_mtx); -} - -int spscq_read(void *arg, void *buf, unsigned len) -{ - struct spscq *q = arg; - unsigned done = 0; - pthread_mutex_lock(&q->wr_mtx); - if (q->fillup) { - unsigned ret; - ret = _min(q->fillup, q->size - q->rd_pos); - ret = _min(ret, len); - memcpy(buf, q->data + q->rd_pos, ret); - q->rd_pos += ret; - if (q->rd_pos == q->size) - q->rd_pos = 0; - q->fillup -= ret; - len -= ret; - done += ret; - if (q->fillup && len) { // can read more - ret = _min(q->fillup, len); - memcpy(buf + done, q->data + q->rd_pos, ret); - q->rd_pos += ret; - q->fillup -= ret; - len -= ret; - done += ret; - } - } - pthread_mutex_unlock(&q->wr_mtx); - if (done) - pthread_cond_signal(&q->wr_cnd); - return done; -} diff --git a/src/base/lib/timer/Makefile b/src/base/lib/timer/Makefile deleted file mode 100644 index ca0a971..0000000 --- a/src/base/lib/timer/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -top_builddir = ../../../.. -include $(top_builddir)/Makefile.conf - -ifeq ($(USE_EVTIMER_FD),1) -CFILES = evtimer_fd.c -else -CFILES = evtimer.c -endif - -include $(REALTOPDIR)/src/Makefile.common diff --git a/src/base/lib/timer/evtimer.c b/src/base/lib/timer/evtimer.c deleted file mode 100644 index e67cda2..0000000 --- a/src/base/lib/timer/evtimer.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: event timer API for freebsd. - * - * Author: stsp - * - * Note: SIGEV_THREAD is completely broken. - * timerfd-based impl should be used whereever possible. - * This implementation is provided only as a fall-back for freebsd. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_LIBBSD -#include -#endif -#include "evtimer.h" - -struct evtimer { - timer_t tmr; - void (*callback)(int ticks, void *); - void *arg; - clockid_t clk_id; - struct timespec start; - pthread_mutex_t start_mtx; - int blocked; - pthread_mutex_t block_mtx; - pthread_cond_t block_cnd; - int ticks; - int in_cbk; -}; - -static void evhandler(union sigval sv) -{ - int bl; - struct evtimer *t = sv.sival_ptr; - - pthread_mutex_lock(&t->block_mtx); - bl = t->blocked; - t->ticks += timer_getoverrun(t->tmr) + 1; - if (!bl) - t->in_cbk++; - pthread_mutex_unlock(&t->block_mtx); - if (!bl) { - t->callback(t->ticks, t->arg); - pthread_mutex_lock(&t->block_mtx); - t->in_cbk--; - t->ticks = 0; - pthread_mutex_unlock(&t->block_mtx); - pthread_cond_signal(&t->block_cnd); - } -} - -void *evtimer_create(void (*cbk)(int ticks, void *), void *arg) -{ - struct evtimer *t; - clockid_t id = CLOCK_MONOTONIC; - struct sigevent sev = { .sigev_notify = SIGEV_THREAD, - .sigev_notify_function = evhandler }; - timer_t tmr; - int rc; - - t = malloc(sizeof(*t)); - assert(t); - sev.sigev_value.sival_ptr = t; - rc = timer_create(id, &sev, &tmr); - assert(rc != -1); - t->tmr = tmr; - t->callback = cbk; - t->arg = arg; - t->clk_id = id; - t->blocked = 0; - t->ticks = 0; - t->in_cbk = 0; - pthread_mutex_init(&t->start_mtx, NULL); - pthread_mutex_init(&t->block_mtx, NULL); - pthread_cond_init(&t->block_cnd, NULL); - return t; -} - -void evtimer_delete(void *tmr) -{ - struct evtimer *t = tmr; - - timer_delete(t->tmr); - pthread_mutex_destroy(&t->start_mtx); - pthread_mutex_destroy(&t->block_mtx); - pthread_cond_destroy(&t->block_cnd); - free(t); -} - -void evtimer_set_rel(void *tmr, uint64_t ns, int periodic) -{ - struct evtimer *t = tmr; - struct itimerspec i = {}; - struct timespec rel, abs, start; - - rel.tv_sec = ns / NANOSECONDS_PER_SECOND; - rel.tv_nsec = ns % NANOSECONDS_PER_SECOND; - if (periodic) - i.it_interval = rel; - clock_gettime(t->clk_id, &start); - timespecadd(&start, &rel, &abs); - i.it_value = abs; - timer_settime(t->tmr, TIMER_ABSTIME, &i, NULL); - pthread_mutex_lock(&t->start_mtx); - t->start = start; - pthread_mutex_unlock(&t->start_mtx); -} - -uint64_t evtimer_gettime(void *tmr) -{ - struct evtimer *t = tmr; - struct timespec rel, abs; - - clock_gettime(t->clk_id, &abs); - pthread_mutex_lock(&t->start_mtx); - timespecsub(&abs, &t->start, &rel); - pthread_mutex_unlock(&t->start_mtx); - return (rel.tv_sec * NANOSECONDS_PER_SECOND + rel.tv_nsec); -} - -void evtimer_stop(void *tmr) -{ - struct evtimer *t = tmr; - struct itimerspec i = {}; - struct timespec start; - - timer_settime(t->tmr, 0, &i, NULL); - clock_gettime(t->clk_id, &start); - pthread_mutex_lock(&t->start_mtx); - t->start = start; - pthread_mutex_unlock(&t->start_mtx); -} - -void evtimer_block(void *tmr) -{ - struct evtimer *t = tmr; - - pthread_mutex_lock(&t->block_mtx); - t->blocked++; - while (t->in_cbk) - pthread_cond_wait(&t->block_cnd, &t->block_mtx); - pthread_mutex_unlock(&t->block_mtx); -} - -void evtimer_unblock(void *tmr) -{ - struct evtimer *t = tmr; - int ticks; - - /* if ticks accumulated, quickly deliver them first */ - pthread_mutex_lock(&t->block_mtx); - ticks = t->ticks; - pthread_mutex_unlock(&t->block_mtx); - if (ticks) - t->callback(ticks, t->arg); - /* then unblock */ - pthread_mutex_lock(&t->block_mtx); - t->ticks -= ticks; - t->blocked--; - pthread_mutex_unlock(&t->block_mtx); -} diff --git a/src/base/lib/timer/evtimer_fd.c b/src/base/lib/timer/evtimer_fd.c deleted file mode 100644 index d706f72..0000000 --- a/src/base/lib/timer/evtimer_fd.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: event timer API on top of timerfd. - * - * Author: @stsp - * - */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_TIMERFD_CREATE -#include -#else -#include -#include -#endif -#include -#include -#ifdef HAVE_BTHREAD_H -#include -#endif -#include -#ifdef HAVE_LIBBSD -#include -#else -#ifndef timespecadd -#define timespecadd(tsp, usp, vsp) \ - do { \ - (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ - (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ - if ((vsp)->tv_nsec >= 1000000000L) { \ - (vsp)->tv_sec++; \ - (vsp)->tv_nsec -= 1000000000L; \ - } \ - } while (0) -#endif -#endif -#include "utilities.h" -#include "evtimer.h" - -struct evtimer { - int fd; - void (*callback)(int ticks, void *); - void *arg; - clockid_t clk_id; - struct timespec start; - pthread_mutex_t start_mtx; - int blocked; - pthread_mutex_t block_mtx; - pthread_cond_t block_cnd; - pthread_cond_t unblock_cnd; - int in_cbk; - pthread_t thr; -}; - -static void do_callback(struct evtimer *t) -{ - uint64_t ticks; -#ifdef HAVE_TIMERFD_CREATE -again: - int rc = read(t->fd, &ticks, sizeof(ticks)); - if (rc == -1) { - if (errno == EAGAIN) // other thread modified timer - goto again; - perror("read()"); - return; - } -#else - struct kevent event; - int rc = kevent(t->fd, NULL, 0, &event, 1, NULL); - if (rc == -1) - perror("kevent()"); - if (event.flags & EV_ERROR) - error("bad kevent return, %i %s\n", rc, strerror(event.data)); - ticks = event.data; -#endif - - t->callback(ticks, t->arg); -} - -static void *evthread(void *arg) -{ - struct evtimer *t = arg; - - while (1) { - struct pollfd pf = { .fd = t->fd, .events = POLLIN }; - int rc = poll(&pf, 1, -1); - switch (rc) { - case -1: - perror("poll()"); - /* no break */ - case 0: - return NULL; - default: - if (!(pf.revents & POLLIN)) { - error("bad poll return, %i %x\n", rc, pf.revents); - continue; - } - break; - } - - pthread_mutex_lock(&t->block_mtx); - while (t->blocked) - cond_wait(&t->unblock_cnd, &t->block_mtx); - t->in_cbk++; - pthread_mutex_unlock(&t->block_mtx); - - do_callback(t); - - pthread_mutex_lock(&t->block_mtx); - t->in_cbk--; - pthread_mutex_unlock(&t->block_mtx); - pthread_cond_signal(&t->block_cnd); - } - - return NULL; -} - -void *evtimer_create(void (*cbk)(int ticks, void *), void *arg) -{ - struct evtimer *t; - clockid_t id = CLOCK_MONOTONIC; -#ifdef HAVE_TIMERFD_CREATE - int fd = timerfd_create(id, TFD_NONBLOCK | TFD_CLOEXEC); -#else - int fd = kqueue(); - int rc = fcntl(fd, F_GETFD); - if (rc != -1) - rc = fcntl(fd, F_SETFD, rc | FD_CLOEXEC); - assert(rc != -1); -#endif - - assert(fd != -1); - t = malloc(sizeof(*t)); - assert(t); - t->fd = fd; - t->callback = cbk; - t->arg = arg; - t->clk_id = id; - t->blocked = 0; - t->in_cbk = 0; - pthread_mutex_init(&t->start_mtx, NULL); - pthread_mutex_init(&t->block_mtx, NULL); - pthread_cond_init(&t->block_cnd, NULL); - pthread_cond_init(&t->unblock_cnd, NULL); - pthread_create(&t->thr, NULL, evthread, t); -#if defined(HAVE_PTHREAD_SETNAME_NP) && defined(__GLIBC__) - pthread_setname_np(t->thr, "dosemu: evtmr"); -#endif - return t; -} - -void evtimer_delete(void *tmr) -{ - struct evtimer *t = tmr; -#ifdef HAVE_TIMERFD_CREATE - struct itimerspec i = {}; - - timerfd_settime(t->fd, 0, &i, NULL); -#else - struct kevent change; - - EV_SET(&change, 1, EVFILT_TIMER, EV_DELETE, 0, 0, 0); - kevent(t->fd, &change, 1, NULL, 0, NULL); -#endif - pthread_mutex_lock(&t->block_mtx); - t->blocked++; - while (t->in_cbk) - cond_wait(&t->block_cnd, &t->block_mtx); - pthread_mutex_unlock(&t->block_mtx); - pthread_cancel(t->thr); - pthread_join(t->thr, NULL); - - close(t->fd); - pthread_mutex_destroy(&t->start_mtx); - pthread_mutex_destroy(&t->block_mtx); - pthread_cond_destroy(&t->block_cnd); - pthread_cond_destroy(&t->unblock_cnd); - free(t); -} - -void evtimer_set_rel(void *tmr, uint64_t ns, int periodic) -{ - struct evtimer *t = tmr; - struct timespec start; -#ifdef HAVE_TIMERFD_CREATE - struct itimerspec i = {}; - struct timespec rel, abs; - - rel.tv_sec = ns / NANOSECONDS_PER_SECOND; - rel.tv_nsec = ns % NANOSECONDS_PER_SECOND; - if (periodic) - i.it_interval = rel; -#endif - clock_gettime(t->clk_id, &start); -#ifdef HAVE_TIMERFD_CREATE - timespecadd(&start, &rel, &abs); - i.it_value = abs; - timerfd_settime(t->fd, TFD_TIMER_ABSTIME, &i, NULL); -#else - struct kevent change; /* event we want to monitor */ - if (periodic) - EV_SET(&change, 1, EVFILT_TIMER, EV_ADD | EV_ENABLE, NOTE_NSECONDS, ns, 0); - else - EV_SET(&change, 1, EVFILT_TIMER, EV_ONESHOT | EV_ADD | EV_ENABLE, NOTE_NSECONDS, ns, 0); - kevent(t->fd, &change, 1, NULL, 0, NULL); -#endif - pthread_mutex_lock(&t->start_mtx); - t->start = start; - pthread_mutex_unlock(&t->start_mtx); -} - -uint64_t evtimer_gettime(void *tmr) -{ - struct evtimer *t = tmr; - uint64_t rel; - struct timespec abs; - - clock_gettime(t->clk_id, &abs); - pthread_mutex_lock(&t->start_mtx); - rel = abs.tv_sec * NANOSECONDS_PER_SECOND + abs.tv_nsec - - (t->start.tv_sec * NANOSECONDS_PER_SECOND + t->start.tv_nsec); - pthread_mutex_unlock(&t->start_mtx); - return rel; -} - -void evtimer_stop(void *tmr) -{ - struct evtimer *t = tmr; - struct timespec start; -#ifdef HAVE_TIMERFD_CREATE - struct itimerspec i = {}; - - timerfd_settime(t->fd, 0, &i, NULL); -#else - struct kevent change; - - EV_SET(&change, 1, EVFILT_TIMER, EV_DELETE, 0, 0, 0); - kevent(t->fd, &change, 1, NULL, 0, NULL); -#endif - clock_gettime(t->clk_id, &start); - pthread_mutex_lock(&t->start_mtx); - t->start = start; - pthread_mutex_unlock(&t->start_mtx); -} - -void evtimer_block(void *tmr) -{ - struct evtimer *t = tmr; - - pthread_mutex_lock(&t->block_mtx); - t->blocked++; - while (t->in_cbk) - cond_wait(&t->block_cnd, &t->block_mtx); - pthread_mutex_unlock(&t->block_mtx); -} - -void evtimer_unblock(void *tmr) -{ - struct evtimer *t = tmr; - - pthread_mutex_lock(&t->block_mtx); - t->blocked--; - pthread_mutex_unlock(&t->block_mtx); - pthread_cond_signal(&t->unblock_cnd); -} diff --git a/src/base/lib/translate/Makefile b/src/base/lib/translate/Makefile index 2ea1d5c..66cd5b3 100644 --- a/src/base/lib/translate/Makefile +++ b/src/base/lib/translate/Makefile @@ -38,10 +38,10 @@ include $(REALTOPDIR)/src/Makefile.common vpath UnicodeCrunchedAttributes $(srcdir) crunch_UnicodeData: crunch_UnicodeData.c - $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(INCDIR) -o $@ $< + $(CC) $(INCDIR) -o $@ $< make_attributes: make_attributes.c - $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(INCDIR) -o $@ $< + $(CC) $(INCDIR) -o $@ $< keysym_attributes.c: UnicodeCrunchedAttributes make_attributes ./make_attributes < $< > $@ diff --git a/src/base/lib/translate/dosemu_charset.c b/src/base/lib/translate/dosemu_charset.c index 06638f4..192d4d4 100644 --- a/src/base/lib/translate/dosemu_charset.c +++ b/src/base/lib/translate/dosemu_charset.c @@ -93,7 +93,7 @@ static void foreach_terminal_callback(void *callback_data, { struct foreach_terminal_state *state = callback_data; if ((byte_len == 1) && ((bytes[0] <= 0x20) || (bytes[0] == 0x7f))) { - /* suppress translations for the control characters.. */ + /* supress translations for the control characters.. */ return; } state->callback(state->callback_data, symbol, bytes, byte_len); @@ -127,7 +127,7 @@ struct char_set_operations terminal_charset_ops = { }; /* - * Terminal Charset management + * Terminal Charset managment * =========================== */ diff --git a/src/base/lib/translate/translate.c b/src/base/lib/translate/translate.c index 4ebbba4..19fcc19 100644 --- a/src/base/lib/translate/translate.c +++ b/src/base/lib/translate/translate.c @@ -3,7 +3,6 @@ #include #include #include -#include "init.h" #include "emu.h" #include "translate/translate.h" #include "translate/unicode_symbols.h" diff --git a/src/base/lib/translate/translate_config.c b/src/base/lib/translate/translate_config.c index b15af42..026c6d4 100644 --- a/src/base/lib/translate/translate_config.c +++ b/src/base/lib/translate/translate_config.c @@ -10,7 +10,7 @@ #include "video.h" #include "utilities.h" -struct translate_config_t trconfig; /* Initialized to nulls */ +struct translate_config_t trconfig; /* Intialized to nulls */ static void config_translate_scrub(void) { diff --git a/src/base/lib/translate/unicode_utils.c b/src/base/lib/translate/unicode_utils.c index 95dac24..73db855 100644 --- a/src/base/lib/translate/unicode_utils.c +++ b/src/base/lib/translate/unicode_utils.c @@ -23,7 +23,7 @@ size_t character_count(const struct char_set_state *in_state, const char *str, do { consumed = charset_to_unicode(&state, &temp, (const unsigned char *)str, max_str_len); if (consumed == (size_t) -1) { - /* An error occurred abort */ + /* An error occured abort */ if (characters == 0) { characters = (size_t) -1; } @@ -52,7 +52,7 @@ size_t charset_to_unicode_string(struct char_set_state *state, do { consumed = charset_to_unicode(state, dst, (const unsigned char *)*src, src_len); if (consumed == (size_t) -1) { - /* An error occurred abort */ + /* An error occured abort */ if (characters == 0) { characters = (size_t) -1; } @@ -86,7 +86,7 @@ size_t unicode_to_charset_string(struct char_set_state *state, produced = unicode_to_charset(state, **src, (unsigned char *)dst, dst_len); if (produced == (size_t) -1) { - /* An error occurred abort */ + /* An error occured abort */ if (characters == 0) { characters = (size_t) -1; } diff --git a/src/base/misc/Makefile b/src/base/misc/Makefile index 6c2feb8..3ba929e 100644 --- a/src/base/misc/Makefile +++ b/src/base/misc/Makefile @@ -2,8 +2,7 @@ top_builddir=../../.. include $(top_builddir)/Makefile.conf -CFILES = hma.c ioctl.c disks.c utilities.c dos2linux.c fatfs.c mmio_tracing.c \ - clipboard.c +CFILES = hma.c ioctl.c disks.c utilities.c dos2linux.c fatfs.c mmio_tracing.c include $(REALTOPDIR)/src/Makefile.common diff --git a/src/base/misc/clipboard.c b/src/base/misc/clipboard.c deleted file mode 100644 index 11f4d62..0000000 --- a/src/base/misc/clipboard.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: clipboard support - * - * Authors: @andrewbird @stsp - */ -#include -#ifdef HAVE_LIBBSD -#include -#endif -#include "dosemu_debug.h" -#include "types.h" -#include "translate/translate.h" -#include "clipboard.h" - -struct clipboard_system *Clipboard; - -static char *clipboard_make_str_utf8(int type, const char *p, int size) -{ - char *q; - - if (type == CF_TEXT) { - q = strndup(p, size); - } else { // CF_OEMTEXT - struct char_set_state state; - int characters; - t_unicode *str; - - init_charset_state(&state, trconfig.dos_charset); - - characters = character_count(&state, p, size); - if (characters == -1) { - v_printf("SDL_clipboard: Write invalid char count\n"); - return NULL; - } - - str = malloc(sizeof(t_unicode) * (characters + 1)); - charset_to_unicode_string(&state, str, &p, size, characters + 1); - cleanup_charset_state(&state); - q = unicode_string_to_charset((wchar_t *)str, "utf8"); - free(str); - } - return q; -} - -static char *clipboard_make_str_dos(int type, const char *p, int size) -{ - char *q; - - if (type == CF_TEXT) { - q = strndup(p, size); - } else { // CF_OEMTEXT - struct char_set_state state; - struct char_set *utf8; - int characters; - t_unicode *str; - - utf8 = lookup_charset("utf8"); - init_charset_state(&state, utf8); - - characters = character_count(&state, p, size); - if (characters == -1) { - v_printf("SDL_clipboard: _clipboard_grab_data() invalid char count\n"); - return NULL; - } - - str = malloc(sizeof(t_unicode) * (characters + 1)); - charset_to_unicode_string(&state, str, &p, size, characters + 1); - cleanup_charset_state(&state); - q = unicode_string_to_charset((wchar_t *)str, trconfig.dos_charset->names[0]); - free(str); - } - return q; -} - -int register_clipboard_system(struct clipboard_system *cs) -{ - Clipboard = cs; - return 1; -} - -char *clip_str; - -static void do_clear(void) -{ - free(clip_str); - clip_str = NULL; -} - -void add_clip_str(char *q) -{ - if (clip_str) { - clip_str = realloc(clip_str, strlen(clip_str) + strlen(q) + 1); - strcat(clip_str, q); - free(q); - } else { - clip_str = q; - } -} - -int cnn_clear(void) -{ - do_clear(); - return TRUE; -} - -int cnn_write(int type, const char *p, int size) -{ - char *q; - - if (type != CF_TEXT && type != CF_OEMTEXT) { - v_printf("SDL_clipboard: Write failed, type (0x%02x) unsupported\n", type); - return FALSE; - } - q = clipboard_make_str_utf8(type, p, size); - if (!q) - return FALSE; - add_clip_str(q); - return TRUE; -} - -int cnn_getsize(int type) -{ - char *q; - int ret; - - if (type == CF_TEXT) - v_printf("SDL_clipboard: GetSize of type CF_TEXT\n"); - else if (type == CF_OEMTEXT) - v_printf("SDL_clipboard: GetSize of type CF_OEMTEXT\n"); - else { - v_printf("SDL_clipboard: GetSize failed (type 0x%02x unsupported\n", type); - return 0; - } - - if (!clip_str) { - v_printf("SDL_clipboard: GetSize failed (grabbed data is NULL\n"); - return 0; - } - q = clipboard_make_str_dos(type, clip_str, strlen(clip_str)); - if (!q) - return 0; - ret = strlen(clip_str) + 1; - free(q); - return ret; -} - -int cnn_getdata(int type, char *p, int size) -{ - char *q; - - if (!clip_str) - return FALSE; - q = clipboard_make_str_dos(type, clip_str, strlen(clip_str)); - if (!q) - return FALSE; - strlcpy(p, q, size); - free(q); - return TRUE; -} diff --git a/src/base/misc/disks.c b/src/base/misc/disks.c index 4c8f80e..4b0bccb 100644 --- a/src/base/misc/disks.c +++ b/src/base/misc/disks.c @@ -36,38 +36,6 @@ #include "redirect.h" #include "cpu-emu.h" -static uint8_t mbr_boot_code[] = { - /* - * Present the usual start to the code in an MBR - - jmp short @1 - nop - */ - 0xeb, - 0x01, - 0x90, - /* - @1: - mov ax,0fffeh - int 0e6h - */ - 0xb8, - DOS_HELPER_MBR, - 0xff, - 0xcd, - DOS_HELPER_INT, - /* - * This is an instruction that we never execute and is present only to - * convince Norton Disk Doctor that we are a valid mbr - - int 0x13 - */ - 0xcd, - 0x13, -}; -static_assert(sizeof(mbr_boot_code) < PART_INFO_START, - "mbr_boot_code size is incorrect"); - static int disks_initiated = 0; struct disk disktab[MAX_FDISKS]; struct disk hdisktab[MAX_HDISKS]; @@ -75,16 +43,20 @@ struct disk hdisktab[MAX_HDISKS]; #define FDISKS config.fdisks #define HDISKS config.hdisks +#ifdef __linux__ +static void set_part_ent(struct disk *dp, unsigned char *tmp_mbr); +#endif + #if 1 # define FLUSHDISK(dp) flush_disk(dp) #else -# define FLUSHDISK(dp) if (dp && dp->removable && !config.fastfloppy) \ +# define FLUSHDISK(dp) if (dp && dp->removeable && !config.fastfloppy) \ ioctl(dp->fdesc, FDFLUSH, 0) #endif static void flush_disk(struct disk *dp) { - if (dp && dp->removable && dp->fdesc >= 0) { + if (dp && dp->removeable && dp->fdesc >= 0) { if (dp->type == IMAGE || (dp->type == FLOPPY && !config.fastfloppy)) { close(dp->fdesc); dp->fdesc = -1; @@ -100,6 +72,7 @@ struct disk_fptr { }; static void image_auto(struct disk *); +static void image_setup(struct disk *); static void hdisk_auto(struct disk *); static void hdisk_setup(struct disk *); @@ -108,19 +81,18 @@ static void floppy_auto(struct disk *); static void floppy_setup(struct disk *); static void partition_auto(struct disk *); +static void partition_setup(struct disk *); static void dir_auto(struct disk *); static void dir_setup(struct disk *); -static void MBR_setup(struct disk *); -static void VBR_setup(struct disk *); static struct disk_fptr disk_fptrs[NUM_DTYPES] = { - {image_auto, MBR_setup}, + {image_auto, image_setup}, {hdisk_auto, hdisk_setup}, {floppy_auto, floppy_setup}, - {partition_auto, VBR_setup}, + {partition_auto, partition_setup}, {dir_auto, dir_setup} }; @@ -195,9 +167,9 @@ static void dump_disk_blks(unsigned tb, int count, int ssiz) int read_mbr(const struct disk *dp, unsigned buffer) { /* copy the MBR... */ - e_invalidate(buffer, sizeof(dp->part_info.mbr)); - memcpy_2dos(buffer, &dp->part_info.mbr, sizeof(dp->part_info.mbr)); - return sizeof(dp->part_info.mbr); + e_invalidate(buffer, dp->part_info.mbr_size); + memcpy_2dos(buffer, dp->part_info.mbr, dp->part_info.mbr_size); + return dp->part_info.mbr_size; } /* read_sectors @@ -253,7 +225,11 @@ read_sectors(const struct disk *dp, unsigned buffer, uint64_t sector, pos = calc_pos(dp, sector); d_printf("DISK: %s: Trying to read %ld sectors at LBA %"PRIu64"", dp->dev_name,count,sector); - d_printf("%+"PRIi64" at pos %"PRIi64"\n", dp->header, pos); +#if defined(__linux__) && defined(__i386__) + d_printf("%+lld at pos %lld\n", dp->header, pos); +#else + d_printf("%+ld at pos %ld\n", dp->header, pos); +#endif /* reads beginning before that actual disk/file */ if (pos < 0 && count > 0) { @@ -261,7 +237,7 @@ read_sectors(const struct disk *dp, unsigned buffer, uint64_t sector, int mbroff = pos + dp->start * SECTOR_SIZE; int mbrread = 0; - if (!(dp->type == PARTITION || dp->type == DIR_TYPE)) { + if(!(dp->type == PARTITION || dp->type == DIR_TYPE)) { error("negative offset on non-partition disk type\n"); return -DERR_NOTFOUND; } @@ -275,11 +251,11 @@ read_sectors(const struct disk *dp, unsigned buffer, uint64_t sector, */ /* copy the MBR... */ - if(mbroff < sizeof(dp->part_info.mbr)) { - mbrread = sizeof(dp->part_info.mbr) - mbroff; + if(mbroff < dp->part_info.mbr_size) { + mbrread = dp->part_info.mbr_size - mbroff; mbrread = mbrread > readsize ? readsize : mbrread; e_invalidate(buffer, mbrread); - memcpy_2dos(buffer, (const uint8_t *)&dp->part_info.mbr + mbroff, mbrread); + memcpy_2dos(buffer, dp->part_info.mbr + mbroff, mbrread); d_printf("read 0x%lx bytes from MBR, ofs = 0x%lx (0x%lx bytes left)\n", (unsigned long) mbrread, (unsigned long) mbroff, (unsigned long) (readsize - mbrread) ); @@ -358,7 +334,11 @@ write_sectors(struct disk *dp, unsigned buffer, uint64_t sector, pos = calc_pos(dp, sector); d_printf("DISK: %s: Trying to write %ld sectors at LBA %"PRIu64"", dp->dev_name,count,sector); - d_printf(" at pos %"PRIi64"\n", pos); +#if defined(__linux__) && defined(__i386__) + d_printf(" at pos %lld\n", pos); +#else + d_printf(" at pos %ld\n", pos); +#endif /* * writes outside the partition (before the actual disk/file) are ignored @@ -491,71 +471,106 @@ static int set_floppy_chs_by_size(off_t s, struct disk *dp) { return 1; } -#ifdef DISK_DEBUG - -static void print_bpb(struct on_disk_bpb *bpb) +static void image_auto(struct disk *dp) { - d_printf(" bpb\n"); - d_printf(" bytes_per_sector %u\n", bpb->bytes_per_sector); - d_printf(" sectors_per_cluster %u\n", bpb->sectors_per_cluster); - d_printf(" reserved_sectors %u\n", bpb->reserved_sectors); - d_printf(" num_fats %u\n", bpb->num_fats); - d_printf(" num_root_entries %u\n", bpb->num_root_entries); - d_printf(" num_sectors_small %u\n", bpb->num_sectors_small); - d_printf(" media_type %x\n", bpb->media_type); - d_printf(" sectors_per_fat %u\n", bpb->sectors_per_fat); - d_printf(" sectors_per_track %u\n", bpb->sectors_per_track); - d_printf(" num_heads %u\n", bpb->num_heads); - // assume v331+ - if (bpb->num_sectors_small == 0) { - d_printf(" v331_400_hidden_sectors %u\n", bpb->v331_400_hidden_sectors); - d_printf(" v331_400_num_sectors_large %u\n", bpb->v331_400_num_sectors_large); - } - // assume v340+ - if (bpb->v340_400_signature == BPB_SIG_V340 || bpb->v340_400_signature == BPB_SIG_V400) { - d_printf(" v340_400_drive_number %x\n", bpb->v340_400_drive_number); - d_printf(" v340_400_flags %x\n", bpb->v340_400_flags); - d_printf(" v340_400_signature %x\n", bpb->v340_400_signature); - d_printf(" v340_400_serial_number %x\n", bpb->v340_400_serial_number); + uint32_t magic; + uint64_t filesize; + struct image_header header; + unsigned char sect[0x200]; + struct stat st; + + d_printf("IMAGE auto-sensing\n"); + + if (dp->fdesc == -1) { + warn("WARNING: image filedesc not open\n"); + dp->fdesc = open(dp->dev_name, (dp->rdonly ? O_RDONLY : O_RDWR) | O_CLOEXEC); + if (dp->fdesc == -1) { + /* We should check whether errno is EROFS, but if not the next open will + fail again and the following lseek will throw us out of dos. So we win + a very tiny amount of time in case it works. Also, if for some reason + this does work (should be impossible), we can at least try to + continue. (again how sick can you get :-) ) + */ + dp->fdesc = open(dp->dev_name, O_RDONLY | O_CLOEXEC); + dp->rdonly = 1; + } } - if (bpb->v340_400_signature == BPB_SIG_V400) { - d_printf(" v400_vol_label '%.11s'\n", bpb->v400_vol_label); - d_printf(" v400_fat_type '%.8s'\n", bpb->v400_fat_type); + if (dp->fdesc == -1) { + warn("WARNING: image filedesc still not open\n"); + leavedos(19); + return; } -} -static void print_disk_structure(struct disk *dp) -{ - d_printf(" disk structure\n"); - d_printf(" rdonly=%d\n", dp->rdonly); - d_printf(" boot=%d\n", dp->boot); - d_printf(" sectors=%d(0x%x)\n", dp->sectors, dp->sectors); - d_printf(" heads=%d(0x%x)\n", dp->heads, dp->heads); - d_printf(" tracks=%d(0x%x)\n", dp->tracks, dp->tracks); - d_printf(" start=%lu(0x%lx)\n", dp->start, dp->start); - d_printf(" num_secs=%"PRIu64"(0x%"PRIx64")\n", dp->num_secs, dp->num_secs); - d_printf(" drive_num=0x%02x\n", dp->drive_num); - d_printf(" header=%lld\n", (long long int)dp->header); -} + if (dp->floppy) { -#else -#define print_bpb(x) -#define print_disk_structure(x) -#endif + if (fstat(dp->fdesc, &st) < 0) { + d_printf("IMAGE auto couldn't stat disk file %s\n", dp->dev_name); + leavedos(19); + return; + } + if (!(set_floppy_chs_by_size(st.st_size, dp) || + set_floppy_chs_by_type(dp->default_cmos, dp)) ){ + d_printf("IMAGE auto set floppy geometry %s\n", dp->dev_name); + leavedos(19); + return; + } + dp->start = 0; + dp->num_secs = (unsigned long long)dp->tracks * dp->heads * dp->sectors; -static void print_partition_entry(struct on_disk_partition *p) -{ - d_printf(" partition entry\n"); - d_printf(" beg head %u, sec %u, cyl %u / end head %u, sec %u, cyl %u\n", - p->start_head, p->start_sector, - PTBL_HL_GET(p, start_track), - p->end_head, p->end_sector, - PTBL_HL_GET(p, end_track)); - d_printf(" pre_secs %u, num_secs %u(0x%x)\n", - p->num_sect_preceding, - p->num_sectors, p->num_sectors); - d_printf(" type 0x%02x, bootflag 0x%02x\n", p->OS_type, p->bootflag); + d_printf("IMAGE auto floppy %s; t=%d, h=%d, s=%d\n", + dp->dev_name, dp->tracks, dp->heads, dp->sectors); + return; + } + + // Hard disk image + + lseek(dp->fdesc, 0, SEEK_SET); + if (RPT_SYSCALL(read(dp->fdesc, &header, sizeof(header))) != sizeof(header)) { + error("could not read full header in image_init\n"); + leavedos(19); + } + lseek(dp->fdesc, 0, SEEK_SET); + if (RPT_SYSCALL(read(dp->fdesc, sect, sizeof(sect))) != sizeof(sect)) { + error("could not read full header in image_init\n"); + leavedos(19); + } + + memcpy(&magic, header.sig, 4); + if (strncmp(header.sig, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) == 0 || + (magic == DEXE_MAGIC) ) { + dp->heads = header.heads; + dp->sectors = header.sectors; + dp->tracks = header.cylinders; + dp->header = header.header_end; + dp->num_secs = (unsigned long long)dp->tracks * dp->heads * dp->sectors; + } else if (sect[510] == 0x55 && sect[511] == 0xaa) { + filesize = lseek(dp->fdesc, 0, SEEK_END); + if (filesize & (SECTOR_SIZE - 1) ) { + error("hdimage size is not sector-aligned (%"PRIu64" bytes), truncated!\n", + filesize & (SECTOR_SIZE - 1) ); + } + dp->num_secs = (filesize /* + SECTOR_SIZE - 1 */ ) / SECTOR_SIZE; + dp->heads = 255; + dp->sectors = 63; + if (dp->num_secs % (dp->heads * dp->sectors) ) { + error("hdimage size is not cylinder-aligned (%"PRIu64" sectors), truncated!\n", + dp->num_secs % (dp->heads * dp->sectors) ); + } + dp->tracks = (dp->num_secs /* + (dp->heads * dp->sectors - 1) */ ) + / (dp->heads * dp->sectors); + /* round down number of sectors and number of tracks */ + dp->header = 0; + } else { + error("IMAGE %s header lacks magic string - cannot autosense!\n", + dp->dev_name); + leavedos(20); + } + + d_printf("IMAGE auto disk %s; num_secs=%"PRIu64", t=%d, h=%d, s=%d, off=%ld\n", + dp->dev_name, dp->num_secs, + dp->tracks, dp->heads, dp->sectors, + (long) dp->header); } static void hdisk_auto(struct disk *dp) @@ -691,22 +706,22 @@ static void dir_auto(struct disk *dp) dp->tracks = 306; dp->heads = 4; dp->sectors = 17; - d_printf("DIR: Forcing IBM disk type 1\n"); + d_printf("DISK: Forcing IBM disk type 1\n"); break; case 2: dp->tracks = 615; dp->heads = 4; dp->sectors = 17; - d_printf("DIR: Forcing IBM disk type 2\n"); + d_printf("DISK: Forcing IBM disk type 2\n"); break; case 9: dp->tracks = 900; dp->heads = 15; dp->sectors = 17; - d_printf("DIR: Forcing IBM disk type 9\n"); + d_printf("DISK: Forcing IBM disk type 9\n"); break; default: - error("DIR: Invalid disk type (%d)\n", dp->hdtype); + d_printf("DISK: Invalid disk type (%d)\n", dp->hdtype); config.exitearly = 1; break; } @@ -714,9 +729,6 @@ static void dir_auto(struct disk *dp) } dp->num_secs = (unsigned long long)dp->tracks * dp->heads * dp->sectors; - - dp->header = 0; - d_printf( "DIR auto disk %s; h=%d, s=%d, t=%d, start=%ld\n", dp->dev_name, dp->heads, dp->sectors, dp->tracks, dp->start @@ -746,290 +758,251 @@ static struct on_disk_partition build_pi(struct disk *dp) return p; } +#ifdef __linux__ +static void update_disk_geometry(struct disk *dp, struct on_disk_partition *p) +{ + dp->heads = p->end_head + 1; + dp->sectors = p->end_sector; + dp->tracks = PTBL_HL_GET(p, end_track) + 1; +} +#endif + static void dir_setup(struct disk *dp) { + unsigned char *mbr; + struct partition *pi = &dp->part_info; int i = strlen(dp->dev_name); - while (--i >= 0) - if (dp->dev_name[i] == '/') - dp->dev_name[i] = 0; - else - break; - if (!dp->floppy) { - dp->part_info.number = 1; - memcpy(&dp->part_info.mbr.code, &mbr_boot_code, sizeof(mbr_boot_code)); - dp->part_info.mbr.partition[0] = build_pi(dp); - dp->part_info.mbr.signature = MBR_SIG; + while(--i >= 0) if(dp->dev_name[i] == '/') dp->dev_name[i] = 0; else break; - d_printf("DIR setup disk %s:\n", dp->dev_name); - print_partition_entry(&dp->part_info.mbr.partition[0]); - print_disk_structure(dp); + dp->header = 0; + if (dp->floppy) { + pi->mbr_size = 0; + pi->mbr = NULL; + } else { + struct on_disk_partition *mp, p; + p = build_pi(dp); + pi->mbr_size = SECTOR_SIZE; + pi->mbr = malloc(pi->mbr_size); + mbr = pi->mbr; + mp = (struct on_disk_partition *)&mbr[PART_INFO_START]; + + memset(mbr, 0, SECTOR_SIZE); + /* + * mov ax,0fffeh + * int 0e6h + */ + mbr[0x00] = 0xb8; + mbr[0x01] = DOS_HELPER_MBR; + mbr[0x02] = 0xff; + mbr[0x03] = 0xcd; + mbr[0x04] = DOS_HELPER_INT; + + /* This is an instruction that we never execute and is present only to + * convince Norton Disk Doctor that we are a valid mbr */ + mbr[0x05] = 0xcd; /* int 0x13 */ + mbr[0x06] = 0x13; + + *mp = p; + mbr[SECTOR_SIZE - 2] = 0x55; + mbr[SECTOR_SIZE - 1] = 0xaa; + + d_printf("DIR partition setup for directory %s\n", dp->dev_name); + + d_printf("DIR partition table entry for device %s is:\n", dp->dev_name); + d_printf("beg head %d, sec %d, cyl %d = end head %d, sec %d, cyl %d\n", + p.start_head, p.start_sector, PTBL_HL_GET(&p, start_track), + p.end_head, p.end_sector, PTBL_HL_GET(&p, end_track)); + d_printf("pre_secs %d, num_secs %d = %x, -dp->header %ld = 0x%lx\n", + p.num_sect_preceding, p.num_sectors, p.num_sectors, + (long) -dp->header, (unsigned long) -dp->header); } dp->fatfs = NULL; } -static void image_auto(struct disk *dp) -{ - uint32_t magic; - uint64_t filesize; - struct stat st; - union { - char buf[512]; - struct image_header header; - struct on_disk_mbr mbr; - struct on_disk_vbr vbr; - } sect0; - static_assert(sizeof(sect0) == 512, "bad sect0 size"); - - d_printf("IMAGE auto-sensing\n"); - - if (dp->fdesc == -1) { - warn("WARNING: image filedesc not open\n"); - dp->fdesc = open(dp->dev_name, (dp->rdonly ? O_RDONLY : O_RDWR) | O_CLOEXEC); - if (dp->fdesc == -1) { - /* We should check whether errno is EROFS, but if not the next open will - fail again and the following lseek will throw us out of dos. So we win - a very tiny amount of time in case it works. Also, if for some reason - this does work (should be impossible), we can at least try to - continue. (again how sick can you get :-) ) - */ - dp->fdesc = open(dp->dev_name, O_RDONLY | O_CLOEXEC); - dp->rdonly = 1; - } - } - - if (dp->fdesc == -1) { - warn("WARNING: image filedesc still not open\n"); - leavedos(19); - return; - } - - if (dp->floppy) { - - if (fstat(dp->fdesc, &st) < 0) { - d_printf("IMAGE auto couldn't stat disk file %s\n", dp->dev_name); - leavedos(19); - return; - } - if (!(set_floppy_chs_by_size(st.st_size, dp) || - set_floppy_chs_by_type(dp->default_cmos, dp)) ){ - d_printf("IMAGE auto set floppy geometry %s\n", dp->dev_name); - leavedos(19); - return; - } - dp->start = 0; - dp->num_secs = (unsigned long long)dp->tracks * dp->heads * dp->sectors; - - d_printf("IMAGE auto floppy %s; t=%d, h=%d, s=%d\n", - dp->dev_name, dp->tracks, dp->heads, dp->sectors); - return; - } - - // Hard disk image - - lseek(dp->fdesc, 0, SEEK_SET); - if (RPT_SYSCALL(read(dp->fdesc, §0.buf, sizeof(sect0))) != sizeof(sect0)) { - error("could not read sector 0 in image_init\n"); - leavedos(19); - } - - memcpy(&magic, sect0.header.sig, 4); - if (strncmp(sect0.header.sig, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) == 0 || - (magic == DEXE_MAGIC) ) { - d_printf(" Dosemu header found, image will contain whole disk\n"); - dp->heads = sect0.header.heads; - dp->sectors = sect0.header.sectors; - dp->tracks = sect0.header.cylinders; - dp->header = sect0.header.header_end; - dp->num_secs = (unsigned long long)dp->tracks * dp->heads * dp->sectors; - - } else if (sect0.vbr.signature == VBR_SIG && - sect0.vbr.u.bpb.media_type == 0xf8 && sect0.vbr.u.bpb.num_fats == 2) { /* VBR */ - d_printf(" VBR found, image is a filesystem\n"); - - if (sect0.vbr.u.bpb.num_sectors_small == 0 && ( - sect0.vbr.u.bpb.v340_400_signature == BPB_SIG_V340 || - sect0.vbr.u.bpb.v340_400_signature == BPB_SIG_V400)) - dp->num_secs = sect0.vbr.u.bpb.v331_400_num_sectors_large; - else if (sect0.vbr.u.bpb7.num_sectors_small == 0 && ( - sect0.vbr.u.bpb7.signature == BPB_SIG_V7_SHORT || - sect0.vbr.u.bpb7.signature == BPB_SIG_V7_LONG)) - dp->num_secs = sect0.vbr.u.bpb7.num_sectors_large; - else - dp->num_secs = sect0.vbr.u.bpb.num_sectors_small; - dp->heads = sect0.vbr.u.bpb.num_heads; - dp->sectors = sect0.vbr.u.bpb.sectors_per_track; - - // Must also set these for build_pi input in setup phase - dp->start = dp->sectors; // one cylinder for mbr + alignment - dp->num_secs += dp->start; - dp->tracks = dp->num_secs / dp->sectors / dp->heads; - dp->header = 0; - - dp->type = PARTITION; // VBR_setup() will subsequently be run - dp->part_image = 1; - - } else if (sect0.mbr.signature == MBR_SIG) { /* MBR */ - d_printf(" MBR found, image contains partitions\n"); - - filesize = lseek(dp->fdesc, 0, SEEK_END); - if (filesize & (SECTOR_SIZE - 1) ) { - error("hdimage size is not sector-aligned (%"PRIu64" bytes), truncated!\n", - filesize & (SECTOR_SIZE - 1) ); - } - dp->num_secs = (filesize /* + SECTOR_SIZE - 1 */ ) / SECTOR_SIZE; - dp->heads = 255; - dp->sectors = 63; - if (dp->num_secs % (dp->heads * dp->sectors) ) { - d_printf("hdimage size is not cylinder-aligned (%"PRIu64" sectors), truncated!\n", - dp->num_secs % (dp->heads * dp->sectors) ); - } - dp->tracks = (dp->num_secs /* + (dp->heads * dp->sectors - 1) */ ) - / (dp->heads * dp->sectors); - /* round down number of sectors and number of tracks */ - dp->header = 0; - - } else { - error("IMAGE %s header lacks magic string - cannot autosense!\n", - dp->dev_name); - leavedos(20); - } - - d_printf("IMAGE auto disk %s; num_secs=%"PRIu64", t=%d, h=%d, s=%d, off=%ld\n", - dp->dev_name, dp->num_secs, - dp->tracks, dp->heads, dp->sectors, - (long) dp->header); -} - -static void MBR_setup(struct disk *dp) +static void image_setup(struct disk *dp) { ssize_t rd; - int ret, i; + int ret; if (dp->floppy) { return; } - /* Disk / Image already has MBR */ dp->part_info.number = 1; + dp->part_info.mbr_size = SECTOR_SIZE; + dp->part_info.mbr = malloc(dp->part_info.mbr_size); + ret = lseek(dp->fdesc, dp->header, SEEK_SET); if (ret == -1) { - error("MBR_setup: Can't seek '%s'\n", dp->dev_name); - leavedos(35); - } - rd = read(dp->fdesc, &dp->part_info.mbr, sizeof(dp->part_info.mbr)); - if (rd != sizeof(dp->part_info.mbr)) { - error("MBR_setup: Can't read MBR from '%s'\n", dp->dev_name); + error("image_setup: Can't seek '%s'\n", dp->dev_name); leavedos(35); } - d_printf("MBR_setup: %s:\n", dp->dev_name); - - for (i = 0; i < 4; i++) { - if (dp->part_info.mbr.partition[i].OS_type) - print_partition_entry(&dp->part_info.mbr.partition[i]); + rd = read(dp->fdesc, dp->part_info.mbr, dp->part_info.mbr_size); + if (rd != dp->part_info.mbr_size) { + error("image_setup: Can't read MBR from '%s'\n", dp->dev_name); + leavedos(35); } - - print_disk_structure(dp); } +/* XXX - relies upon a file of SECTOR_SIZE in PARTITION_PATH that which + * contains the MBR (first sector) of the drive (i.e. /dev/hda). + * only works for /dev/hda1 right now, and only allows one + * partition, which must begin at head 1, sec 1, cyl 0 (i.e. linear + * sector 2, the second one). + * Also, it eats memory proportional to the number of sectors before + * the start of the partition. + */ + static void partition_auto(struct disk *dp) { - struct on_disk_vbr vbr; - d_printf("PARTITION auto\n"); - - if (!dp->part_image) { -#ifdef __linux__ - unsigned long length; - if (ioctl(dp->fdesc, BLKGETSIZE, &length)) { - error("calling ioctl BLKGETSIZE for PARTITION %s\n", dp->dev_name); - leavedos(22); - } - dp->num_secs = length; -#else - error("no support for block device PARTITION on non linux platforms\n"); - leavedos(22); -#endif - } else { - struct stat sb; - if (fstat(dp->fdesc, &sb)) { - error("calling ioctl FSTAT for PARTITION(image) %s\n", dp->dev_name); - leavedos(22); - } - dp->num_secs = sb.st_size / SECTOR_SIZE; - } - - lseek(dp->fdesc, 0, SEEK_SET); - if (RPT_SYSCALL(read(dp->fdesc, &vbr, sizeof(vbr))) != sizeof(vbr)) { - error("could not read first sector PARTITION %s\n", dp->dev_name); - leavedos(22); - } - - if (vbr.signature == VBR_SIG && - vbr.u.bpb.media_type == 0xf8 && vbr.u.bpb.num_fats == 2) { - - d_printf("VBR found, we have a filesystem on PARTITION %s\n", dp->dev_name); - - if (vbr.u.bpb.num_sectors_small == 0 && ( - vbr.u.bpb.v340_400_signature == BPB_SIG_V340 || - vbr.u.bpb.v340_400_signature == BPB_SIG_V400)) - dp->num_secs = vbr.u.bpb.v331_400_num_sectors_large; - else if (vbr.u.bpb7.num_sectors_small == 0 && ( - vbr.u.bpb7.signature == BPB_SIG_V7_SHORT || - vbr.u.bpb7.signature == BPB_SIG_V7_LONG)) - dp->num_secs = vbr.u.bpb7.num_sectors_large; - else - dp->num_secs = vbr.u.bpb.num_sectors_small; - dp->heads = vbr.u.bpb.num_heads; - dp->sectors = vbr.u.bpb.sectors_per_track; - - } else { - dp->heads = 254; - dp->sectors = 255; - } - - // Must also set these for build_pi input in setup phase - dp->start = dp->sectors; // one cylinder for mbr + alignment - dp->num_secs += dp->start; - dp->tracks = dp->num_secs / dp->sectors / dp->heads; - dp->header = 0; } -static void VBR_setup(struct disk *dp) +static void partition_setup(struct disk *dp) { - struct on_disk_vbr vbr; - uint8_t typ = 0; +#ifdef __linux__ + int part_fd, i; + unsigned char tmp_mbr[SECTOR_SIZE]; + char *hd_name; + struct on_disk_partition p; - d_printf("VBR setup for %s\n", dp->dev_name); +#define PNUM dp->part_info.number - if (dp->floppy) { - return; - } + /* PNUM is 1-based */ - lseek(dp->fdesc, 0, SEEK_SET); - if (RPT_SYSCALL(read(dp->fdesc, &vbr, sizeof(vbr))) != sizeof(vbr)) { - d_printf(" BPB could not be read\n"); + d_printf("PARTITION SETUP for %s\n", dp->dev_name); + + hd_name = strdup(dp->dev_name); + hd_name[8] = '\0'; /* i.e. /dev/hda6 -> /dev/hda */ + + part_fd = SILENT_DOS_SYSCALL(open(hd_name, O_RDONLY | O_CLOEXEC)); + if (part_fd == -1) { + if (dp->floppy) { + free(hd_name); + return; + } + PNUM = 1; + set_part_ent(dp, tmp_mbr); + tmp_mbr[0x1fe] = 0x55; + tmp_mbr[0x1ff] = 0xaa; } else { - if (vbr.u.bpb7.num_sectors_small == 0 && ( - vbr.u.bpb7.signature == BPB_SIG_V7_SHORT || - vbr.u.bpb7.signature == BPB_SIG_V7_LONG)) - typ = 0x0b; - print_bpb(&vbr.u.bpb); + (void)RPT_SYSCALL(read(part_fd, tmp_mbr, SECTOR_SIZE)); + close(part_fd); + d_printf("Using MBR from %s for PARTITION %s (part#=%d).\n", + hd_name, dp->dev_name, PNUM); } + free(hd_name); - dp->part_info.number = 1; - memcpy(&dp->part_info.mbr.code, &mbr_boot_code, sizeof(mbr_boot_code)); - dp->part_info.mbr.partition[0] = build_pi(dp); - if (typ) - dp->part_info.mbr.partition[0].OS_type = typ; - dp->part_info.mbr.signature = MBR_SIG; + /* check for logical partition, if so simulate as primary part#1 */ + if (PNUM > 4 ) { + d_printf("LOGICAL PARTITION - will be simulated as physical partition 1\n"); + PNUM = 1; + set_part_ent(dp, tmp_mbr); + } + memcpy(&p, tmp_mbr + 0x1be, sizeof(p)); + update_disk_geometry(dp, &p); - print_partition_entry(&dp->part_info.mbr.partition[0]); - print_disk_structure(dp); + /* HelpPC is wrong about the location of num_secs; it says 0xb! */ + + /* head should be zero-based, but isn't in the partition table. + * sector should be zero-based, and is. + */ +#if 0 + dp->header = -(DISK_OFFSET(dp, dp->part_info.p.start_head - 1, + dp->part_info.p.start_sector, + dp->part_info.p.start_track) + + (SECTOR_SIZE * (dp->part_info.p.num_sect_preceding - 1))); +#else + dp->start = p.num_sect_preceding; +#endif + + dp->part_info.mbr_size = SECTOR_SIZE; + dp->part_info.mbr = malloc(dp->part_info.mbr_size); + memcpy(dp->part_info.mbr, tmp_mbr, dp->part_info.mbr_size); + + /* want this to be the first & only partition on the virtual disk */ + if (PNUM != 1) + memcpy(dp->part_info.mbr + PART_INFO_START, + dp->part_info.mbr + PART_INFO_START + (PART_INFO_LEN * (PNUM - 1)), + PART_INFO_LEN); + + d_printf("beg head %d, sec %d, cyl %d = end head %d, sec %d, cyl %d\n", + p.start_head, p.start_sector, + PTBL_HL_GET(&p, start_track), + p.end_head, p.end_sector, + PTBL_HL_GET(&p, end_track)); + d_printf("pre_secs %d, num_secs %d = %x, -dp->header %ld = 0x%lx\n", + p.num_sect_preceding, p.num_sectors, + p.num_sectors, + (long) -dp->header, (unsigned long) -dp->header); + + /* XXX - make sure there is only 1 partition by zero'ing out others */ + for (i = 1; i <= 3; i++) { + d_printf("DESTROYING any traces of partition %d\n", i + 1); + memset(dp->part_info.mbr + PART_INFO_START + (i * PART_INFO_LEN), + 0, PART_INFO_LEN); + } +#endif } +/* XXX - this function constructs a primary partition table entry for the device + * dp->dev_name which should be a logical DOS partition. This is done by + * knowing the preceding sectors & length in sectors, and the geometry + * of the drive. The physical h/s/c start and end are calculated and + * put in the dp->part_info.number'th entry in the part table. + */ +#ifdef __linux__ +static void set_part_ent(struct disk *dp, unsigned char *tmp_mbr) +{ + long length; /* partition length in sectors */ + long end; /* last sector number offset */ + unsigned char *p; /* ptr to part table entry to create */ + + if (ioctl(dp->fdesc, BLKGETSIZE, &length)) { + error("calling ioctl BLKGETSIZE for PARTITION %s\n", dp->dev_name); + leavedos(22); + } +#define SECPERCYL (dp->heads * dp->sectors) +#define CYL(s) ((s)/SECPERCYL) /* 0-based */ +#define HEAD(s) (((s)%SECPERCYL)/dp->sectors) /* 0-based */ +#define SECT(s) (((s)%dp->sectors)+1) /* 1-based */ + + d_printf("SET_PART_ENT: making part table entry for device %s,\n", + dp->dev_name); + d_printf("Calculated physical start: head=%4ld sect=%4ld cyl=%4ld,\n", + HEAD(dp->start), SECT(dp->start), CYL(dp->start)); + end = dp->start+length-1; + d_printf("Calculated physical end: head=%4ld sect=%4ld cyl=%4ld.\n", + HEAD(end), SECT(end), CYL(end)); + + /* get address of where to put new part table entry */ + p = tmp_mbr + PART_INFO_START + (PART_INFO_LEN * (dp->part_info.number-1)); + + /* initialize with LBA values */ + p[1] = p[5] = 254; + p[2] = p[6] = 255; + p[3] = p[7] = 255; + p[4] = 0xe; + + p[0] = PART_BOOT; /* bootable */ + if (CYL(dp->start) <= 1023) { + p[1] = HEAD(dp->start); /* beg head */ + p[2] = SECT(dp->start) | ((CYL(dp->start) >> 2) & 0xC0); /* beg sect */ + p[3] = CYL(dp->start) & 0xFF; /* beg cyl */ + } + if (CYL(end) <= 1023) { + p[4] = (length < 32*1024*1024/SECTOR_SIZE)? 0x04 : 0x06; /* dos sysid */ + p[5] = HEAD(end); /* end head */ + p[6] = SECT(end) | ((CYL(end) >> 2) & 0xC0); /* end sect */ + p[7] = CYL(end) & 0xFF; /* end cyl */ + } + *((uint32_t *)(p+8)) = dp->start; /* pre sects */ + *((uint32_t *)(p+12)) = length; /* len sects */ +} +#endif void disk_close(void) { @@ -1037,7 +1010,7 @@ disk_close(void) if (!disks_initiated) return; /* just to be safe */ for (dp = disktab; dp < &disktab[FDISKS]; dp++) { - if (dp->removable && dp->fdesc >= 0) { + if (dp->removeable && dp->fdesc >= 0) { d_printf("DISK: Closing disk %s\n",dp->dev_name); (void) close(dp->fdesc); dp->fdesc = -1; @@ -1051,7 +1024,7 @@ static void disk_sync(void) if (!disks_initiated) return; /* just to be safe */ for (dp = disktab; dp < &disktab[FDISKS]; dp++) { - if (dp->removable && dp->fdesc >= 0) { + if (dp->removeable && dp->fdesc >= 0) { d_printf("DISK: Syncing disk %s\n",dp->dev_name); (void) fsync(dp->fdesc); } @@ -1059,9 +1032,12 @@ static void disk_sync(void) } +#ifdef __linux__ void disk_open(struct disk *dp) { + struct floppy_struct fl; + if (dp == NULL || dp->fdesc >= 0) return; @@ -1071,13 +1047,12 @@ disk_open(struct disk *dp) if (dp->type == IMAGE || dp->type == DIR_TYPE) return; -#ifdef __linux__ /* FIXME: * Why the hell was the below handling restricted to non-removeable disks? * This made opening writeprotected floppies impossible :-( * -- Hans, 990112 */ - if ( /*!dp->removable &&*/ (dp->fdesc < 0)) { + if ( /*!dp->removeable &&*/ (dp->fdesc < 0)) { if (errno == EROFS || errno == ENODEV) { dp->fdesc = DOS_SYSCALL(open(dp->dev_name, O_RDONLY | O_CLOEXEC)); if (dp->fdesc < 0) { @@ -1093,8 +1068,6 @@ disk_open(struct disk *dp) } { - struct floppy_struct fl; - #if 1 /* NOTE: Starting with linux 1.3.100 the floppy driver has changed * so that it no longer returns from the following ioctl without @@ -1124,6 +1097,7 @@ disk_open(struct disk *dp) fatalerr = 5; return; } +} d_printf("FLOPPY %s h=%d, s=%d, t=%d\n", dp->dev_name, fl.head, fl.sect, fl.track); dp->sectors = fl.sect; dp->heads = fl.head; @@ -1132,7 +1106,6 @@ disk_open(struct disk *dp) DOS_SYSCALL(ioctl(dp->fdesc, FDMSGOFF, 0)); } #endif -} void disk_close_all(void) @@ -1163,14 +1136,14 @@ disk_close_all(void) static Bit8u floppy_DOR = 0xc; -static Bit8u floppy_io_read(ioport_t port, void *arg) +static Bit8u floppy_io_read(ioport_t port) { if (port == 0x3f2) return floppy_DOR; return 0xff; } -static void floppy_io_write(ioport_t port, Bit8u value, void *arg) +static void floppy_io_write(ioport_t port, Bit8u value) { if (port == 0x3f2) { floppy_DOR = value; @@ -1207,6 +1180,8 @@ disk_init(void) io_device.handler_name = "Floppy Drive"; io_device.start_addr = 0x03F0; io_device.end_addr = 0x03F7; + io_device.irq = 6; + io_device.fd = -1; port_register_handler(io_device, 0); } @@ -1214,7 +1189,7 @@ disk_init(void) dp = &disktab[i]; dp->fdesc = -1; dp->floppy = 1; - dp->removable = 1; + dp->removeable = 1; dp->serial = 0xF10031A0 + dp->drive_num; // sernum must be unique! } @@ -1228,6 +1203,11 @@ disk_init(void) static void disk_reset2(void) { +#ifdef SILLY_GET_GEOMETRY + int s; + char buf[512], label[12]; +#endif + struct stat stbuf; struct disk *dp; int i; @@ -1260,7 +1240,7 @@ static void disk_reset2(void) } else if (S_ISDIR(stbuf.st_mode)) { d_printf("dev %s is a directory\n", dp->dev_name); dp->type = DIR_TYPE; - dp->removable = 0; + dp->removeable = 0; } else { error("dev %s is wrong type\n", dp->dev_name); config.exitearly = 1; @@ -1294,17 +1274,63 @@ static void disk_reset2(void) config.exitearly = 1; } } - dp->removable = 0; + dp->removeable = 0; /* HACK: if unspecified geometry (-1) then try to get it from kernel. May only work on WD compatible disks (MFM/RLL/ESDI/IDE). */ if (dp->sectors == -1) disk_fptrs[dp->type].autosense(dp); - /* do all the necessary dirtiness to get this disk working + /* do all the necesary dirtiness to get this disk working * (mostly for the partition type) */ disk_fptrs[dp->type].setup(dp); + + /* this really doesn't make sense...where the disk geometry + * is in reality given for the actual disk (i.e. /dev/hda) + * NOT the partition (i.e. /dev/hda1), the code below returns + * the values for the partition. + * + * don't use this code...it's stupid. + */ +#ifdef SILLY_GET_GEOMETRY + if (RPT_SYSCALL(read(dp->fdesc, buf, 512)) != 512) { + error("can't read disk info of %s\n", dp->dev_name); + config.exitearly = 1; + } + + dp->sectors = *(us *) & buf[0x18]; /* sectors per track */ + dp->heads = *(us *) & buf[0x1a]; /* heads */ + + /* for partitions <= 32MB, the number of sectors is at offset 19. + * since DOS 4.0, larger partitions have the # of sectors as a long + * at offset 32, and the number at 19 is set to 0 + */ + s = *(us *) & buf[19]; + if (!s) { + s = *(uint32_t *) &buf[32]; + d_printf("DISK: zero # secs, so DOS 4 # secs = %d\n", s); + } + s += *(us *) & buf[28]; /* + hidden sectors */ + + dp->num_secs = s; + dp->tracks = s / (dp->sectors * dp->heads); + + d_printf("DISK read_info disk %s; h=%d, s=%d, t=%d, #=%d, hid=%d\n", + dp->dev_name, dp->heads, dp->sectors, dp->tracks, + s, *(us *) & buf[28]); + + /* print serial # and label (DOS 4+ only) */ + memcpy(label, &buf[0x2b], 11); + label[11] = 0; + g_printf("VOLUME serial #: 0x%08x, LABEL: %s\n", + *(unsigned int *) &buf[39], label); + + if (s % (dp->sectors * dp->heads) != 0) { + error("incorrect track number of %s\n", dp->dev_name); + /* leavedos(28); */ + } +#endif }); } @@ -1357,13 +1383,16 @@ static void hdisk_reset(int num) int disk_is_bootable(const struct disk *dp) { + uint8_t *p; switch (dp->type) { case DIR_TYPE: return fatfs_is_bootable(dp->fatfs); case IMAGE: if (dp->floppy) return 1; - return dp->part_info.mbr.partition[dp->part_info.number - 1].bootflag == PART_BOOT; + p = dp->part_info.mbr + PART_INFO_START + + (PART_INFO_LEN * (dp->part_info.number-1)); + return (p[0] == PART_BOOT); default: // fsck on other types return 1; } @@ -1440,7 +1469,7 @@ int int13(void) * on it. We count it down in INT08 (bios.S) --SW, --Hans, --Bart */ case 0: case 2: case 3: case 5: case 10: case 11: case 0x42: case 0x43: - WRITE_BYTE(BIOS_MOTOR_TIMEOUT, 37); /* set timeout to 2 seconds */ + WRITE_BYTE(BIOS_MOTOR_TIMEOUT, 37); /* set timout to 2 seconds */ break; } } else { @@ -1528,7 +1557,7 @@ int int13(void) } else if (res & 511) { /* must read multiple of 512 bytes */ error("sector_corrupt 1, return = %d!\n", res); - HI(ax) = DERR_BADSEC; /* sector corrupt */ + HI(ax) = DERR_BADSEC; /* sector corrrupt */ CARRY; break; } @@ -1757,7 +1786,7 @@ int int13(void) HI(ax) = DERR_BADCMD; break; - case 0x0A: /* We don't have access to ECC info */ + case 0x0A: /* We dont have access to ECC info */ case 0x0B: CARRY; HI(ax) = DERR_BADCMD; /* unsupported opn. */ @@ -1783,7 +1812,7 @@ int int13(void) case 0x11: /* Recalibrate */ disk = LO(dx); if (disk < 0x80 || disk >= 0x80 + HDISKS) { - /* Controller didn't respond */ + /* Controller didnt respond */ HI(ax) = DERR_CONTROLLER; CARRY; break; @@ -1847,10 +1876,10 @@ int int13(void) case 0x16: /* get disk change status - hard - by claiming - our disks don't have a changed line we are kind of ok */ + our disks dont have a changed line we are kind of ok */ warn("int13: CHECK DISKCHANGE LINE\n"); disk = LO(dx); - if (disk >= FDISKS || disktab[disk].removable) { + if (disk >= FDISKS || disktab[disk].removeable) { d_printf("int13: DISK CHANGED\n"); CARRY; /* REG(eax)&=0xFF; @@ -1876,7 +1905,7 @@ int int13(void) track = HI(cx) + ((LO(cx) & 0xc0) << 2); sect = LO(cx) & 0x3f; d_printf("disk: set media type %x failed, %d sectors, %d tracks\n", disk, sect, track); - HI(ax) = DERR_BADCMD; /* function not available */ + HI(ax) = DERR_BADCMD; /* function not avilable */ CARRY; break; @@ -1943,7 +1972,7 @@ int int13(void) } else if (res & 511) { /* must read multiple of 512 bytes */ error("sector_corrupt 1, return = %d!\n", res); - HI(ax) = DERR_BADSEC; /* sector corrupt */ + HI(ax) = DERR_BADSEC; /* sector corrrupt */ CARRY; break; } @@ -2013,7 +2042,7 @@ int int13(void) } else if (res & 511) { /* must read multiple of 512 bytes */ error("sector_corrupt 1, return = %d!\n", res); - HI(ax) = DERR_BADSEC; /* sector corrupt */ + HI(ax) = DERR_BADSEC; /* sector corrrupt */ CARRY; break; } diff --git a/src/base/misc/dos2linux.c b/src/base/misc/dos2linux.c index 9394d9f..b96ccd7 100644 --- a/src/base/misc/dos2linux.c +++ b/src/base/misc/dos2linux.c @@ -124,7 +124,6 @@ #include #include #include -#include #ifdef __GLIBC__ #include #endif @@ -148,7 +147,6 @@ #include "../../dosext/mfs/lfn.h" #include "../../dosext/mfs/mfs.h" #include "mmio_tracing.h" -#include "spscq.h" #define com_stderr 2 @@ -167,7 +165,7 @@ char *misc_e6_options(void) return misc_dos_options; } -void misc_e6_store_options(const char *str) +void misc_e6_store_options(char *str) { size_t olen = 0; size_t slen = strlen(str); @@ -188,48 +186,50 @@ void misc_e6_store_options(const char *str) static int pty_fd; static int pty_done; static int cbrk; -static sem_t rd_sem; -static pthread_t reader; -static void *queue; - -static void *rd_thread(void *arg) -{ - while (1) { - sem_wait(&rd_sem); - while (1) { - void *ptr; - unsigned len; - ssize_t rd; - - ptr = spscq_write_area(queue, &len); - rd = read(pty_fd, ptr, len); - if (rd <= 0) - break; - spscq_commit_write(queue, rd); - } - __atomic_store_n(&pty_done, 1, __ATOMIC_RELEASE); - } - return NULL; -} +static sem_t *pty_sem; +static char sem_name[256]; static void pty_thr(void) { -#define MAX_LEN (1024+1) - char buf[MAX_LEN]; - int rd, wr; + char buf[128]; + fd_set rfds; + struct timeval tv; + int retval, rd, wr; struct char_set_state kstate; struct char_set_state dstate; init_charset_state(&kstate, trconfig.keyb_charset); init_charset_state(&dstate, trconfig.dos_charset); - sem_post(&rd_sem); while (1) { - rd = spscq_read(queue, buf, sizeof(buf) - 1); - if (rd > 0) { + rd = wr = 0; + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&rfds); + FD_SET(pty_fd, &rfds); + retval = RPT_SYSCALL(select(pty_fd + 1, &rfds, NULL, NULL, &tv)); + switch (retval) { + case -1: + g_printf("run_unix_command(): select error %s\n", strerror(errno)); + pty_done++; + break; + case 0: + break; + default: + /* one of the pipes has data, or EOF */ + rd = RPT_SYSCALL(read(pty_fd, buf, sizeof(buf) - 1)); + switch (rd) { + case -1: + g_printf("run_unix_command(): read error %s\n", strerror(errno)); + /* no break */ + case 0: + pty_done++; + break; + default: { int rc; const char *p = buf; buf[rd] = 0; while (*p) { + #define MAX_LEN 256 t_unicode uni[MAX_LEN]; const t_unicode *u = uni; char buf2[MAX_LEN * MB_LEN_MAX]; @@ -243,11 +243,15 @@ static void pty_thr(void) break; com_doswritecon(buf2, rc); } - } - if (__atomic_load_n(&pty_done, __ATOMIC_ACQUIRE)) + break; + } + } break; + } + if (pty_done) + return; - wr = com_dosreadcon(buf, sizeof(buf) - 1); + wr = com_dosreadcon(buf, sizeof(buf)); if (wr > 0) write(pty_fd, buf, wr); @@ -258,30 +262,47 @@ static void pty_thr(void) cleanup_charset_state(&dstate); } -void dos2tty_init(void) +int dos2tty_init(void) { pty_fd = posix_openpt(O_RDWR); if (pty_fd == -1) { error("openpt failed %s\n", strerror(errno)); - return; + return -1; } unlockpt(pty_fd); - sem_init(&rd_sem, 0, 0); - queue = spscq_init(1024 * 64); // 64K queue - pthread_create(&reader, NULL, rd_thread, queue); -#if defined(HAVE_PTHREAD_SETNAME_NP) && defined(__GLIBC__) - pthread_setname_np(reader, "dosemu: ttyrd"); -#endif + snprintf(sem_name, sizeof(sem_name), "/dosemu_pty_sem_%i", getpid()); + pty_sem = sem_open(sem_name, O_CREAT, S_IRUSR | S_IWUSR, 0); + if (!pty_sem) + { + error("sem_open failed %s\n", strerror(errno)); + return -1; + } + return 0; } void dos2tty_done(void) { - pthread_cancel(reader); - pthread_join(reader, NULL); - spscq_done(queue); close(pty_fd); - sem_destroy(&rd_sem); + sem_close(pty_sem); + sem_unlink(sem_name); +} + +static int dos2tty_open(void) +{ + int err, pts_fd; + err = grantpt(pty_fd); + if (err) { + error("grantpt failed: %s\n", strerror(errno)); + return err; + } + pts_fd = open(ptsname(pty_fd), O_RDWR | O_CLOEXEC); + if (pts_fd == -1) { + error("pts open failed: %s\n", strerror(errno)); + return -1; + } + sem_post(pty_sem); + return pts_fd; } static void dos2tty_start(void) @@ -295,8 +316,8 @@ static void dos2tty_start(void) } while (rd > 0); pty_done = 0; /* must run with interrupts enabled to read keypresses */ - assert(!isset_IF()); set_IF(); + sem_wait(pty_sem); pty_thr(); } @@ -306,10 +327,64 @@ static void dos2tty_stop(void) com_setcbreak(cbrk); } -static int do_wait_cmd(pid_t pid) +static int do_run_cmd(const char *path, int argc, char * const *argv, + int use_stdin, int close_from) { - int status, retval; + sigset_t set, oset; + int pid, status, retval, wt; + int pts_fd; + struct timespec to = { 0, 0 }; + signal_block_async_nosig(&oset); + sigprocmask(SIG_SETMASK, NULL, &set); + /* fork child */ + switch ((pid = fork())) { + case -1: /* failed */ + sigprocmask(SIG_SETMASK, &oset, NULL); + g_printf("run_unix_command(): fork() failed\n"); + return -1; + case 0: /* child */ + priv_drop(); + setsid(); // will have ctty + /* open pts _after_ setsid, or it won't became a ctty */ + pts_fd = dos2tty_open(); + if (pts_fd == -1) { + error("run_unix_command(): open pts failed %s\n", strerror(errno)); + _exit(EXIT_FAILURE); + } + close(0); + close(1); + close(2); + if (use_stdin) + dup(pts_fd); + else + open("/dev/null", O_RDONLY); + dup(pts_fd); + dup(pts_fd); + close(pts_fd); + close(pty_fd); +#ifdef HAVE_LIBBSD + if (close_from != -1) + closefrom(close_from); +#else +#warning no closefrom() +#endif + /* close signals, then unblock */ + signal_done(); + /* flush pending signals */ + do { + wt = sigtimedwait(&set, NULL, &to); + } while (wt != -1); + sigprocmask(SIG_SETMASK, &oset, NULL); + + retval = execve(path, argv, dosemu_envp); /* execute command */ + error("exec failed: %s\n", strerror(errno)); + _exit(retval); + break; + } + sigprocmask(SIG_SETMASK, &oset, NULL); + + assert(!isset_IF()); dos2tty_start(); while ((retval = waitpid(pid, &status, WNOHANG)) == 0) coopth_wait(); @@ -322,11 +397,10 @@ static int do_wait_cmd(pid_t pid) return WEXITSTATUS(status); } -int run_unix_command(int argc, const char **argv, int bg) +int run_unix_command(int argc, char **argv) { const char *path; char *p; - pid_t pid; path = findprog(argv[0], getenv("PATH")); if (!path) { @@ -353,22 +427,17 @@ int run_unix_command(int argc, const char **argv, int bg) } g_printf("UNIX: run %s, %i args\n", path, argc); - pid = run_external_command(path, argc, argv, !bg, -1, pty_fd); - if (bg) { - sigchld_enable_cleanup(pid); - return 0; - } - return do_wait_cmd(pid); + return do_run_cmd(path, argc, argv, 1, -1); } /* no PATH searching, no arguments allowed, no stdin, no inherited fds */ -int run_unix_secure(const char *prg) +int run_unix_secure(char *prg) { char *path; - const char *argv[2]; - pid_t pid; + char *argv[2]; + int ret; - path = assemble_path(dosemu_exec_dir_path, prg); + path = assemble_path(DOSEMULIBEXEC_DEFAULT, prg); if (!exists_file(path)) { com_printf("unix: %s not found\n", path); free(path); @@ -377,9 +446,9 @@ int run_unix_secure(const char *prg) argv[0] = prg; argv[1] = NULL; /* no args allowed */ g_printf("UNIX: run_secure %s '%s'\n", path, prg); - pid = run_external_command(path, 1, argv, 0, STDERR_FILENO + 1, pty_fd); + ret = do_run_cmd(path, 1, argv, 0, STDERR_FILENO + 1); free(path); - return do_wait_cmd(pid); + return ret; } /* @@ -387,8 +456,7 @@ int run_unix_secure(const char *prg) * of X/SDL and the VGA emulation during a DOSEMU session. * It is used by the xmode.exe program that comes with DOSEMU. */ -int change_config(unsigned item, void *buf, int grab_active, - int kbd_grab_active, int clip_mode) +int change_config(unsigned item, void *buf, int grab_active, int kbd_grab_active) { static char title_emuname [TITLE_EMUNAME_MAXLEN] = {0}; static char title_appname [TITLE_APPNAME_MAXLEN] = {0}; @@ -431,20 +499,15 @@ int change_config(unsigned item, void *buf, int grab_active, strcat (title, "[background pause] "); } - if (grab_active || kbd_grab_active || clip_mode) { + if (grab_active || kbd_grab_active) { strcat(title, "["); if (kbd_grab_active) { strcat(title, "keyboard"); - if (grab_active || clip_mode) + if (grab_active) strcat(title, "+"); } - if (grab_active) { + if (grab_active) strcat(title, "mouse"); - if (clip_mode) - strcat(title, "+"); - } - if (clip_mode) - strcat(title, "clip"); strcat(title, " grab] "); } @@ -509,8 +572,6 @@ int change_config(unsigned item, void *buf, int grab_active, know that regular reads and writes are valid. Initialize with invalid entries */ static dosaddr_t unprotected_page_cache[PAGE_SIZE] = {0xffffffff}; -/* software TLB to translate unprotected pages to UNIX addresses */ -static unsigned char *unprotected_page_unixaddr_tlb[PAGE_SIZE] = {}; void invalidate_unprotected_page_cache(dosaddr_t addr, int len) { @@ -520,9 +581,7 @@ void invalidate_unprotected_page_cache(dosaddr_t addr, int len) unprotected_page_cache[page & (PAGE_SIZE-1)] = 0xffffffff; } -/* returns the host address if it's definitely unprotected, - otherwise NULL */ -static inline void *unprotected_dosaddr_to_unixaddr(dosaddr_t addr, int len) +static inline int mem_likely_protected(dosaddr_t addr, int len) { /* hash = low 12 bits of page number, add len-1 to fail on boundaries. This gives no clashes if all addresses are under 16MB and >99.99% hit @@ -532,19 +591,12 @@ static inline void *unprotected_dosaddr_to_unixaddr(dosaddr_t addr, int len) this technique. */ int hash = (addr >> PAGE_SHIFT) & (PAGE_SIZE-1); - if (unprotected_page_cache[hash] == ((addr + len - 1) & _PAGE_MASK)) - return &unprotected_page_unixaddr_tlb[hash][addr & (PAGE_SIZE-1)]; - else - return NULL; + return unprotected_page_cache[hash] != ((addr + len - 1) & PAGE_MASK); } -/* marks the page as unprotected in the cache, and add the host address to - the TLB */ -static inline void set_unprotected_page(dosaddr_t addr, void *uaddr) +static inline void set_unprotected_page(dosaddr_t addr) { - int hash = (addr >> PAGE_SHIFT) & (PAGE_SIZE-1); - unprotected_page_cache[hash] = addr & _PAGE_MASK; - unprotected_page_unixaddr_tlb[hash] = (void *)((uintptr_t)uaddr & _PAGE_MASK); + unprotected_page_cache[(addr >> PAGE_SHIFT) & (PAGE_SIZE-1)] = addr & PAGE_MASK; } void default_sim_pagefault_handler(dosaddr_t addr, int err, uint32_t op, int len) @@ -558,7 +610,7 @@ void default_sim_pagefault_handler(dosaddr_t addr, int err, uint32_t op, int len leavedos_main(1); } -static void check_read_pagefault(dosaddr_t addr, void *uaddr, +static void check_read_pagefault(dosaddr_t addr, sim_pagefault_handler_t handler) { if (addr >= LOWMEM_SIZE + HMASIZE) { @@ -569,30 +621,26 @@ static void check_read_pagefault(dosaddr_t addr, void *uaddr, if (!dpmi_write_access(addr)) return; } - if (!e_querymprot(addr) && !memcheck_is_rom(addr)) - set_unprotected_page(addr, uaddr); + set_unprotected_page(addr); } uint8_t do_read_byte(dosaddr_t addr, sim_pagefault_handler_t handler) { - void *uaddr = unprotected_dosaddr_to_unixaddr(addr, 1); - if (!uaddr) { + if (mem_likely_protected(addr, 1)) { /* use vga_write_access instead of vga_read_access here to avoid adding read-only addresses to the cache */ if (vga_write_access(addr)) return vga_read(addr); if (config.mmio_tracing && mmio_check(addr)) return mmio_trace_byte(addr, READ_BYTE(addr), MMIO_READ); - uaddr = dosaddr_to_unixaddr(addr); - check_read_pagefault(addr, uaddr, handler); + check_read_pagefault(addr, handler); } - return UNIX_READ_BYTE(uaddr); + return READ_BYTE(addr); } uint16_t do_read_word(dosaddr_t addr, sim_pagefault_handler_t handler) { - void *uaddr = unprotected_dosaddr_to_unixaddr(addr, 2); - if (!uaddr) { + if (mem_likely_protected(addr, 2)) { if (((addr+1) & (PAGE_SIZE-1)) == 0) /* split if spanning a page boundary */ return do_read_byte(addr, handler) | @@ -601,16 +649,14 @@ uint16_t do_read_word(dosaddr_t addr, sim_pagefault_handler_t handler) return vga_read_word(addr); if (config.mmio_tracing && mmio_check(addr)) return mmio_trace_word(addr, READ_WORD(addr), MMIO_READ); - uaddr = dosaddr_to_unixaddr(addr); - check_read_pagefault(addr, uaddr, handler); + check_read_pagefault(addr, handler); } - return UNIX_READ_WORD(uaddr); + return READ_WORD(addr); } uint32_t do_read_dword(dosaddr_t addr, sim_pagefault_handler_t handler) { - void *uaddr = unprotected_dosaddr_to_unixaddr(addr, 4); - if (!uaddr) { + if (mem_likely_protected(addr, 4)) { if (((addr+3) & (PAGE_SIZE-1)) < 3) return do_read_word(addr, handler) | ((uint32_t)do_read_word(addr+2, handler) << 16); @@ -618,10 +664,9 @@ uint32_t do_read_dword(dosaddr_t addr, sim_pagefault_handler_t handler) return vga_read_dword(addr); if (config.mmio_tracing && mmio_check(addr)) return mmio_trace_dword(addr, READ_DWORD(addr), MMIO_READ); - uaddr = dosaddr_to_unixaddr(addr); - check_read_pagefault(addr, uaddr, handler); + check_read_pagefault(addr, handler); } - return UNIX_READ_DWORD(uaddr); + return READ_DWORD(addr); } uint64_t do_read_qword(dosaddr_t addr, sim_pagefault_handler_t handler) @@ -630,22 +675,20 @@ uint64_t do_read_qword(dosaddr_t addr, sim_pagefault_handler_t handler) ((uint64_t)do_read_dword(addr+4, handler) << 32); } -static int check_write_pagefault(dosaddr_t addr, void *uaddr, uint32_t op, int len, +static int check_write_pagefault(dosaddr_t addr, uint32_t op, int len, sim_pagefault_handler_t handler) { if (addr >= LOWMEM_SIZE + HMASIZE && !dpmi_write_access(addr)) { handler(addr, 6 + dpmi_read_access(addr), op, len); return 1; } - if (!e_querymprot(addr) && !memcheck_is_rom(addr)) - set_unprotected_page(addr, uaddr); + set_unprotected_page(addr); return 0; } void do_write_byte(dosaddr_t addr, uint8_t byte, sim_pagefault_handler_t handler) { - void *uaddr = unprotected_dosaddr_to_unixaddr(addr, 1); - if (!uaddr) { + if (mem_likely_protected(addr, 1)) { if (vga_write_access(addr)) { vga_write(addr, byte); @@ -653,22 +696,18 @@ void do_write_byte(dosaddr_t addr, uint8_t byte, sim_pagefault_handler_t handler } if (config.mmio_tracing && mmio_check(addr)) mmio_trace_byte(addr, byte, MMIO_WRITE); - e_invalidate(addr, 1); - uaddr = dosaddr_to_unixaddr(addr); - if (check_write_pagefault(addr, uaddr, byte, 1, handler)) + if (check_write_pagefault(addr, byte, 1, handler)) return; } - UNIX_WRITE_BYTE(uaddr, byte); + WRITE_BYTE(addr, byte); } void do_write_word(dosaddr_t addr, uint16_t word, sim_pagefault_handler_t handler) { - void *uaddr = unprotected_dosaddr_to_unixaddr(addr, 2); - if (!uaddr) { + if (mem_likely_protected(addr, 2)) { if (((addr+1) & (PAGE_SIZE-1)) == 0) { do_write_byte(addr, word & 0xff, handler); do_write_byte(addr+1, word >> 8, handler); - return; } if (vga_write_access(addr)) { vga_write_word(addr, word); @@ -676,22 +715,18 @@ void do_write_word(dosaddr_t addr, uint16_t word, sim_pagefault_handler_t handle } if (config.mmio_tracing && mmio_check(addr)) mmio_trace_word(addr, word, MMIO_WRITE); - e_invalidate(addr, 2); - uaddr = dosaddr_to_unixaddr(addr); - if (check_write_pagefault(addr, uaddr, word, 2, handler)) + if (check_write_pagefault(addr, word, 2, handler)) return; } - UNIX_WRITE_WORD(uaddr, word); + WRITE_WORD(addr, word); } void do_write_dword(dosaddr_t addr, uint32_t dword, sim_pagefault_handler_t handler) { - void *uaddr = unprotected_dosaddr_to_unixaddr(addr, 4); - if (!uaddr) { + if (mem_likely_protected(addr, 4)) { if (((addr+3) & (PAGE_SIZE-1)) < 3) { do_write_word(addr, dword & 0xffff, handler); do_write_word(addr+2, dword >> 16, handler); - return; } if (vga_write_access(addr)) { vga_write_dword(addr, dword); @@ -699,12 +734,10 @@ void do_write_dword(dosaddr_t addr, uint32_t dword, sim_pagefault_handler_t hand } if (config.mmio_tracing && mmio_check(addr)) mmio_trace_dword(addr, dword, MMIO_WRITE); - e_invalidate(addr, 4); - uaddr = dosaddr_to_unixaddr(addr); - if (check_write_pagefault(addr, uaddr, dword, 4, handler)) + if (check_write_pagefault(addr, dword, 4, handler)) return; } - UNIX_WRITE_DWORD(uaddr, dword); + WRITE_DWORD(addr, dword); } void do_write_qword(dosaddr_t addr, uint64_t qword, sim_pagefault_handler_t handler) @@ -760,7 +793,7 @@ void memcpy_2unix(void *dest, dosaddr_t src, size_t n) else while (n) { /* EMS can produce the non-contig mapping. We need to iterate it * page-by-page or use a separate alias window... */ - dosaddr_t bound = (src & _PAGE_MASK) + PAGE_SIZE; + dosaddr_t bound = (src & PAGE_MASK) + PAGE_SIZE; size_t to_copy = _min(n, bound - src); MEMCPY_2UNIX(dest, src, to_copy); src += to_copy; @@ -776,7 +809,7 @@ void memcpy_2dos(dosaddr_t dest, const void *src, size_t n) else { e_invalidate(dest, n); while (n) { - dosaddr_t bound = (dest & _PAGE_MASK) + PAGE_SIZE; + dosaddr_t bound = (dest & PAGE_MASK) + PAGE_SIZE; size_t to_copy = _min(n, bound - dest); MEMCPY_2DOS(dest, src, to_copy); src += to_copy; @@ -793,7 +826,7 @@ void memset_dos(dosaddr_t dest, char ch, size_t n) else { e_invalidate(dest, n); while (n) { - dosaddr_t bound = (dest & _PAGE_MASK) + PAGE_SIZE; + dosaddr_t bound = (dest & PAGE_MASK) + PAGE_SIZE; size_t to_copy = _min(n, bound - dest); MEMSET_DOS(dest, ch, to_copy); dest += to_copy; @@ -814,8 +847,8 @@ void memmove_dos2dos(dosaddr_t dest, dosaddr_t src, size_t n) else { e_invalidate(dest, n); while (n) { - dosaddr_t bound1 = (src & _PAGE_MASK) + PAGE_SIZE; - dosaddr_t bound2 = (dest & _PAGE_MASK) + PAGE_SIZE; + dosaddr_t bound1 = (src & PAGE_MASK) + PAGE_SIZE; + dosaddr_t bound2 = (dest & PAGE_MASK) + PAGE_SIZE; size_t to_copy1 = _min(bound1 - src, bound2 - dest); size_t to_copy = _min(n, to_copy1); MEMMOVE_DOS2DOS(dest, src, to_copy); @@ -836,8 +869,8 @@ void memcpy_dos2dos(unsigned dest, unsigned src, size_t n) else { e_invalidate(dest, n); while (n) { - dosaddr_t bound1 = (src & _PAGE_MASK) + PAGE_SIZE; - dosaddr_t bound2 = (dest & _PAGE_MASK) + PAGE_SIZE; + dosaddr_t bound1 = (src & PAGE_MASK) + PAGE_SIZE; + dosaddr_t bound2 = (dest & PAGE_MASK) + PAGE_SIZE; size_t to_copy1 = _min(bound1 - src, bound2 - dest); size_t to_copy = _min(n, to_copy1); MEMCPY_DOS2DOS(dest, src, to_copy); @@ -995,7 +1028,7 @@ void call_msdos(void) do_int_call_back(0x21); } -int com_doswrite(int dosfilefd, const char *buf32, u_short size) +int com_doswrite(int dosfilefd, char *buf32, u_short size) { char *s; u_short int23_seg, int23_off; @@ -1084,12 +1117,46 @@ int com_dosreadcon(char *buf32, u_short size) int com_doswritecon(const char *buf32, u_short size) { - return com_doswrite(STDOUT_FILENO, buf32, size); + u_short rd; + + if (!size) + return 0; + pre_msdos(); + for (rd = 0; rd < size; rd++) { + LWORD(eax) = 0x600; + LO(dx) = buf32[rd]; + call_msdos(); + } + post_msdos(); + return rd; } int com_dosprint(const char *buf32) { - return com_doswritecon(buf32, strlen(buf32)); + char *s; + u_short int23_seg, int23_off, size; + size = strlen(buf32); + if (!size) return 0; + com_errno = 8; + s = lowmem_alloc(size); + if (!s) return -1; + memcpy(s, buf32, size); + pre_msdos(); + LWORD(ebx) = STDOUT_FILENO; + LWORD(ecx) = size; + SREG(ds) = DOSEMU_LMHEAP_SEG; + LWORD(edx) = DOSEMU_LMHEAP_OFFS_OF(s); + HI(ax) = 0x40; + /* write() can be interrupted with ^C. Therefore we set int0x23 here + * so that even in this case it will return to the proper place. */ + int23_seg = ISEG(0x23); + int23_off = IOFF(0x23); + SETIVEC(0x23, CBACK_SEG, CBACK_OFF); + call_msdos(); /* call MSDOS */ + SETIVEC(0x23, int23_seg, int23_off); /* restore 0x23 ASAP */ + post_msdos(); + lowmem_free(s); + return size; } int com_dosopen(const char *name, int flags) @@ -1206,250 +1273,3 @@ int com_setcbreak(int on) post_msdos(); return old_b; } - -/* Output a character to the screen. */ -void char_out(unsigned char ch, int page) -{ - struct vm86_regs saved_regs = REGS; - HI(ax) = 0xe; - LO(ax) = ch; - HI(bx) = page; - LO(bx) = 7; - do_int_call_back(0x10); - REGS = saved_regs; -} - -unsigned char sdb_drive_letter(sdb_t sdb) -{ - return (*(u_char *)&sdb[sdb_drive_letter_off]); -} -char *sdb_template_name(sdb_t sdb) -{ - return ((char *)&sdb[sdb_template_name_off]); -} -char *sdb_template_ext(sdb_t sdb) -{ - return ((char *)&sdb[sdb_template_ext_off]); -} -unsigned char sdb_attribute(sdb_t sdb) -{ - return (*(u_char *)&sdb[sdb_attribute_off]); -} -unsigned short sdb_dir_entry(sdb_t sdb) -{ - return (*(u_short *)&sdb[sdb_dir_entry_off]); -} -unsigned short sdb_p_cluster(sdb_t sdb) -{ - return (*(u_short *)&sdb[sdb_p_cluster_off]); -} -char *sdb_file_name(sdb_t sdb) -{ - return ((char *)&sdb[sdb_file_name_off]); -} -char *sdb_file_ext(sdb_t sdb) -{ - return ((char *)&sdb[sdb_file_ext_off]); -} -unsigned char sdb_file_attr(sdb_t sdb) -{ - return (*(u_char *)&sdb[sdb_file_attr_off]); -} -unsigned short sdb_file_time(sdb_t sdb) -{ - return (*(u_short *)&sdb[sdb_file_time_off]); -} -unsigned short sdb_file_date(sdb_t sdb) -{ - return (*(u_short *)&sdb[sdb_file_date_off]); -} -unsigned short sdb_file_st_cluster(sdb_t sdb) -{ - return (*(u_short *)&sdb[sdb_file_st_cluster_off]); -} -Bit32u sdb_file_size(sdb_t sdb) -{ - return (*(u_int *)&sdb[sdb_file_size_off]); -} - -unsigned short sft_handle_cnt(sft_t sft) -{ - return (*(u_short *)&sft[sft_handle_cnt_off]); -} -unsigned short sft_open_mode(sft_t sft) -{ - return (*(u_short *)&sft[sft_open_mode_off]); -} -unsigned char sft_attribute_byte(sft_t sft) -{ - return (*(u_char *)&sft[sft_attribute_byte_off]); -} -unsigned short sft_device_info(sft_t sft) -{ - return (*(u_short *)&sft[sft_device_info_off]); -} -Bit32u sft_dev_drive_ptr(sft_t sft) -{ - return (*(u_int *)&sft[sft_dev_drive_ptr_off]); -} -unsigned short sft_start_cluster(sft_t sft) -{ - return (*(u_short *)&sft[sft_start_cluster_off]); -} -unsigned short sft_time(sft_t sft) -{ - return (*(u_short *)&sft[sft_time_off]); -} -unsigned short sft_date(sft_t sft) -{ - return (*(u_short *)&sft[sft_date_off]); -} -Bit32u sft_size(sft_t sft) -{ - return (*(u_int *)&sft[sft_size_off]); -} -Bit32u sft_position(sft_t sft) -{ - return (*(u_int *)&sft[sft_position_off]); -} -unsigned short sft_rel_cluster(sft_t sft) -{ - return (*(u_short *)&sft[sft_rel_cluster_off]); -} -unsigned short sft_abs_cluster(sft_t sft) -{ - return (*(u_short *)&sft[sft_abs_cluster_off]); -} -unsigned short sft_directory_sector(sft_t sft) -{ - return (*(u_short *)&sft[sft_directory_sector_off]); -} -unsigned char sft_directory_entry(sft_t sft) -{ - return (*(u_char *)&sft[sft_directory_entry_off]); -} -char *sft_name(sft_t sft) -{ - return ( (char *)&sft[sft_name_off]); -} -char *sft_ext(sft_t sft) -{ - return ( (char *)&sft[sft_ext_off]); -} -unsigned short sft_fd(sft_t sft) -{ - return (*(u_short *)&sft[sft_fd_off]); -} - -dosaddr_t sda_current_dta(sda_t sda) -{ - if (!sda) - return 0; - return (FARADDR((far_t *)&sda[sda_current_dta_off])); -} -unsigned short sda_error_code(sda_t sda) -{ - if (!sda) - return 0; - return (*(u_short *)&sda[4]); -} -unsigned short sda_cur_psp(sda_t sda) -{ - if (!sda) - return 0; - return (*(u_short *)&sda[sda_cur_psp_off]); -} -unsigned char sda_cur_drive(sda_t sda) -{ - if (!sda) - return 0; - return (*(u_char *)&sda[sda_cur_drive_off]); -} -char *sda_filename1(sda_t sda) -{ - if (!sda) - return NULL; - return ((char *)&sda[sda_filename1_off]); -} -char *sda_filename2(sda_t sda) -{ - if (!sda) - return NULL; - return ((char *)&sda[sda_filename2_off]); -} -sdb_t sda_sdb(sda_t sda) -{ - if (!sda) - return NULL; - return ((sdb_t )&sda[sda_sdb_off]); -} -cds_t sda_cds(sda_t sda) -{ - if (!sda) - return NULL; - return ((cds_t)(FARPTR((far_t *)&sda[sda_cds_off]))); -} -unsigned char sda_search_attribute(sda_t sda) -{ - if (!sda) - return 0; - return (*(u_char *)&sda[sda_search_attribute_off]); -} -unsigned char sda_open_mode(sda_t sda) -{ - if (!sda) - return 0; - return (*(u_char *)&sda[sda_open_mode_off]); -} -sdb_t sda_rename_source(sda_t sda) -{ - if (!sda) - return NULL; - return ((sdb_t )&sda[sda_rename_source_off]); -} -char *sda_user_stack(sda_t sda) -{ - if (!sda) - return NULL; - return ((char *)(FARPTR((far_t *)&sda[sda_user_stack_off]))); -} - -/* - * Data for extended open/create operations, DOS 4 or greater: - */ -unsigned short sda_ext_act(sda_t sda) -{ - return (*(u_short *)&sda[sda_ext_act_off]); -} -unsigned short sda_ext_attr(sda_t sda) -{ - return (*(u_short *)&sda[sda_ext_attr_off]); -} -unsigned short sda_ext_mode(sda_t sda) -{ - return (*(u_short *)&sda[sda_ext_mode_off]); -} - -unsigned short psp_parent_psp(psp_t psp) -{ - return (*(u_short *)&psp[0x16]); -} -char *psp_handles(psp_t psp) -{ - return ((char *)(FARPTR((far_t *)&psp[0x34]))); -} - -far_t lol_dpbfarptr(lol_t lol) -{ - return (rFAR_FARt(READ_DWORD((lol)+lol_dpbfarptr_off))); -} -far_t lol_cdsfarptr(lol_t lol) -{ - return (rFAR_FARt(READ_DWORD((lol)+lol_cdsfarptr_off))); -} -char lol_last_drive(lol_t lol) -{ - return (READ_BYTE((lol)+lol_last_drive_off)); -} -// lol_nuldev(lol_t lol) ((lol)+lol_nuldev_off) -// lol_njoined(lol_t lol) ((lol)+lol_njoined_off) diff --git a/src/base/misc/fatfs.c b/src/base/misc/fatfs.c index 150856d..2864a89 100644 --- a/src/base/misc/fatfs.c +++ b/src/base/misc/fatfs.c @@ -9,7 +9,7 @@ * DANG_BEGIN_MODULE * * REMARK - * FAT filesystem emulation (read-only) for DOSEMU. + * FAT filesytem emulation (read-only) for DOSEMU. * /REMARK * DANG_END_MODULE * @@ -62,9 +62,6 @@ #include #include #include /* RxDOS.3 lsv uses types */ -#ifdef HAVE_LIBBSD -#include -#endif #include "int.h" #include "disks.h" @@ -298,9 +295,7 @@ void fatfs_init(struct disk *dp) memcpy(f->sfiles, i_sfiles, sizeof(f->sfiles)); strcpy(config_sys, real_config_sys); if (config.emusys) { - char *p = strrchr(config_sys, '.'); - if (p && p - config_sys <= 8) - strlcpy(p + 1, config.emusys, 4); + strcpy(strrchr(config_sys, '.') + 1, config.emusys); strupperDOS(config_sys); } for (i = 0; i < sys_hooks_used; i++) @@ -912,6 +907,7 @@ static void set_vol_and_len(fatfs_t *f, unsigned oi) void scan_dir(fatfs_t *f, unsigned oi) { obj_t *o = f->obj + oi; + struct stat sb; char *s, *name; unsigned u; int i; @@ -969,20 +965,18 @@ void scan_dir(fatfs_t *f, unsigned oi) } else { char *buf, *buf_ptr; int fd, size; - struct stat sb; if (sys_type == MS_D) { s = full_name(f, oi, dlist[0]->d_name); /* io.sys */ if (s && stat(s, &sb) == 0) { if((fd = open(s, O_RDONLY)) != -1) { buf = malloc(sb.st_size + 1); - assert(sb.st_size < PTRDIFF_MAX); // fixes gcc warning size = read(fd, buf, sb.st_size); if (size > 0) { if(buf[0] == 'M' && buf[1] == 'Z') { /* MS-DOS >= 7 */ sys_type = NEWMSD_D; } else { /* see if it has a version string */ - buf[size] = '\0'; + buf[size] = 0; for (buf_ptr=buf;buf_ptr < buf + size; buf_ptr++) { if(strncmp(buf_ptr, "NEC IO.SYS for MS-DOS", 21)==0) { sys_type = NECMSD_D; @@ -1023,7 +1017,6 @@ void scan_dir(fatfs_t *f, unsigned oi) if (s && stat(s, &sb) == 0) { if((fd = open(s, O_RDONLY)) != -1) { buf = malloc(sb.st_size + 1); - assert(sb.st_size < PTRDIFF_MAX); // fixes gcc warning size = read(fd, buf, sb.st_size); if (size > 0) { buf[size] = 0; @@ -1618,7 +1611,7 @@ void mimic_boot_blk(void) uint16_t seg; uint16_t ofs; - fatfs_t *f = get_fat_fs_by_drive(LO(dx)); + fatfs_t *f = get_fat_fs_by_drive(HI(ax)); if (!f || (idx = sys_file_idx(f->obj[1].name, f)) == -1) { error("BOOT-helper requested, but no systemfile available\n"); @@ -1911,7 +1904,7 @@ void build_boot_blk(fatfs_t *f, unsigned char *b) /* boot loading is done by DOSEMU-HELPER with mimic_boot_blk() function */ b[0x40] = 0xb8; /* mov ax,0fdh */ b[0x41] = DOS_HELPER_BOOTSECT; - b[0x42] = 0; + b[0x42] = f->drive_num; b[0x43] = 0xcd; /* int 0e6h */ b[0x44] = DOS_HELPER_INT; diff --git a/src/base/misc/fatfs.h b/src/base/misc/fatfs.h index f72017a..f7fd2ec 100644 --- a/src/base/misc/fatfs.h +++ b/src/base/misc/fatfs.h @@ -28,7 +28,6 @@ struct sys_dsc { #define FLG_COMCOM32 2 #define FLG_ISDIR 4 #define FLG_NOREAD 8 -#define FLG_COMCOM64 0x10 void fatfs_set_sys_hook(void (*hook)(struct sys_dsc *, fatfs_t *)); diff --git a/src/base/misc/hma.c b/src/base/misc/hma.c index 48d282b..21d259f 100644 --- a/src/base/misc/hma.c +++ b/src/base/misc/hma.c @@ -24,14 +24,15 @@ #define HMAAREA 0x100000 +unsigned char *ext_mem_base = NULL; int a20; -static void HMA_MAP(int HMA) +void HMA_MAP(int HMA) { int ret; /* destroy simx86 memory protections first */ e_invalidate_full(HMAAREA, HMASIZE); - /* Note: MAPPING_HMA is magic, don't be confused by src==dst==HMAAREA here */ + /* Note: MAPPING_HMA is magic, dont be confused by src==dst==HMAAREA here */ off_t src = HMA ? HMAAREA : 0; x_printf("Entering HMA_MAP with HMA=%d\n", HMA); ret = alias_mapping(MAPPING_HMA, HMAAREA, HMASIZE, @@ -41,13 +42,12 @@ static void HMA_MAP(int HMA) HMAAREA, strerror(errno)); leavedos(47); } - x_printf("HMA: %smapped\n", HMA ? "" : "un"); + x_printf("HMA: mapped\n"); } -void set_a20(int enableHMA) +void +set_a20(int enableHMA) { - if (!config.hma) - return; if (a20 == enableHMA) { g_printf("WARNING: redundant %s of A20!\n", enableHMA ? "enabling" : "disabling"); @@ -69,14 +69,19 @@ void HMA_init(void) int ret = alias_mapping(MAPPING_HMA, HMAAREA, HMASIZE, PROT_READ | PROT_WRITE | PROT_EXEC, LOWMEM(0)); if (ret == -1) { - error("HMA: Mapping HMA to HMAAREA %#x unsuccessful: %s\n", + x_printf("HMA: Mapping HMA to HMAAREA %#x unsuccessful: %s\n", HMAAREA, strerror(errno)); config.exitearly = 1; return; } a20 = 0; - memcheck_addtype('H', "HMA"); - memcheck_reserve('H', LOWMEM_SIZE, HMASIZE); + if (config.ext_mem) { + ext_mem_base = mmap_mapping(MAPPING_EXTMEM | MAPPING_SCRATCH, -1, + EXTMEM_SIZE, PROT_READ | PROT_WRITE); + x_printf("Ext.Mem of size 0x%x at %p\n", EXTMEM_SIZE, ext_mem_base); + memcheck_addtype('x', "Extended memory (HMA+XMS)"); + memcheck_reserve('x', LOWMEM_SIZE, HMASIZE + EXTMEM_SIZE); + } } @@ -84,3 +89,42 @@ void hma_exit(void) { } + +void extmem_copy(unsigned dst, unsigned src, unsigned len) +{ + unsigned slen, dlen, clen, copied = 0; + unsigned s, d, edge = LOWMEM_SIZE + HMASIZE; + unsigned char *ps = NULL; + + while ((clen = len - copied) > 0) { + slen = clen; + s = src + copied; + if (s >= edge) + ps = &ext_mem_base[s - edge]; + else if (s + slen > edge) + slen = edge - s; + + dlen = clen; + d = dst + copied; + if (d < edge && d + dlen > edge) + dlen = edge - d; + + clen = _min(slen, dlen); + x_printf("INT15: copy 0x%x bytes from %#x to %#x%s\n", + clen, s, d, clen != len ? " (split)" : ""); + if (d < edge) { + if (s < edge) + memmove_dos2dos(d, s, clen); + else + memcpy_2dos(d, ps, clen); + e_invalidate(d, clen); + } else { + unsigned char *pd = &ext_mem_base[d - edge]; + if (s < edge) + memcpy_2unix(pd, s, clen); + else + memmove(pd, ps, clen); + } + copied += clen; + } +} diff --git a/src/base/misc/ioctl.c b/src/base/misc/ioctl.c index 39c0b00..bde83d2 100644 --- a/src/base/misc/ioctl.c +++ b/src/base/misc/ioctl.c @@ -5,7 +5,9 @@ #include #include #include -#include +#ifndef EDEADLOCK + #define EDEADLOCK EDEADLK +#endif #include #include #include @@ -19,6 +21,7 @@ #include #include "memory.h" +#include "mhpdbg.h" #include "emu.h" #ifdef __linux__ #include "sys_vm86.h" @@ -35,7 +38,6 @@ #include "bitops.h" #include "pic.h" #include "emudpmi.h" -#include "ioselect.h" #ifdef USE_MHPDBG #include "mhpdbg.h" @@ -46,18 +48,9 @@ #define PAGE_SIZE 4096 #endif -struct io_callback_s { - void (*func)(int, void *); - void *arg; - const char *name; - int fd; - unsigned flags; -}; -#define MAX_FD FD_SETSIZE -static struct io_callback_s io_callback_func[MAX_FD]; -static struct io_callback_s io_callback_stash[MAX_FD]; +#define MAX_FD 1024 +static struct callback_s io_callback_func[MAX_FD]; static fd_set fds_sigio; -static fd_set fds_masked; #if defined(SIG) static inline int process_interrupt(SillyG_t *sg) @@ -66,12 +59,12 @@ static inline int process_interrupt(SillyG_t *sg) if ((irq = sg->irq) != 0) { h_printf("INTERRUPT: 0x%02x\n", irq); - pic_request(irq); + ret=(pic_request(pic_irq_list[irq])!=PIC_REQ_LOST); } return ret; } -void irq_select(void) +static inline void irq_select(void) { if (SillyG) { int irq_bits = vm86_plus(VM86_GET_IRQ_BITS, 0); @@ -89,59 +82,33 @@ void irq_select(void) } } } -#else -void irq_select(void) -{ -} #endif /* */ /* io_select @@@ 24576 MOVED_CODE_BEGIN @@@ 01/23/96, ./src/base/misc/dosio.c --> src/base/misc/ioctl.c */ -static int max_fd; -static int syncpipe[2]; -static pthread_t io_thr; -static pthread_mutex_t fun_mtx = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t blk_mtx = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t fds_mtx = PTHREAD_MUTEX_INITIALIZER; +static int numselectfd= 0; -static void ioselect_demux(void *arg) -{ - struct io_callback_s *p = arg; - struct io_callback_s f; - - pthread_mutex_lock(&fun_mtx); - f = *p; - pthread_mutex_unlock(&fun_mtx); - /* check if not removed from other thread */ - if (f.func) { - g_printf("GEN: fd %i has data for %s\n", f.fd, f.name); - f.func(f.fd, f.arg); - reset_idle(0); - } -} - -static void io_select(void) +void +io_select(void) { int selrtn, i; - fd_set fds; - int nfds; + struct timeval tvptr; + fd_set fds = fds_sigio; - pthread_mutex_lock(&fds_mtx); - fds = fds_sigio; - nfds = max_fd + 1; - pthread_mutex_unlock(&fds_mtx); + tvptr.tv_sec=0L; + tvptr.tv_usec=0L; - pthread_mutex_lock(&blk_mtx); - for (i = 0; i < nfds; i++) { - if (FD_ISSET(i, &fds_masked)) - FD_CLR(i, &fds); +#if defined(SIG) + irq_select(); +#endif + + while ( ((selrtn = select(numselectfd, &fds, NULL, NULL, &tvptr)) == -1) + && (errno == EINTR)) { + tvptr.tv_sec=0L; + tvptr.tv_usec=0L; + g_printf("WARNING: interrupted io_select: %s\n", strerror(errno)); } - pthread_mutex_unlock(&blk_mtx); - - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - selrtn = RPT_SYSCALL(select(nfds, &fds, NULL, NULL, NULL)); - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); switch (selrtn) { case 0: /* none ready, nothing to do :-) */ @@ -152,31 +119,23 @@ static void io_select(void) break; default: /* has at least 1 descriptor ready */ - pthread_mutex_lock(&blk_mtx); - for (i = 0; i < nfds; i++) { - if (FD_ISSET(i, &fds_masked)) - continue; - if (FD_ISSET(i, &fds)) { - if (io_callback_func[i].flags & IOFLG_IMMED) { - if (io_callback_func[i].flags & IOFLG_MASKED) - FD_SET(i, &fds_masked); - io_callback_func[i].func(i, io_callback_func[i].arg); - } else { - FD_SET(i, &fds_masked); - add_thread_callback(ioselect_demux, &io_callback_func[i], "ioselect"); - } - } + for(i = 0; i < numselectfd; i++) { + if (FD_ISSET(i, &fds) && io_callback_func[i].func) { + g_printf("GEN: fd %i has data for %s\n", i, + io_callback_func[i].name); + io_callback_func[i].func(io_callback_func[i].arg); + } } - pthread_mutex_unlock(&blk_mtx); + reset_idle(0); break; - } + } } /* * DANG_BEGIN_FUNCTION add_to_io_select * * arguments: - * fd - File handle to add to select statement + * fd - File handle to add to select statment * want_sigio - want SIGIO (1) if it's available, or not (0). * * description: @@ -186,42 +145,37 @@ static void io_select(void) * DANG_END_FUNCTION */ void -add_to_io_select_new(int new_fd, void (*func)(int, void *), void *arg, - unsigned flags, const char *name) +add_to_io_select_new(int new_fd, void (*func)(void *), void *arg, + const char *name) { - struct io_callback_s *f = &io_callback_func[new_fd]; + int flags; - if (new_fd >= MAX_FD) { + if ((new_fd+1) > numselectfd) numselectfd = new_fd+1; + if (numselectfd > MAX_FD) { error("Too many IO fds used.\n"); leavedos(76); } - io_callback_stash[new_fd] = *f; + if ((flags = fcntl(new_fd, F_GETFL)) == -1 || + fcntl(new_fd, F_SETOWN, getpid()) == -1 || + fcntl(new_fd, F_SETFL, flags | O_ASYNC) == -1 || + fcntl(new_fd, F_SETFD, FD_CLOEXEC) == -1) { + error("add_to_io_select_new: Fcntl failed\n"); + leavedos(76); + } - g_printf("GEN: fd=%d gets SIGIO for %s\n", new_fd, name); - pthread_mutex_lock(&fun_mtx); - f->func = func; - f->arg = arg; - f->name = name; - f->fd = new_fd; - f->flags = flags; - pthread_mutex_unlock(&fun_mtx); - - pthread_mutex_lock(&fds_mtx); - if (new_fd > max_fd) - max_fd = new_fd; FD_SET(new_fd, &fds_sigio); - pthread_mutex_unlock(&fds_mtx); - - if (!io_callback_stash[new_fd].func) - write(syncpipe[1], "+", 1); + g_printf("GEN: fd=%d gets SIGIO for %s\n", new_fd, name); + io_callback_func[new_fd].func = func; + io_callback_func[new_fd].arg = arg; + io_callback_func[new_fd].name = name; } /* * DANG_BEGIN_FUNCTION remove_from_io_select * * arguments: - * fd - File handle to remove from select statement. + * fd - File handle to remove from select statment. * used_sigio - used SIGIO (1) if it's available, or not (0). * * description: @@ -230,98 +184,32 @@ add_to_io_select_new(int new_fd, void (*func)(int, void *), void *arg, * * DANG_END_FUNCTION */ -void remove_from_io_select(int fd) +void remove_from_io_select(int new_fd) { - if (fd < 0 || !io_callback_func[fd].func) { - g_printf("GEN: removing bogus fd %d (ignoring)\n", fd); + int flags; + + if (new_fd < 0) { + g_printf("GEN: removing bogus fd %d (ignoring)\n", new_fd); return; } - - pthread_mutex_lock(&fun_mtx); - io_callback_func[fd] = io_callback_stash[fd]; - pthread_mutex_unlock(&fun_mtx); - io_callback_stash[fd].func = NULL; - - if (!io_callback_func[fd].func) { - pthread_mutex_lock(&fds_mtx); - FD_CLR(fd, &fds_sigio); - pthread_mutex_unlock(&fds_mtx); - write(syncpipe[1], "-", 1); - g_printf("GEN: fd=%d removed from select SIGIO\n", fd); + if ((flags = fcntl(new_fd, F_GETFL)) == -1 || + fcntl(new_fd, F_SETOWN, NULL) == -1 || + fcntl(new_fd, F_SETFL, flags & ~O_ASYNC) == -1) { + error("remove_from_io_select: Fcntl failed\n"); + leavedos(76); } -} - -static void do_unmask(int fd) -{ - pthread_mutex_lock(&blk_mtx); - FD_CLR(fd, &fds_masked); - pthread_mutex_unlock(&blk_mtx); - write(syncpipe[1], "=", 1); -} - -void ioselect_complete(int fd) -{ - do_unmask(fd); -} - -void ioselect_block(int fd) -{ - assert(io_callback_func[fd].flags & IOFLG_IMMED); - pthread_mutex_lock(&blk_mtx); - FD_SET(fd, &fds_masked); - pthread_mutex_unlock(&blk_mtx); -} - -void ioselect_unblock(int fd) -{ - assert(io_callback_func[fd].flags & IOFLG_IMMED); - do_unmask(fd); -} - -static void *ioselect_thread(void *arg) -{ - while (1) { - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - io_select(); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - pthread_testcancel(); - } - return NULL; -} - -static void do_syncpipe(int fd, void *arg) -{ - char buf[4096]; - read(fd, buf, sizeof(buf)); -} - -void ioselect_init(void) -{ - struct io_callback_s *f; - struct sched_param parm = { .sched_priority = 1 }; - - FD_ZERO(&fds_sigio); - FD_ZERO(&fds_masked); - pipe(syncpipe); - assert(syncpipe[0] < MAX_FD); - f = &io_callback_func[syncpipe[0]]; - f->func = do_syncpipe; - f->arg = NULL; - f->name = "syncpipe"; - f->fd = syncpipe[0]; - f->flags = IOFLG_IMMED; - max_fd = syncpipe[0]; - FD_SET(syncpipe[0], &fds_sigio); - pthread_create(&io_thr, NULL, ioselect_thread, NULL); - pthread_setschedparam(io_thr, SCHED_FIFO, &parm); -#if defined(HAVE_PTHREAD_SETNAME_NP) && defined(__GLIBC__) - pthread_setname_np(io_thr, "dosemu: io"); -#endif + FD_CLR(new_fd, &fds_sigio); + g_printf("GEN: fd=%d removed from select SIGIO\n", new_fd); + io_callback_func[new_fd].func = NULL; } void ioselect_done(void) { - pthread_cancel(io_thr); - pthread_join(io_thr, NULL); - close(syncpipe[1]); + int i; + for (i = 0; i < MAX_FD; i++) { + if (io_callback_func[i].func) { + remove_from_io_select(i); + close(i); + } + } } diff --git a/src/base/misc/utilities.c b/src/base/misc/utilities.c index 911af65..7bacf6b 100644 --- a/src/base/misc/utilities.c +++ b/src/base/misc/utilities.c @@ -1,5 +1,5 @@ /* - * Various sundry utilities for dos emulator. + * Various sundry utilites for dos emulator. * */ #include "emu.h" @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -21,9 +20,6 @@ #include #include #include -#ifdef HAVE_LIBBSD -#include -#endif #include "bios.h" #include "timers.h" @@ -187,7 +183,7 @@ int vlog_printf(int flg, const char *fmt, va_list args) q = (is_cr? timestamp(logptr) : logptr); i = vsnprintf(q, MAX_LINE_SIZE, fmt, args); - if (i >= MAX_LINE_SIZE) { /* truncated for buffer overflow */ + if (i < 0) { /* truncated for buffer overflow */ i = MAX_LINE_SIZE-2; q[i++]='\n'; q[i]=0; is_cr=1; } @@ -324,9 +320,9 @@ void error(const char *fmt, ...) /* write string to dos? */ -static int _dos_vstr(const char *fmt, va_list args, void (*cout)(u_char, int)) +int p_dos_vstr(const char *fmt, va_list args) { - char buf[1024]; + static char buf[1024]; char *s; int i; @@ -334,15 +330,10 @@ static int _dos_vstr(const char *fmt, va_list args, void (*cout)(u_char, int)) s = buf; g_printf("CONSOLE MSG: '%s'\n",buf); while (*s) - cout(*s++, READ_BYTE(BIOS_CURRENT_SCREEN_PAGE)); + char_out(*s++, READ_BYTE(BIOS_CURRENT_SCREEN_PAGE)); return i; } -int p_dos_vstr(const char *fmt, va_list args) -{ - return _dos_vstr(fmt, args, char_out); -} - int p_dos_str(const char *fmt, ...) { va_list args; @@ -371,14 +362,14 @@ void close_proc_scan(void) procfile_name = procbuf = procbufptr = proclastpos = 0; } -int open_proc_scan(const char *name) +void open_proc_scan(const char *name) { int size, fd; close_proc_scan(); fd = open(name, O_RDONLY); if (fd == -1) { error("cannot open %s\n", name); - return -1; + leavedos(5); } procfile_name = strdup(name); procbuf = malloc(PROCBUFSIZE); @@ -386,7 +377,6 @@ int open_proc_scan(const char *name) procbuf[size] = 0; procbufptr = procbuf; close(fd); - return 0; } void advance_proc_bufferptr(void) @@ -449,6 +439,25 @@ int get_proc_intvalue_by_key(const char *key) return -1; /* just to make GCC happy */ } + +int integer_sqrt(int x) +{ + unsigned y; + int delta; + + if (x < 1) return 0; + if (x <= 1) return 1; + y = power_of_2_sqrt(x); + if ((y*y) == x) return y; + delta = y >> 1; + while (delta) { + y += delta; + if (y*y > x) y -= delta; + delta >>= 1; + } + return y; +} + int exists_dir(const char *name) { struct stat st; @@ -517,31 +526,21 @@ char *expand_path(const char *dir) int err; err = wordexp(dir, &p, WRDE_NOCMD); - if (err) - return NULL; - if (p.we_wordc != 1) { - wordfree(&p); - return NULL; - } + assert(!err); + assert(p.we_wordc == 1); s = realpath(p.we_wordv[0], NULL); wordfree(&p); return s; } -char *mkdir_under(const char *basedir, const char *dir) +const char *mkdir_under(const char *basedir, const char *dir) { - char *s; + const char *s = basedir; - if (dir) - s = assemble_path(basedir, dir); - else - s = strdup(basedir); + if (dir) s = assemble_path(basedir, dir); if (!exists_dir(s)) { if (mkdir(s, S_IRWXU)) { - fprintf(stderr, "can't create dir %s: %s\n", s, - strerror(errno)); - free(s); - s = NULL; + fprintf(stderr, "can't create local %s directory\n", s); } } return s; @@ -561,35 +560,11 @@ char *get_path_in_HOME(const char *path) return assemble_path(home, path); } -char *get_dosemu_local_home(void) +const char *get_dosemu_local_home(void) { return mkdir_under(get_path_in_HOME(".dosemu"), 0); } -char *prefix(const char *suffix) -{ - char *p1, *ret, *s, *p; - - if (dosemu_proc_self_exe[0] != '/') { - error("cannot evaluate prefix from relative path %s\n", - dosemu_proc_self_exe); - return assemble_path(PREFIX, suffix); - } - s = strdup(dosemu_proc_self_exe); - p = dirname(s); - assert(p); - p1 = strrchr(p, '/'); - if (p1 && strcmp(p1 + 1, "bin") == 0) { - *p1 = '\0'; - ret = assemble_path(p, suffix); - } else { - error("unable to evaluate prefix from %s\n", dosemu_proc_self_exe); - ret = assemble_path(PREFIX, suffix); - } - free(s); - return ret; -} - int argparse(char *s, char *argvx[], int maxarg) { int mode = 0; @@ -652,7 +627,7 @@ void subst_file_ext(char *ptr) if (toupperDOS(ptr[0]) == 'D') ptr++; #endif ext_fix(config.emusys); - snprintf(config_name, sizeof(config_name), "CONFIG.%-.3s", config.emusys); + sprintf(config_name, "CONFIG.%-3s", config.emusys); if (subst_sys == 1 && !strequalDOS(ptr, config_name) && !strequalDOS(ptr, "CONFIG.SYS")) { subst_sys = 0; @@ -664,6 +639,46 @@ void subst_file_ext(char *ptr) } } +void call_cmd(const char *cmd, int maxargs, const struct cmd_db *cmdtab, + cmdprintf_func *printf) +{ + int argc1; + char **argv1; + char *tmpcmd; + void (*cmdproc)(int, char *[]); + const struct cmd_db *cmdp; + + tmpcmd = strdup(cmd); + if (!tmpcmd) { + if (printf) (*printf)("out of memory\n"); + return; + } + argv1 = malloc(maxargs * sizeof(char *)); + if (!argv1) { + if (printf) (*printf)("out of memory\n"); + free(tmpcmd); + return; + }; + argc1 = argparse(tmpcmd, argv1, maxargs); + if (argc1 < 1) { + free(tmpcmd); + free(argv1); + return; + } + for (cmdp = cmdtab, cmdproc = NULL; cmdp->cmdproc; cmdp++) { + if (!memcmp(cmdp->cmdname, argv1[0], strlen(argv1[0])+1)) { + cmdproc = cmdp->cmdproc; + break; + } + } + if (!cmdproc) { + if (printf) (*printf)("Command %s not found\n", argv1[0]); + } + else (*cmdproc)(argc1, argv1); + free(tmpcmd); + free(argv1); +} + void sigalarm_onoff(int on) { static struct itimerval itv_old; @@ -732,7 +747,7 @@ static void *do_dlopen(const char *filename, int flags) handle = dlopen(filename, flags); if (handle) return handle; - error("%s: %s\n", filename, dlerror()); + error("%s\n", dlerror()); return NULL; } @@ -750,8 +765,7 @@ void *load_plugin(const char *plugin_name) (int)(p - dosemu_proc_self_exe), dosemu_proc_self_exe, plugin_name); if (access(fullname, R_OK) == 0 && - strncmp(fullname, dosemu_plugin_dir_path, - strlen(dosemu_plugin_dir_path)) != 0) { + strcmp(dosemu_plugin_dir_path, DOSEMUPLUGINDIR) == 0) { error("running from build dir must be done via script\n"); warned++; } @@ -912,7 +926,7 @@ strlcpy(char *dst, const char *src, size_t dsize) /* Copyright (c) 1997 Todd C. Miller */ /* modified by stsp */ -const char *findprog(const char *prog, const char *pathc) +char *findprog(char *prog, const char *pathc) { static char filename[PATH_MAX]; char *p; @@ -1000,7 +1014,6 @@ int replace_string(struct string_store *store, const char *old, char *str) return 0; } -#ifdef HAVE_FOPENCOOKIE struct tee_struct { FILE *stream[2]; }; @@ -1008,8 +1021,8 @@ struct tee_struct { static ssize_t tee_write(void *cookie, const char *buf, size_t size) { struct tee_struct *c = cookie; - fwrite(buf, 1, size, c->stream[0]); - return fwrite(buf, 1, size, c->stream[1]); + fwrite(buf, size, 1, c->stream[0]); + return fwrite(buf, size, 1, c->stream[1]); } static int tee_close(void *cookie) @@ -1039,241 +1052,3 @@ FILE *fstream_tee(FILE *orig, FILE *copy) setbuf(f, NULL); return f; } -#endif - -static int pts_open(int pty_fd) -{ - int err, pts_fd; - - setsid(); // will have ctty - /* open pts _after_ setsid, or it won't became a ctty */ - err = grantpt(pty_fd); - if (err) { - error("grantpt failed: %s\n", strerror(errno)); - return err; - } - pts_fd = open(ptsname(pty_fd), O_RDWR | O_CLOEXEC); - if (pts_fd == -1) { - error("pts open failed: %s\n", strerror(errno)); - return -1; - } - return pts_fd; -} - -static int pshared_sem_init(pshared_sem_t *sem, unsigned int value) -{ - char sem_name[] = "/dosemu2_psem_%PXXXXXX"; - pshared_sem_t s; - int ret; - - tempname(sem_name, 6); - s = sem_open(sem_name, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, value); - if (!s) - { - /* Stalled sem. Name collision is practically impossible - * because we unlink the sem immediately after creation, - * and also we can't collide with another running dosemu2 - * instance because we use PID in the sem name. */ - error("sem_open %s failed %s\n", sem_name, strerror(errno)); - sem_unlink(sem_name); - s = sem_open(sem_name, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, value); - } - if (!s) - { - error("sem_open failed %s\n", strerror(errno)); - return -1; - } - ret = sem_unlink(sem_name); - if (!ret) - *sem = s; - return ret; -} - -static int pshared_sem_destroy(pshared_sem_t *sem) -{ - int ret = sem_close(*sem); - *sem = NULL; - return ret; -} - -pid_t run_external_command(const char *path, int argc, const char **argv, - int use_stdin, int close_from, int pty_fd) -{ - pid_t pid; - int wt, retval; - sigset_t set, oset; - int pts_fd; - pshared_sem_t pty_sem; - - retval = pshared_sem_init(&pty_sem, 0); - assert(!retval); - signal_block_async_nosig(&oset); - sigprocmask(SIG_SETMASK, NULL, &set); - /* fork child */ - switch ((pid = fork())) { - case -1: /* failed */ - sigprocmask(SIG_SETMASK, &oset, NULL); - g_printf("run_unix_command(): fork() failed\n"); - return -1; - case 0: /* child */ - priv_drop(); - pts_fd = pts_open(pty_fd); - /* Reading master side before slave opened, results in EOF. - * Notify user that reads are now safe. */ - pshared_sem_post(pty_sem); - pshared_sem_destroy(&pty_sem); - if (pts_fd == -1) { - error("run_unix_command(): open pts failed %s\n", strerror(errno)); - _exit(EXIT_FAILURE); - } - close(0); - close(1); - close(2); - if (use_stdin) - dup(pts_fd); - else - open("/dev/null", O_RDONLY); - dup(pts_fd); - dup(pts_fd); - close(pts_fd); - close(pty_fd); - if (close_from != -1) -#ifdef HAVE_CLOSEFROM - closefrom(close_from); -#else - for (; close_from < sysconf(_SC_OPEN_MAX); close_from++) - close(close_from); -#endif - /* close signals, then unblock */ - signal_done(); - /* flush pending signals */ - do { -#ifdef HAVE_SIGTIMEDWAIT - struct timespec to = { 0, 0 }; - wt = sigtimedwait(&set, NULL, &to); -#else - int i; - sigset_t pending; - sigpending(&pending); - wt = -1; - for (i = 1; i < SIGMAX; i++) - if (sigismember(&pending, i) && sigismember(&set, i)) { - sigwait(&set, NULL); - wt = 0; - } -#endif - } while (wt != -1); - sigprocmask(SIG_SETMASK, &oset, NULL); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wincompatible-pointer-types" - retval = execve(path, argv, dosemu_envp); /* execute command */ -#pragma GCC diagnostic pop - error("exec failed: %s\n", strerror(errno)); - _exit(retval); - break; - } - sigprocmask(SIG_SETMASK, &oset, NULL); - /* wait until its safe to read from pty_fd */ - pshared_sem_wait(pty_sem); - pshared_sem_destroy(&pty_sem); - return pid; -} - -/* ripped out of glibc. same as mktemp() but doesn't check the file */ -/* - congruential generator that starts with Var's value - mixed in with a clock's low-order bits if available. */ -typedef uint_fast64_t random_value; -#define RANDOM_VALUE_MAX UINT_FAST64_MAX -#define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */ -#define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62) - -static random_value -random_bits (random_value var) -{ - struct timespec tv; - clock_gettime (CLOCK_MONOTONIC, &tv); - var ^= tv.tv_nsec; - return 2862933555777941757 * var + 3037000493; -} - -/* These are the characters used in temporary file names. */ -static const char letters[] = -"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -int tempname(char *tmpl, size_t x_suffix_len) -{ - int suffixlen = 0; - size_t len; - char *XXXXXX, *p; - - /* A random variable. The initial value is used only the for fallback path - on 'random_bits' on 'getrandom' failure. Its initial value tries to use - some entropy from the ASLR and ignore possible bits from the stack - alignment. */ - random_value v = ((uintptr_t) &v) / (sizeof(long)); - - /* How many random base-62 digits can currently be extracted from V. */ - int vdigits = 0; - - /* Least unfair value for V. If V is less than this, V can generate - BASE_62_DIGITS digits fairly. Otherwise it might be biased. */ - random_value const unfair_min - = RANDOM_VALUE_MAX - RANDOM_VALUE_MAX % BASE_62_POWER; - - len = strlen (tmpl); - if (len < x_suffix_len + suffixlen - || strspn (&tmpl[len - x_suffix_len - suffixlen], "X") < x_suffix_len) - { - return -1; - } - - if ((p = strstr(tmpl, "%PX"))) { - /* reserve at least 1 X */ - int plen = snprintf(p, x_suffix_len + 2, "%02i", getpid()); - if (plen >= x_suffix_len + 2) - return -1; - assert(p[plen] == '\0'); // snprintf's trailing 0 - p[plen] = 'X'; - assert(plen >= 2); - x_suffix_len -= plen - 2; - } - - /* This is where the Xs start. */ - XXXXXX = &tmpl[len - x_suffix_len - suffixlen]; - - { - for (size_t i = 0; i < x_suffix_len; i++) - { - if (vdigits == 0) - { - do - { - v = random_bits (v); - } - while (unfair_min <= v); - - vdigits = BASE_62_DIGITS; - } - - XXXXXX[i] = letters[v % 62]; - v /= 62; - vdigits--; - } - } - - return 0; -} - -int mktmp_in(char *dir_tmpl, const char *fname, mode_t mode) -{ - int fd; - char *p; - char *d = mkdtemp(dir_tmpl); - if (!d) - return -1; - p = assemble_path(d, fname); - fd = open(p, O_CREAT | O_RDWR | O_EXCL, mode); - free(p); - return fd; -} diff --git a/src/base/mouse/mouse.c b/src/base/mouse/mouse.c index b85a909..7f5aef3 100644 --- a/src/base/mouse/mouse.c +++ b/src/base/mouse/mouse.c @@ -3,7 +3,6 @@ * */ -#include "init.h" #include "emu.h" #include "bios.h" #include "int.h" @@ -11,8 +10,6 @@ #include "video.h" /* video base address */ #include "serial.h" #include "timers.h" -#include "virq.h" -#include "coopth.h" #include "utilities.h" #include "doshelpers.h" #include "lowmem.h" @@ -36,10 +33,6 @@ #define INIT_SPEED_X 8 #define INIT_SPEED_Y 16 -static int mouse_tid; - -static void reset_scale(void); - static int mickeyx(void) { return (mouse.unscm_x / (mouse.px_range * 8)); @@ -123,7 +116,7 @@ static void do_move_abs(int x, int y, int x_range, int y_range, int vis); /* mouse movement functions */ static void mouse_reset(void); -static void mouse_do_cur(int callback), mouse_update_cursor(void); +static void mouse_do_cur(int callback), mouse_update_cursor(int clipped); static void mouse_reset_to_current_video_mode(void); static void int33_mouse_move_buttons(int lbutton, int mbutton, int rbutton, void *udata); @@ -135,7 +128,6 @@ static void int33_mouse_move_absolute(int x, int y, int x_range, int y_range, int vis, void *udata); static void int33_mouse_drag_to_corner(int x_range, int y_range, void *udata); static void int33_mouse_enable_native_cursor(int flag, void *udata); -static void call_int15_mouse_event_handler(void); /* graphics cursor */ void graph_cursor(void), text_cursor(void); @@ -148,6 +140,7 @@ static void mouse_delta(int); static int mouse_clip_coords(void); static void mouse_hide_on_exclusion(void); +static void call_mouse_event_handler(void); static int mouse_events = 0; struct dragged_hack { int cnt, skipped; @@ -239,10 +232,9 @@ mouse_helper(struct vm86_regs *regs) SETHIGH(regs->ebx, 0x10); /* We are currently in Microsoft Mode */ else SETHIGH(regs->ebx, 0x20); /* We are currently in PC Mouse Mode */ - SETLO_BYTE(regs->ecx, mice->init_speed_x); - SETHIGH(regs->ecx, mice->init_speed_y); - SETLO_BYTE(regs->edx, (mice->ignorevesa & 1) | - ((mice->ignore_speed << 1) & 2)); + SETLO_BYTE(regs->ecx, mouse.speed_x); + SETHIGH(regs->ecx, mouse.speed_y); + SETLO_BYTE(regs->edx, mice->ignorevesa); break; case 4: /* Set vertical speed */ if (LO_BYTE_d(regs->ecx) < 1) { @@ -268,16 +260,12 @@ mouse_helper(struct vm86_regs *regs) case 8: /* set minimum internal resolution */ mouse.min_max_x = LO_WORD(regs->ecx); mouse.min_max_y = LO_WORD(regs->edx); - reset_scale(); break; case 9: /* set cursor visibility */ - mouse_client_show_cursor(LO_BYTE_d(regs->ecx)); + mouse_client_show_cursor(!!regs->ecx); break; case 0xa: /* lock cursor visibility */ - mouse.visibility_locked = LO_BYTE_d(regs->ecx); - break; - case 0xb: /* ungrabbed mode tweak */ - mice->ignore_speed = LO_BYTE_d(regs->ecx); + mouse.visibility_locked = !!regs->ecx; break; case DOS_SUBHELPER_MOUSE_START_VIDEO_MODE_SET: m_printf("MOUSE Start video mode set\n"); @@ -315,11 +303,7 @@ mouse_helper(struct vm86_regs *regs) break; case 0xf2: m_printf("MOUSE int74 helper\n"); - if (mouse.ps2.state && (mouse.ps2.cs || mouse.ps2.ip)) { - call_int15_mouse_event_handler(); - mouse_events = 0; - } - pic_untrigger(12); + call_mouse_event_handler(); break; case 0xff: m_printf("MOUSE Checking InternalDriver presence !!\n"); @@ -656,7 +640,7 @@ mouse_int(void) } if (mouse.cursor_on == 0) - mouse_update_cursor(); + mouse_update_cursor(0); return 1; } @@ -937,16 +921,6 @@ static void setxy(int x, int y) mouse.unsc_y = get_unsc_y(y); } -/* change pos from software preserving coord reminders */ -static void setxy_sw(int x, int y) -{ - int rem_x = mouse.unsc_x % get_unsc_x(1 << mouse.xshift); - int rem_y = mouse.unsc_y % get_unsc_y(1 << mouse.yshift); - - mouse.unsc_x = get_unsc_x(mouse_roundx(x)) + rem_x; - mouse.unsc_y = get_unsc_y(mouse_roundy(y)) + rem_y; -} - static int get_unsc_mk_x(int dx) { return dx * mouse.px_range; @@ -979,13 +953,8 @@ static void add_mickey_coords(long long udx, long long udy) static void get_scale_range(int *mx_range, int *my_range) { - if (config.mouse.ignore_speed) { - *mx_range = _max(mouse.maxx, mouse.virtual_maxx) - MOUSE_MINX + 1; - *my_range = _max(mouse.maxy, mouse.virtual_maxy) - MOUSE_MINY + 1; - } else { - *mx_range = mouse.maxx - MOUSE_MINX + 1; - *my_range = mouse.maxy - MOUSE_MINY + 1; - } + *mx_range = mouse.maxx - MOUSE_MINX +1; + *my_range = mouse.maxy - MOUSE_MINY +1; } static void add_mk(int dx, int dy) @@ -1035,7 +1004,7 @@ static void reset_scale(void) * returns yourself. * * To handle programs written by programmers who weren't so cautious a - * doctrine of least surprise has been implemented. + * doctrine of least suprise has been implemented. * * As much as possible do the same as a standard dos mouse driver in the * original vga modes 0,1,2,3,4,5,6,7,13,14,15,16,17,18,19. @@ -1101,8 +1070,6 @@ mouse_reset_to_current_video_mode(void) mouse.sens_x = 100; mouse.sens_y = 100; mouse.threshold = 200; - mouse.px_abs = 0; - mouse.py_abs = 0; /* * Here we make sure text modes are resolved properly, according to the @@ -1183,7 +1150,7 @@ static void scale_coords2(int x, int y, int x_range, int y_range, /* if cursor is not visible we need to take into * account the user's speed. If it is visible, then * in ungrabbed mode we have to ignore user's speed. */ - if (!config.mouse.ignore_speed && mouse.cursor_on < 0) + if (mouse.cursor_on < 0) scale_coords_spd(x, y, x_range, y_range, mx_range, my_range, speed_x, speed_y, s_x, s_y); @@ -1303,11 +1270,7 @@ mouse_cursor(int flag) /* 1=show, -1=hide */ if (flag == 1 && need_resync && !dragged.cnt) do_move_abs(mouse.px_abs, mouse.py_abs, mouse.px_range, mouse.py_range, mouse.cursor_on >= 0); - /* first time enabling should work immediately */ - if (flag == 1 && !mouse.visibility_changed) - mouse_client_show_cursor(mouse.visibility_locked ?: mouse.cursor_on >= 0); - else - mouse.visibility_changed++; + mouse.visibility_changed++; } m_printf("MOUSE: %s mouse cursor %d\n", flag > 0 ? "show" : "hide", mouse.cursor_on); @@ -1331,7 +1294,18 @@ mouse_pos(void) void mouse_setpos(void) { - setxy_sw(LWORD(ecx), LWORD(edx)); + /* disable the hack below, it is likely no longer needed. -stsp */ +#if 0 + /* WP reads mickeys, and then sets the cursor position to make certain + * it doesn't loose any mickeys. This will catch that case, and keeps + * us from breaking all apps under X that set the mouse position. + */ + if (last_mouse_call_read_mickeys && mice->use_absolute) { + m_printf("MOUSE: ignoring 'set cursor pos' in X with no grab active\n"); + return; + } +#endif + setxy(LWORD(ecx), LWORD(edx)); mouse_clip_coords(); mouse_hide_on_exclusion(); if (mouse.cursor_on >= 0) { @@ -1449,8 +1423,6 @@ mouse_setxminmax(void) mouse.virtual_minx = mouse_roundx(mouse.virtual_minx); mouse.virtual_maxx = mouse_roundx(mouse.virtual_maxx); mouse.virtual_maxx += (1 << mouse.xshift) -1; - - mouse_clip_coords(); } void @@ -1464,8 +1436,6 @@ mouse_setyminmax(void) mouse.virtual_miny = mouse_roundy(mouse.virtual_miny); mouse.virtual_maxy = mouse_roundy(mouse.virtual_maxy); mouse.virtual_maxy += (1 << mouse.yshift) -1; - - mouse_clip_coords(); } void @@ -1484,7 +1454,7 @@ mouse_set_gcur(void) memcpy((void *)mouse.graphscreenmask,ptr,32); memcpy((void *)mouse.graphcursormask,ptr+16,32); - /* compile it so that it can actually be drawn. */ + /* compile it so that it can acutally be drawn. */ define_graphics_cursor(mouse.graphscreenmask, mouse.graphcursormask); } @@ -1561,7 +1531,7 @@ mouse_version(void) } void -mouse_disable_internaldriver(void) +mouse_disable_internaldriver() { LWORD(eax) = 0x001F; SREG(es) = mouse.cs; @@ -1574,7 +1544,7 @@ mouse_disable_internaldriver(void) } void -mouse_enable_internaldriver(void) +mouse_enable_internaldriver() { mouse.enabled = TRUE; mouse_client_show_cursor(mouse.cursor_on >= 0); @@ -1582,7 +1552,7 @@ mouse_enable_internaldriver(void) } /* Keyboard mouse control :) */ -void mouse_keyboard(bool make, t_keysym key) +void mouse_keyboard(Boolean make, t_keysym key) { static struct keyboard_mouse_state { int l, r, u, d; @@ -1729,7 +1699,7 @@ static void mouse_hide_on_exclusion(void) } } -static void mouse_move(int abs) +static void mouse_move(int clipped) { /* delayed visibility change */ if (mouse.visibility_changed) { @@ -1738,11 +1708,11 @@ static void mouse_move(int abs) } mouse_hide_on_exclusion(); - mouse_update_cursor(); + mouse_update_cursor(clipped); m_printf("MOUSE: move: x=%d,y=%d\n", get_mx(), get_my()); - mouse_delta(DELTA_CURSOR | (abs ? DELTA_ABSOLUTE : 0)); + mouse_delta(DELTA_CURSOR); } static void mouse_lb(void) @@ -1937,7 +1907,7 @@ static int move_abs_coords(int x, int y, int x_range, int y_range, int vis) mouse.x_delta = mouse.y_delta = 0; clipped = mouse_clip_coords2(new_x + mouse.x_delta, new_y + mouse.y_delta, &c_x, &c_y); - /* we don't allow DOS prog to grab mouse pointer by locking it + /* we dont allow DOS prog to grab mouse pointer by locking it * inside a clipping region. So just update deltas. If cursor * is visible, we always try to keep them at 0. */ if (clipped) { @@ -1970,7 +1940,7 @@ static void do_move_abs(int x, int y, int x_range, int y_range, int vis) * update the event mask */ if (moved) - mouse_move(1); + mouse_move(0); } static void int33_mouse_move_absolute(int x, int y, int x_range, int y_range, @@ -2042,6 +2012,7 @@ void mouse_delta(int event) { mouse_events |= event; + pic_request(PIC_IMOUSE); reset_idle(0); } @@ -2112,9 +2083,9 @@ static void call_int33_mouse_event_handler(void) mouse.wmcount = 0; /* jump to mouse cs:ip */ - m_printf("MOUSE: event %d, x %d(%d), y %d(%d), mx %d, my %d, b %x\n", - mouse_events, MOUSE_RX, get_mx(), MOUSE_RY, get_my(), mickeyx(), - mickeyy(), LWORD(ebx)); + m_printf("MOUSE: event %d, x %d, y %d, mx %d, my %d, b %x\n", + mouse_events, get_mx(), get_my(), mickeyx(), mickeyy(), + LWORD(ebx)); m_printf("MOUSE: .........jumping to %04x:%04x\n", mouse.cs, mouse.ip); SREG(ds) = mouse.cs; /* put DS in user routine */ do_call_back(mouse.cs, mouse.ip); @@ -2140,19 +2111,24 @@ static void call_int33_mouse_event_handler(void) } /* this function is called from int74 via inte6 */ -static void call_mouse_event_handler(void *arg) +static void call_mouse_event_handler(void) { int handled = 0; - if ((mouse.mask & mouse_events) && (mouse.cs || mouse.ip)) { - call_int33_mouse_event_handler(); - mouse_events = 0; + if (mouse_events && mouse.ps2.state && (mouse.ps2.cs || mouse.ps2.ip)) { + call_int15_mouse_event_handler(); handled = 1; } else { - m_printf("MOUSE: Skipping event handler, " + if (mouse.mask & mouse_events && (mouse.cs || mouse.ip)) { + call_int33_mouse_event_handler(); + handled = 1; + } else { + m_printf("MOUSE: Skipping event handler, " "mask=0x%x, ev=0x%x, cs=0x%x, ip=0x%x\n", mouse.mask, mouse_events, mouse.cs, mouse.ip); + } } + mouse_events = 0; if (handled && dragged.skipped) { dragged.skipped = 0; @@ -2185,12 +2161,12 @@ static void mouse_do_cur(int callback) /* conditionally update the mouse cursor only if it's changed position. */ static void -mouse_update_cursor(void) +mouse_update_cursor(int clipped) { /* sigh, too many programs seem to expect the mouse cursor to magically redraw itself, so we'll bend to their will... */ if (MOUSE_RX != mouse.oldrx || MOUSE_RY != mouse.oldry) { - mouse_do_cur(0); + mouse_do_cur(clipped); mouse.oldrx = MOUSE_RX; mouse.oldry = MOUSE_RY; } @@ -2268,32 +2244,7 @@ static void mouse_curtick(void) /* we used to do an unconditional update here, but that causes a distracting flicker in the mouse cursor. */ - mouse_update_cursor(); -} - -static enum VirqSwRet do_mouse_irq(void *arg) -{ - int ret = VIRQ_SWRET_DONE; - - if (mouse.ps2.state && (mouse.ps2.cs || mouse.ps2.ip)) - return ret; - if (mouse_events) { - coopth_start(mouse_tid, NULL); - ret = VIRQ_SWRET_BH; - } - return ret; -} - -static enum VirqHwRet do_mouse_fifo(void *arg) -{ - int cnt = mousedrv_process_fifo("int33 mouse"); - if (cnt == -1) { - error("mouse fifo empty\n"); - return VIRQ_HWRET_DONE; - } - if (mouse_events) - pic_request(12); // for ps2 - return (cnt ? VIRQ_HWRET_CONT : VIRQ_HWRET_DONE); + mouse_update_cursor(0); } /* @@ -2311,7 +2262,7 @@ static int int33_mouse_init(void) /* set minimum internal resolution * 640x200 is a long standing dosemu default - * although I accidentally broke it broke it by flipping my X & Y coordinates. + * although I accidentally broke it broke it by flipping my X & Y coordiantes. * -- Eric Biederman 29 May 2000 */ mouse.min_max_x = 640; @@ -2341,8 +2292,7 @@ static int int33_mouse_init(void) mouse.exc_lx = mouse.exc_ux = -1; mouse.exc_ly = mouse.exc_uy = -1; - virq_register(VIRQ_MOUSE, do_mouse_fifo, do_mouse_irq, NULL); - mouse_tid = coopth_create("mouse", call_mouse_event_handler); + pic_seti(PIC_IMOUSE, NULL, 0, NULL); sigalrm_register_handler(mouse_curtick); m_printf("MOUSE: INIT complete\n"); @@ -2357,17 +2307,12 @@ static int int33_mouse_accepts(int from, void *udata) * and nothing else. Those events ignore .accepts member. */ if (mice->com != -1) return 0; - /* for 2 mice see if source is ours */ + /* for 2 mices see if source is ours */ if (mice->type != mice->dev_type) return (from == mice->type); return 1; } -static void fifo_notify(void *udata) -{ - virq_raise(VIRQ_MOUSE); -} - void mouse_late_init(void) { if (!mice->intdrv) return; @@ -2418,5 +2363,5 @@ struct mouse_drv int33_mouse = { CONSTRUCTOR(static void int33_mouse_register(void)) { - register_mouse_driver_buffered(&int33_mouse, fifo_notify); + register_mouse_driver(&int33_mouse); } diff --git a/src/base/mouse/mousedrv.c b/src/base/mouse/mousedrv.c index 5989ccc..a50c602 100644 --- a/src/base/mouse/mousedrv.c +++ b/src/base/mouse/mousedrv.c @@ -22,49 +22,20 @@ #include #include #include -#include #include "emu.h" #include "serial.h" #include "utilities.h" -#include "ringbuf.h" #include "mouse.h" -struct bdrv_s { - struct mouse_drv *drv; - void *udata; - struct rng_s buf; - pthread_mutex_t buf_mtx; - void (*callback)(void *); - void **arg_p; -}; - struct mouse_drv_wrp { struct mouse_drv *drv; struct mouse_drv_wrp *next; void *udata; int initialized; - struct bdrv_s bdrv; }; static struct mouse_drv_wrp *mdrv; -enum MsApiIds { - MID_move_button, - MID_move_buttons, - MID_move_wheel, - MID_move_relative, - MID_move_mickeys, - MID_move_absolute, - MID_drag_to_corner, - MID_enable_native_cursor, -}; - -#define B_MAX_ARGS 10 -struct mbuf_s { - enum MsApiIds id; - int args[B_MAX_ARGS]; -}; - struct mouse_client_wrp { struct mouse_client *clnt; int initialized; @@ -95,27 +66,17 @@ mouse_client_f(void, post_init, void, ()) mouse_client_f(void, show_cursor, int yes, (yes)) mouse_client_f(void, reset, void, ()) -static struct mouse_drv_wrp *do_create_driver(struct mouse_drv *mouse) -{ - struct mouse_drv_wrp *ms; - - ms = malloc(sizeof(*ms)); - ms->drv = mouse; - ms->bdrv.drv = NULL; - ms->udata = NULL; - ms->initialized = 0; - ms->next = NULL; - return ms; -} - void register_mouse_driver(struct mouse_drv *mouse) { struct mouse_drv_wrp *m, *ms; - - ms = do_create_driver(mouse); - if (mdrv == NULL) { + ms = malloc(sizeof(*ms)); + ms->drv = mouse; + ms->udata = NULL; + ms->initialized = 0; + ms->next = NULL; + if (mdrv == NULL) mdrv = ms; - } else { + else { for (m = mdrv; m->next; m = m->next); m->next = ms; } @@ -124,7 +85,7 @@ void register_mouse_driver(struct mouse_drv *mouse) void mousedrv_set_udata(const char *name, void *udata) { struct mouse_drv_wrp *m; - for (m = mdrv; m; m = m->next) { + for (m = mdrv; m->next; m = m->next) { if (strcmp(name, m->drv->name) == 0) { m->udata = udata; break; @@ -132,122 +93,6 @@ void mousedrv_set_udata(const char *name, void *udata) } } -static void fifo_mdrv_add(struct bdrv_s *r, struct mbuf_s *b) -{ - int rc, cnt; - - pthread_mutex_lock(&r->buf_mtx); - rc = rng_put(&r->buf, b); - cnt = rng_count(&r->buf); - pthread_mutex_unlock(&r->buf_mtx); - if (!rc) - error("mouse queue overflow\n"); - if (cnt == 1) - r->callback(*r->arg_p); -} - -#define MOUSE_BO(n, DEF, ...) \ -static void fifo_mdrv_##n DEF \ -{ \ - struct mbuf_s b = { MID_##n, {__VA_ARGS__} }; \ - fifo_mdrv_add(udata, &b); \ -} - -MOUSE_BO(move_button, (int num, int press, void *udata), - num, press) -MOUSE_BO(move_buttons, (int lbutton, int mbutton, int rbutton, void *udata), - lbutton, mbutton, rbutton) -MOUSE_BO(move_wheel, (int dy, void *udata), dy) -MOUSE_BO(move_relative, (int dx, int dy, int x_range, int y_range, - void *udata), - dx, dy, x_range, y_range) -MOUSE_BO(move_mickeys, (int dx, int dy, void *udata), dx, dy) -MOUSE_BO(move_absolute, (int x, int y, int x_range, int y_range, int vis, - void *udata), - x, y, x_range, y_range, vis) -MOUSE_BO(drag_to_corner, (int x_range, int y_range, void *udata), - x_range, y_range) -MOUSE_BO(enable_native_cursor, (int flag, void *udata), flag) - -struct mouse_drv fifo_mdrv = { - .move_button = fifo_mdrv_move_button, - .move_buttons = fifo_mdrv_move_buttons, - .move_wheel = fifo_mdrv_move_wheel, - .move_relative = fifo_mdrv_move_relative, - .move_mickeys = fifo_mdrv_move_mickeys, - .move_absolute = fifo_mdrv_move_absolute, - .drag_to_corner = fifo_mdrv_drag_to_corner, - .enable_native_cursor = fifo_mdrv_enable_native_cursor, - .name = "fifo helper", -}; - -static void fifo_mdrv_init(struct mouse_drv_wrp *m, void (*cb)(void *)) -{ -#define M_FIFO_LEN 1024 - m->bdrv.drv = &fifo_mdrv; - rng_init(&m->bdrv.buf, M_FIFO_LEN, sizeof(struct mbuf_s)); - pthread_mutex_init(&m->bdrv.buf_mtx, NULL); - m->bdrv.udata = &m->bdrv; - m->bdrv.callback = cb; - m->bdrv.arg_p = &m->udata; -} - -static int do_process_fifo(struct mouse_drv_wrp *m) -{ - int rc, ret; - struct mbuf_s b; - struct mouse_drv *d = m->drv; - - assert(m->bdrv.drv); - pthread_mutex_lock(&m->bdrv.buf_mtx); - rc = rng_get(&m->bdrv.buf, &b); - ret = rng_count(&m->bdrv.buf); - pthread_mutex_unlock(&m->bdrv.buf_mtx); - if (!rc) - return -1; - switch (b.id) { -#define MP(n, ...) \ - case MID_##n: \ - d->n(__VA_ARGS__, m->udata); \ - break - - MP(move_button, b.args[0], b.args[1]); - MP(move_buttons, b.args[0], b.args[1], b.args[2]); - MP(move_wheel, b.args[0]); - MP(move_relative, b.args[0], b.args[1], b.args[2], b.args[3]); - MP(move_mickeys, b.args[0], b.args[1]); - MP(move_absolute, b.args[0], b.args[1], b.args[2], b.args[3], b.args[4]); - MP(drag_to_corner, b.args[0], b.args[1]); - MP(enable_native_cursor, b.args[0]); - } - return ret; -} - -int mousedrv_process_fifo(const char *name) -{ - struct mouse_drv_wrp *m; - for (m = mdrv; m; m = m->next) { - if (strcmp(name, m->drv->name) == 0) - return do_process_fifo(m); - } - return 0; -} - -void register_mouse_driver_buffered(struct mouse_drv *mouse, - void (*cb)(void *)) -{ - struct mouse_drv_wrp *m, *ms; - - ms = do_create_driver(mouse); - fifo_mdrv_init(ms, cb); - if (mdrv == NULL) { - mdrv = ms; - } else { - for (m = mdrv; m->next; m = m->next); - m->next = ms; - } -} - static int none_init(void) { return TRUE; @@ -296,35 +141,36 @@ void dosemu_mouse_init(void) mouse_client_init(); } -#define MOUSE_DO(n, DEF, ...) \ +#define AR(...) (__VA_ARGS__, m->udata) +#define _MOUSE_DO(n, DEF, ARGS) \ void mouse_##n DEF \ { \ struct mouse_drv_wrp *m; \ for (m = mdrv; m; m = m->next) { \ - struct mouse_drv *d, *b; \ - void *ud; \ + struct mouse_drv *d; \ if (!m->initialized) \ continue; \ d = m->drv; \ - b = m->bdrv.drv ?: d; \ - ud = m->bdrv.drv ? m->bdrv.udata : m->udata; \ if (d->n && d->accepts(from, m->udata)) \ - b->n(__VA_ARGS__, ud); \ + d->n ARGS; \ } \ } -MOUSE_DO(move_button, (int num, int press, int from), num, press) +#define MOUSE_DO(n, DEF, ARGS) _MOUSE_DO(n, DEF, AR ARGS) +#define MOUSE_DO0(n) _MOUSE_DO(n, (void), ()) +MOUSE_DO(move_button, (int num, int press, int from), + (num, press)) MOUSE_DO(move_buttons, (int lbutton, int mbutton, int rbutton, int from), - lbutton, mbutton, rbutton) -MOUSE_DO(move_wheel, (int dy, int from), dy) + (lbutton, mbutton, rbutton)) +MOUSE_DO(move_wheel, (int dy, int from), (dy)) MOUSE_DO(move_relative, (int dx, int dy, int x_range, int y_range, int from), - dx, dy, x_range, y_range) -MOUSE_DO(move_mickeys, (int dx, int dy, int from), dx, dy) + (dx, dy, x_range, y_range)) +MOUSE_DO(move_mickeys, (int dx, int dy, int from), (dx, dy)) MOUSE_DO(move_absolute, (int x, int y, int x_range, int y_range, int vis, int from), - x, y, x_range, y_range, vis) + (x, y, x_range, y_range, vis)) MOUSE_DO(drag_to_corner, (int x_range, int y_range, int from), - x_range, y_range) -MOUSE_DO(enable_native_cursor, (int flag, int from), flag) + (x_range, y_range)) +MOUSE_DO(enable_native_cursor, (int flag, int from), (flag)) int mousedrv_accepts(const char *id, int from) { @@ -343,7 +189,7 @@ int mousedrv_accepts(const char *id, int from) } #define DID(...) (__VA_ARGS__, const char *id) -#define MOUSE_ID_DO(n, DEF, ...) \ +#define MOUSE_ID_DO(n, DEF, ARGS) \ void mouse_##n##_id DID DEF \ { \ struct mouse_drv_wrp *m; \ @@ -354,15 +200,15 @@ void mouse_##n##_id DID DEF \ d = m->drv; \ if (strcmp(d->name, id) != 0) \ continue; \ - /* not checking for .accepts */ \ + /* not checking for .accpets */ \ if (d->n) \ - d->n(__VA_ARGS__, m->udata); \ + d->n AR ARGS; \ } \ } MOUSE_ID_DO(move_button, (int num, int press), - num, press) + (num, press)) MOUSE_ID_DO(move_buttons, (int lbutton, int mbutton, int rbutton), - lbutton, mbutton, rbutton) -MOUSE_ID_DO(move_wheel, (int dy), dy) -MOUSE_ID_DO(move_mickeys, (int dx, int dy), dx, dy) -MOUSE_ID_DO(enable_native_cursor, (int flag), flag) + (lbutton, mbutton, rbutton)) +MOUSE_ID_DO(move_wheel, (int dy), (dy)) +MOUSE_ID_DO(move_mickeys, (int dx, int dy), (dx, dy)) +MOUSE_ID_DO(enable_native_cursor, (int flag), (flag)) diff --git a/src/base/mouse/mouseint.c b/src/base/mouse/mouseint.c index 1425c98..750f41e 100644 --- a/src/base/mouse/mouseint.c +++ b/src/base/mouse/mouseint.c @@ -44,7 +44,6 @@ #include "mouse.h" #include "serial.h" #include "iodev.h" -#include "ioselect.h" static void DOSEMUSetMouseSpeed(int old, int _new, unsigned cflag); @@ -448,7 +447,7 @@ static void DOSEMUSetMouseSpeed(int old, int _new, unsigned cflag) } } -static void raw_mouse_getevent(int fd, void *arg) +static void raw_mouse_getevent(void *arg) { #define MOUSE_BUFFER 8 unsigned char rBuf[MOUSE_BUFFER]; @@ -457,7 +456,6 @@ static void raw_mouse_getevent(int fd, void *arg) int nBytes; nBytes = RPT_SYSCALL(read(mice->fd, rBuf, MOUSE_BUFFER)); - ioselect_complete(fd); if (nBytes <= 0) return; m_printf("MOUSE: Read %d bytes.\n", nBytes); diff --git a/src/base/serial/Makefile b/src/base/serial/Makefile index a21c3f3..368e70d 100644 --- a/src/base/serial/Makefile +++ b/src/base/serial/Makefile @@ -7,7 +7,7 @@ include $(top_builddir)/Makefile.conf #The C files, include files and dependancies here. CFILES = ser_init.c ser_irq.c ser_ports.c int14.c fossil.c tty_io.c \ - sermouse.c commouse.c comredir.c nullmm.c + sermouse.c commouse.c DEPENDS=$(CFILES:.c=.d) HFILES = ser_defs.h diff --git a/src/base/serial/commouse.c b/src/base/serial/commouse.c index 7c84943..325f87f 100644 --- a/src/base/serial/commouse.c +++ b/src/base/serial/commouse.c @@ -30,8 +30,21 @@ #include "coopth.h" #include "ser_defs.h" +#define read_reg(num, offset) do_serial_in((num), com_cfg[(num)].base_port + (offset)) +#define read_char(num) read_reg((num), UART_RX) +#define read_LCR(num) read_reg((num), UART_LCR) +#define read_LSR(num) read_reg((num), UART_LSR) +#define read_IIR(num) read_reg((num), UART_IIR) +#define write_reg(num, offset, byte) do_serial_out((num), com_cfg[(num)].base_port + (offset), (byte)) +#define write_char(num, byte) write_reg((num), UART_TX, (byte)) +#define write_DLL(num, byte) write_reg((num), UART_DLL, (byte)) +#define write_DLM(num, byte) write_reg((num), UART_DLM, (byte)) +#define write_FCR(num, byte) write_reg((num), UART_FCR, (byte)) +#define write_LCR(num, byte) write_reg((num), UART_LCR, (byte)) +#define write_MCR(num, byte) write_reg((num), UART_MCR, (byte)) +#define write_IER(num, byte) write_reg((num), UART_IER, (byte)) + #define _com_num config.mouse.com -#define COM_INTR COM_INTERRUPT(_com_num) static u_short irq_hlt; static void com_irq(Bit16u idx, HLT_ARG(arg)); @@ -41,8 +54,11 @@ static int com_mouse_init(void) int num; if (config.mouse.com_num == -1 || !config.mouse.intdrv) return 0; - num = get_com_idx(config.mouse.com_num); - if (num == -1) + for (num = 0; num < config.num_ser; num++) { + if (com_cfg[num].real_comport == config.mouse.com_num) + break; + } + if (num >= config.num_ser) return 0; _com_num = num; @@ -65,7 +81,7 @@ static void com_irq(Bit16u idx, HLT_ARG(arg)) while (read_LSR(_com_num) & UART_LSR_DR) { val = read_char(_com_num); /* - * talk to int33 explicitly as we don't want to talk + * talk to int33 explicitly as we dont want to talk * to for example sermouse.c */ DOSEMUMouseProtocol(&val, 1, MOUSE_MS3BUTTON, "int33 mouse"); @@ -81,7 +97,7 @@ static void com_irq(Bit16u idx, HLT_ARG(arg)) static int get_char(int num) { - LWORD(edx) = com_cfg[num].real_comport - 1; + LWORD(edx) = com_cfg[_com_num].real_comport - 1; HI(ax) = 2; LO(ax) = 0; do_int_call_back(0x14); @@ -149,7 +165,7 @@ static int com_mouse_reset(void) return -1; } - SETIVEC(COM_INTR, BIOS_HLT_BLK_SEG, irq_hlt); + SETIVEC(com[_com_num].interrupt, BIOS_HLT_BLK_SEG, irq_hlt); write_MCR(_com_num, com[_com_num].MCR | UART_MCR_OUT2); imr = imr1 = port_inb(0x21); imr &= ~(1 << com_cfg[_com_num].irq); @@ -168,8 +184,8 @@ static void com_mouse_post_init(void) if (_com_num == -1) return; mouse_enable_native_cursor_id(1, "int33 mouse"); - com[_com_num].ivec.segment = ISEG(COM_INTR); - com[_com_num].ivec.offset = IOFF(COM_INTR); + com[_com_num].ivec.segment = ISEG(com[_com_num].interrupt); + com[_com_num].ivec.offset = IOFF(com[_com_num].interrupt); com_mouse_reset(); } diff --git a/src/base/serial/comredir.c b/src/base/serial/comredir.c deleted file mode 100644 index 19190a2..0000000 --- a/src/base/serial/comredir.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: com port redirect to console - * - * Author: stsp - */ -#include -#include -#include -#include - -#include "emu.h" -#include "hlt.h" -#include "int.h" -#include "coopth.h" -#include "port.h" -#include "keyboard/keyb_server.h" -#include "dos2linux.h" -#include "serial.h" -#include "ser_defs.h" -#include "comredir.h" - -static int com_num; -static int com_num_wr; -static far_t old_ivec; -static u_short irq_hlt; -static int redir_tid; -static void comredir_thr(void *arg); -static far_t old_int15; -static u_short int15_hlt; -static int int15_tid; -static void int15_thr(void *arg); -static void int15_irq(Bit16u idx, HLT_ARG(arg)); -static far_t old_int10; -static void int10_irq(Bit16u idx, HLT_ARG(arg)); -static u_short int10_hlt; -static unsigned tflags; -// suppress output -#define TFLG_SUPPR 1 -// append NL to CR on output -#define TFLG_OANL 2 -// prepend CR to NL on output -#define TFLG_OPCR 4 -// append NL to CR on input -#define TFLG_IANL 8 -// prepend CR to NL on input -#define TFLG_IPCR 0x10 - -void comredir_init(void) -{ - emu_hlt_t hlt_hdlr = HLT_INITIALIZER; - hlt_hdlr.name = "comint15 isr"; - hlt_hdlr.func = int15_irq; - hlt_hdlr.len = 1; - int15_hlt = hlt_register_handler_vm86(hlt_hdlr); - hlt_hdlr.name = "comint10 isr"; - hlt_hdlr.func = int10_irq; - hlt_hdlr.len = 1; - int10_hlt = hlt_register_handler_vm86(hlt_hdlr); - - redir_tid = coopth_create_vm86("comredir thr", comredir_thr, do_eoi_iret, - &irq_hlt); - int15_tid = coopth_create("comint15 thr", int15_thr); -} - -void comredir_setup(int num, int num_wr, unsigned flags) -{ - int i = -1, j = -1; - if (num > 0 && num <= 4) { - struct vm86_regs saved_regs = REGS; - int intr; - unsigned char imr, imr1; - - if (com_num) { - com_printf("comredir is already active\n"); - return; - } - i = get_com_idx(num); - if (i == -1) { - com_printf("comredir: com port %i not configured\n", num); - return; - } - j = get_com_idx(num_wr); - if (j == -1) { - com_printf("comredir: com port %i not configured\n", num_wr); - return; - } - intr = COM_INTERRUPT(i); - old_ivec.segment = ISEG(intr); - old_ivec.offset = IOFF(intr); - SETIVEC(intr, BIOS_HLT_BLK_SEG, irq_hlt); - - _AX = 0b11100011; // 8N1 - _DX = i; - do_int_call_back(0x14); - if (num_wr != num) { - _AX = 0b11100011; // 8N1 - _DX = num_wr - 1; - do_int_call_back(0x14); - } - REGS = saved_regs; - write_MCR(i, com[i].MCR | UART_MCR_OUT2); - write_IER(i, UART_IER_RDI); - - imr = imr1 = port_inb(0x21); - imr &= ~(1 << com_cfg[i].irq); - if (imr != imr1) - port_outb(0x21, imr); - - old_int15.segment = ISEG(0x15); - old_int15.offset = IOFF(0x15); - if (num_wr) - SETIVEC(0x15, BIOS_HLT_BLK_SEG, int15_hlt); - - old_int10.segment = ISEG(0x10); - old_int10.offset = IOFF(0x10); - if (flags & TFLG_SUPPR) - SETIVEC(0x10, BIOS_HLT_BLK_SEG, int10_hlt); - } else { - if (!com_num) - return; - int intr = COM_INTERRUPT(com_num - 1); - write_IER(com_num - 1, 0); - SETIVEC(intr, old_ivec.segment, old_ivec.offset); - SETIVEC(0x15, old_int15.segment, old_int15.offset); - SETIVEC(0x10, old_int10.segment, old_int10.offset); - } - com_num = i + 1; - com_num_wr = j + 1; - tflags = flags; -} - -void comredir_reset(void) -{ - com_num = 0; -} - -static void do_int10(void) -{ - unsigned int ssp, sp; - - ssp = SEGOFF2LINEAR(SREG(ss), 0); - sp = LWORD(esp); - pushw(ssp, sp, LWORD(eflags)); - LWORD(esp) -= 2; - do_call_back(old_int10.segment, old_int10.offset); -} - -static void do_char_out(char out) -{ - _AH = 0x0e; - _AL = out; - _BX = 0; - do_int10(); -} - -static void comredir_thr(void *arg) -{ - int i = com_num - 1; - uint8_t iir; - - s_printf("comredir: got irq\n"); - iir = read_IIR(i); - switch (iir & UART_IIR_CND_MASK) { - case UART_IIR_NO_INT: - break; - case UART_IIR_RDI: { - struct vm86_regs saved_regs = REGS; - while (read_LSR(i) & UART_LSR_DR) { - unsigned char c = read_char(i); - if ((tflags & TFLG_IPCR) && c == '\n') - do_char_out('\r'); - do_char_out(c); - if ((tflags & TFLG_IANL) && c == '\r') - do_char_out('\n'); - if (c == 0x1a) // ^Z, exit - comredir_setup(0, 0, 0); - } - REGS = saved_regs; - break; - } - default: - s_printf("comredir: unexpected interrupt cond %#x\n", iir); - break; - } -} - -static void int15_thr(void *arg) -{ - unsigned int ssp, sp; - - ssp = SEGOFF2LINEAR(SREG(ss), 0); - sp = LWORD(esp); - pushw(ssp, sp, LWORD(eflags)); - LWORD(esp) -= 2; - do_call_back(old_int15.segment, old_int15.offset); - if (!isset_CF()) - return; - clear_CF(); - if (!(_AL & 0x80)) { - unsigned char c = get_bios_key(_AL); - if (!c) { - set_CF(); - return; - } - if ((tflags & TFLG_OPCR) && c == '\n') - write_char(com_num_wr - 1, '\r'); - write_char(com_num_wr - 1, c); - if ((tflags & TFLG_OANL) && c == '\r') - write_char(com_num_wr - 1, '\n'); - if (c == 0x1a) { // ^Z, exit - do_char_out(c); - comredir_setup(0, 0, 0); - } - } else { - set_CF(); - } -} - -static void int15_irq(Bit16u idx, HLT_ARG(arg)) -{ - if (_AH != 0x4f) { - jmp_to(old_int15.segment, old_int15.offset); - return; - } - fake_iret(); - coopth_start(int15_tid, NULL); -} - -static void int10_irq(Bit16u idx, HLT_ARG(arg)) -{ - /* suppress console output */ - if (_AH == 9 || _AH == 0xe || _AH == 0x13 || _AH == 2) { - fake_iret(); - return; - } - jmp_to(old_int10.segment, old_int10.offset); -} diff --git a/src/base/serial/comredir.h b/src/base/serial/comredir.h deleted file mode 100644 index 96e7c76..0000000 --- a/src/base/serial/comredir.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef COMREDIR_H -#define COMREDIR_H - -void comredir_init(void); -void comredir_setup(int num, int num_wr, unsigned flags); -void comredir_reset(void); - -#endif diff --git a/src/base/serial/fossil.c b/src/base/serial/fossil.c index 4916f45..2d64b65 100644 --- a/src/base/serial/fossil.c +++ b/src/base/serial/fossil.c @@ -28,9 +28,35 @@ #include "utilities.h" #include "serial.h" #include "ser_defs.h" -#include "comredir.h" + #include "doshelpers.h" +/* These macros are shortcuts to access various serial port registers + * read_char Read character + * read_LCR Read Line Control Register + * read_MCR Read Modem Control Register + * write_char Transmit character + * write_DLL Write Baudrate Divisor Latch LSB value + * write_DLM Write Baudrate Divisor Latch MSB value + * write_FCR Write FIFO Control Register + * write_LCR Write Line Control Register + * write_MCR Write Modem Control Register + */ +#define read_reg(num, offset) do_serial_in((num), com_cfg[(num)].base_port + (offset)) +#define read_char(num) read_reg((num), UART_RX) +#define read_LCR(num) read_reg((num), UART_LCR) +#define read_MCR(num) read_reg((num), UART_MCR) +#define read_LSR(num) read_reg((num), UART_LSR) +#define read_IIR(num) read_reg((num), UART_IIR) +#define write_reg(num, offset, byte) do_serial_out((num), com_cfg[(num)].base_port + (offset), (byte)) +#define write_char(num, byte) write_reg((num), UART_TX, (byte)) +#define write_DLL(num, byte) write_reg((num), UART_DLL, (byte)) +#define write_DLM(num, byte) write_reg((num), UART_DLM, (byte)) +#define write_FCR(num, byte) write_reg((num), UART_FCR, (byte)) +#define write_LCR(num, byte) write_reg((num), UART_LCR, (byte)) +#define write_MCR(num, byte) write_reg((num), UART_MCR, (byte)) +#define write_IER(num, byte) write_reg((num), UART_IER, (byte)) + /* Get the LSR/MSR status bits in FOSSIL format. Since we don't care about * the delta/interrupt bits anyway, reading the com[] structure is * faster than calling do_serial_in. @@ -58,18 +84,12 @@ boolean fossil_initialised = FALSE; static u_short irq_hlt; static void fossil_irq(Bit16u idx, HLT_ARG(arg)); -void fossil_init(void) +static void fossil_init(void) { emu_hlt_t hlt_hdlr = HLT_INITIALIZER; hlt_hdlr.name = "fossil isr"; hlt_hdlr.func = fossil_irq; - hlt_hdlr.len = 2; irq_hlt = hlt_register_handler_vm86(hlt_hdlr); -} - -static void fossil_setup(void) -{ - int i; fossil_initialised = TRUE; @@ -83,20 +103,15 @@ static void fossil_setup(void) // Out SREG(ds) = FOSSIL_SEG; LWORD(edx) = FOSSIL_isr; - - for (i = 0; i < config.num_ser; i++) - com[i].fossil_active = FALSE; } static void fossil_irq(Bit16u idx, HLT_ARG(arg)) { int i; uint8_t iir, lsr; - int inum = idx + 3; - - s_printf("FOSSIL: got irq %i\n", inum); + s_printf("FOSSIL: got irq\n"); for (i = 0; i < config.num_ser; i++) { - if (com[i].opened <= 0 || com_cfg[i].irq != inum) + if (com[i].opened <= 0) continue; iir = read_IIR(i); switch (iir & UART_IIR_CND_MASK) { @@ -171,7 +186,7 @@ void fossil_int14(int num) /* the previous read was probably interrupted by ^C... */ s_printf("SER%d: FOSSIL 0x02: Read with wait interrupted??\n", num); coopth_ensure_sleeping(com[num].fossil_blkrd_tid); - /* to avoid resource leakage, we just kill it the unsafe way */ + /* to avoid resouce leakage, we just kill it the unsafe way */ coopth_cancel(com[num].fossil_blkrd_tid); coopth_unsafe_detach(com[num].fossil_blkrd_tid, __FILE__); com[num].fossil_blkrd_tid = COOPTH_TID_INVALID; @@ -201,18 +216,12 @@ void fossil_int14(int num) case 0x1c: { uint8_t imr, imr1; fossil_info_t *fi; - int ioff = com_cfg[num].irq - 3; - int inum = COM_INTERRUPT(num); assert(sizeof(*fi) == 19); - /* Do nothing if TSR isn't installed or already initialized. */ - if (!fossil_initialised || com[num].fossil_active) + /* Do nothing if TSR isn't installed. */ + if (!fossil_initialised) return; - if (ioff > 1) { - error("COM%i irq misconfigured, %i\n", num, com_cfg[num].irq); - return; - } com[num].fossil_active = TRUE; LWORD(eax) = FOSSIL_MAGIC; HI(bx) = FOSSIL_REVISION; @@ -226,16 +235,13 @@ void fossil_int14(int num) /* init IRQs, set disabled */ write_MCR(num, com[num].MCR | UART_MCR_OUT2); write_IER(num, 0); - /* interrupts are shared, don't set twice */ - if (ISEG(inum) != BIOS_HLT_BLK_SEG || IOFF(inum) != irq_hlt + ioff) { - com[num].ivec.segment = ISEG(inum); - com[num].ivec.offset = IOFF(inum); - SETIVEC(inum, BIOS_HLT_BLK_SEG, irq_hlt + ioff); - imr = imr1 = port_inb(0x21); - imr &= ~(1 << com_cfg[num].irq); - if (imr != imr1) + com[num].ivec.segment = ISEG(com[num].interrupt); + com[num].ivec.offset = IOFF(com[num].interrupt); + SETIVEC(com[num].interrupt, BIOS_HLT_BLK_SEG, irq_hlt); + imr = imr1 = port_inb(0x21); + imr &= ~(1 << com_cfg[num].irq); + if (imr != imr1) port_outb(0x21, imr); - } com[num].fossil_blkrd_tid = COOPTH_TID_INVALID; /* Initialize FOSSIL driver info. This is used by the function 0x1b @@ -267,7 +273,7 @@ void fossil_int14(int num) imr = port_inb(0x21); imr |= (1 << com_cfg[num].irq); port_outb(0x21, imr); - SETIVEC(COM_INTERRUPT(num), com[num].ivec.segment, com[num].ivec.offset); + SETIVEC(com[num].interrupt, com[num].ivec.segment, com[num].ivec.offset); com[num].fossil_active = FALSE; /* Note: the FIFO values aren't restored. Hopefully nobody notices... */ s_printf("SER%d: FOSSIL 0x%02x: Emulation deactivated\n", num, req); @@ -592,16 +598,12 @@ void serial_helper(void) old_seg = SREG(es); old_off = LWORD(ebx); - fossil_setup(); + fossil_init(); NOCARRY; s_printf("SER: FOSSIL: installation, ES:BX=%04x:%04x => DS:DX=%04x:%04x\n", old_seg, old_off, SREG(ds), LWORD(edx)); break; - case DOS_SUBHELPER_SERIAL_COMREDIR_INIT: - comredir_setup(_BL, _CL, _CH); - break; - default: s_printf("SER: FOSSIL helper 0x%02x: Unknown function!\n", HI(ax)); } diff --git a/src/base/serial/int14.c b/src/base/serial/int14.c index 22cd58b..de50fb3 100644 --- a/src/base/serial/int14.c +++ b/src/base/serial/int14.c @@ -36,6 +36,29 @@ #include "timers.h" #include "coopth.h" +/* These macros are shortcuts to access various serial port registers: + * read_char Read character + * read_LCR Read Line Control Register + * read_LSR Read Line Status Register + * read_MSR Read Modem Status Register + * write_char Transmit character + * write_DLL Write Baudrate Divisor Latch LSB value + * write_DLM Write Baudrate Divisor Latch MSB value + * write_LCR Write Line Control Register + * write_MCR Write Modem Control Register + */ +#define read_char(num) do_serial_in(num, com_cfg[num].base_port) +#define read_LCR(num) do_serial_in(num, com_cfg[num].base_port + 3) +#define read_MCR(num) do_serial_in(num, com_cfg[num].base_port + 4) +#define read_LSR(num) do_serial_in(num, com_cfg[num].base_port + 5) +#define read_MSR(num) do_serial_in(num, com_cfg[num].base_port + 6) +#define write_char(num, byte) do_serial_out(num, com_cfg[num].base_port, byte) +#define write_DLL(num, byte) do_serial_out(num, com_cfg[num].base_port, byte) +#define write_DLM(num, byte) do_serial_out(num, com_cfg[num].base_port + 1, byte) +#define write_LCR(num, byte) do_serial_out(num, com_cfg[num].base_port + 3, byte) +#define write_MCR(num, byte) do_serial_out(num, com_cfg[num].base_port + 4, byte) + + /* The following function sets the speed of the serial port. * num is the index, and speed is a baudrate divisor value. */ @@ -63,11 +86,12 @@ int int14(void) int temp; /* Translate the requested COM port number in the DL register, into - * the necessary arbitrary port number system used throughout this module. + * the necessary arbritary port number system used throughout this module. */ - num = get_com_idx(LO(dx)+1); - if (num == -1) - return 1; /* Exit if not on supported port */ + for(num = 0; num < config.num_ser; num++) + if (com_cfg[num].real_comport == (LO(dx)+1)) break; + + if (num >= config.num_ser) return 1; /* Exit if not on supported port */ switch (HI(ax)) { case 0: /* Initialize serial port. */ diff --git a/src/base/serial/nullmm.c b/src/base/serial/nullmm.c deleted file mode 100644 index e0c8ffb..0000000 --- a/src/base/serial/nullmm.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Null-modem connection - * - * Author: stsp - */ -#include -#include "emu.h" -#include "init.h" -#include "utilities.h" -#include "ser_defs.h" -#include "nullmm.h" - -static int add_buf(com_t *c, const char *buf, int len) -{ - if (RX_BUF_BYTES(c->num) + len > RX_BUFFER_SIZE) { - if(s3_printf) s_printf("SER%d: Too many bytes (%i) in buffer\n", c->num, - RX_BUF_BYTES(c->num)); - return 0; - } - - /* Slide the buffer contents to the bottom */ - rx_buffer_slide(c->num); - - memcpy(&c->rx_buf[c->rx_buf_end], buf, len); - if (debug_level('s') >= 9) { - int i; - for (i = 0; i < len; i++) - s_printf("SER%d: Got mouse data byte: %#x\n", c->num, - c->rx_buf[c->rx_buf_end + i]); - } - c->rx_buf_end += len; - receive_engine(c->num, len); - return len; -} - -static void nullmm_rx_buffer_dump(com_t *c) -{ -} - -static void nullmm_tx_buffer_dump(com_t *c) -{ -} - -static int nullmm_get_tx_queued(com_t *c) -{ - return 0; -} - -static void nullmm_termios(com_t *c) -{ -} - -static int nullmm_brkctl(com_t *c, int flag) -{ - return 0; -} - -static ssize_t nullmm_write(com_t *c, char *buf, size_t len) -{ - int idx = get_com_idx(c->cfg->nullmm); - if (idx == -1) - return -1; - return add_buf(&com[idx], buf, len); -} - -static int nullmm_dtr(com_t *c, int flag) -{ - return 0; -} - -static int nullmm_rts(com_t *c, int flag) -{ - return 0; -} - -static int nullmm_open(com_t *c) -{ - return 1; -} - -static int nullmm_close(com_t *c) -{ - return 0; -} - -static int nullmm_uart_fill(com_t *c) -{ - return 0; -} - -static int nullmm_get_msr(com_t *c) -{ - com_t *c2; - int idx = get_com_idx(c->cfg->nullmm); - if (idx == -1) - return -1; - c2 = &com[idx]; - unsigned char msr = UART_MSR_DCD; - if (c2->MCR & UART_MCR_DTR) - msr |= UART_MSR_DSR; - if (c2->MCR & UART_MCR_RTS) - msr |= UART_MSR_CTS; - return msr; -} - - -struct serial_drv nullmm_drv = { - nullmm_rx_buffer_dump, - nullmm_tx_buffer_dump, - nullmm_get_tx_queued, - nullmm_termios, - nullmm_brkctl, - nullmm_write, - nullmm_dtr, - nullmm_rts, - nullmm_open, - nullmm_close, - nullmm_uart_fill, - nullmm_get_msr, - "serial_mouse_tty" -}; diff --git a/src/base/serial/nullmm.h b/src/base/serial/nullmm.h deleted file mode 100644 index 1d25139..0000000 --- a/src/base/serial/nullmm.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef NULLMM_H -#define NULLMM_H - -extern struct serial_drv nullmm_drv; - -#endif diff --git a/src/base/serial/ser_defs.h b/src/base/serial/ser_defs.h index dcefd4d..410c36b 100644 --- a/src/base/serial/ser_defs.h +++ b/src/base/serial/ser_defs.h @@ -69,6 +69,7 @@ * config.num_ser Number of serial ports active. * com[x].base_port The base port address of emulated serial port. * com[x].real_comport The COM port number. + * com[x].interrupt The PIC interrupt level (based on IRQ number) * com[x].mouse Flag mouse (to enable extended features) * com[x].fd File descriptor for port device * com[x].dev[] Filename of port port device @@ -335,13 +336,11 @@ typedef struct { int num; int fd; /* File descriptor of device */ int opened; - int wr_fd; boolean is_file; - boolean is_closed; + boolean ro; boolean dev_locked; /* Flag to indicate that device is locked */ boolean fossil_active; /* Flag: FOSSIL emulation active */ fossil_info_t fossil_info; /* FOSSIL driver info structure */ - pid_t pty_pid; struct vec_t ivec; /* MODEM STATUS */ // long int ms_freq; /* Frequency of Modem Status (MS) check */ @@ -352,6 +351,7 @@ typedef struct { u_char rx_fifo_trigger; /* Receive Fifo trigger value */ int rx_fifo_size; /* Size of receive FIFO to emulate */ /* MISCELLANEOUS */ + int interrupt; /* IRQ line handled by device */ u_char int_condition; /* Interrupt Condition flags - TX/RX/MS/LS */ /* The following are serial port registers */ @@ -403,6 +403,7 @@ int convert_bit(int, int, int); void serial_int_engine(int, int); void serial_timer_update(void); void uart_clear_fifo(int, int); +int pic_serial_run(int); void fossil_int14(int); void ser_termios(int num); void modstat_engine(int num); @@ -428,42 +429,20 @@ int ser_close(int num); int uart_fill(int num); int serial_get_msr(int num); -void fossil_init(void); - struct serial_drv { - void (*rx_buffer_dump)(com_t *c); - void (*tx_buffer_dump)(com_t *c); - int (*serial_get_tx_queued)(com_t *c); - void (*ser_termios)(com_t *c); - int (*serial_brkctl)(com_t *c, int brkflg); - ssize_t (*serial_write)(com_t *c, char *buf, size_t len); - int (*serial_dtr)(com_t *c, int flag); - int (*serial_rts)(com_t *c, int flag); - int (*ser_open)(com_t *c); - int (*ser_close)(com_t *c); - int (*uart_fill)(com_t *c); - int (*serial_get_msr)(com_t *c); + void (*rx_buffer_dump)(com_t *com); + void (*tx_buffer_dump)(com_t *com); + int (*serial_get_tx_queued)(com_t *com); + void (*ser_termios)(com_t *com); + int (*serial_brkctl)(com_t *com, int brkflg); + ssize_t (*serial_write)(com_t *com, char *buf, size_t len); + int (*serial_dtr)(com_t *com, int flag); + int (*serial_rts)(com_t *com, int flag); + int (*ser_open)(com_t *com); + int (*ser_close)(com_t *com); + int (*uart_fill)(com_t *com); + int (*serial_get_msr)(com_t *com); const char *name; }; -#define COM_INTERRUPT(num) (com_cfg[num].irq + 8) - -#define read_reg(num, offset) do_serial_in((num), com_cfg[(num)].base_port + (offset)) -#define read_char(num) read_reg((num), UART_RX) -#define read_LCR(num) read_reg((num), UART_LCR) -#define read_MCR(num) read_reg((num), UART_MCR) -#define read_LSR(num) read_reg((num), UART_LSR) -#define read_MSR(num) read_reg((num), UART_MSR) -#define read_IIR(num) read_reg((num), UART_IIR) -#define write_reg(num, offset, byte) do_serial_out((num), com_cfg[(num)].base_port + (offset), (byte)) -#define write_char(num, byte) write_reg((num), UART_TX, (byte)) -#define write_DLL(num, byte) write_reg((num), UART_DLL, (byte)) -#define write_DLM(num, byte) write_reg((num), UART_DLM, (byte)) -#define write_FCR(num, byte) write_reg((num), UART_FCR, (byte)) -#define write_LCR(num, byte) write_reg((num), UART_LCR, (byte)) -#define write_MCR(num, byte) write_reg((num), UART_MCR, (byte)) -#define write_IER(num, byte) write_reg((num), UART_IER, (byte)) - -int get_com_idx(int num); - #endif /* SER_DEFS_H */ diff --git a/src/base/serial/ser_init.c b/src/base/serial/ser_init.c index 6c40d75..56ca247 100644 --- a/src/base/serial/ser_init.c +++ b/src/base/serial/ser_init.c @@ -46,12 +46,11 @@ #include "sermouse.h" #include "utilities.h" /* due to getpwnam */ #include "iodev.h" -#include "comredir.h" -#include "nullmm.h" int no_local_video = 0; serial_t com_cfg[MAX_SER]; com_t com[MAX_SER]; +static u_char irq_source_num[255]; /* Index to map from IRQ no. to serial port */ struct ser_dmx { ioport_t port; Bit8u def_val; @@ -84,7 +83,7 @@ static void add_dmx(ioport_t port, int val) sprintf(dmxs[i].name, "ser_dmx_%hhi", (uint8_t)i); } -static Bit8u dmx_readb(ioport_t port, void *arg) +static Bit8u dmx_readb(ioport_t port) { int num, i; Bit8u val; @@ -107,7 +106,7 @@ static Bit8u dmx_readb(ioport_t port, void *arg) return val; } -static void dmx_writeb(ioport_t port, Bit8u value, void *arg) +static void dmx_writeb(ioport_t port, Bit8u value) { s_printf("SER: write to readonly port %#x, val=%#x\n", port, value); } @@ -126,6 +125,8 @@ static int init_dmxs(void) io_device.write_portd = NULL; io_device.start_addr = dmxs[i].port; io_device.end_addr = dmxs[i].port; + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; io_device.handler_name = dmxs[i].name; port_register_handler(io_device, 0); s_printf("SER: added demux at port %#x\n", dmxs[i].port); @@ -183,8 +184,7 @@ static void ser_setup_custom(int num) } } -static Bit8u com_readb(ioport_t port, void *arg) -{ +static Bit8u com_readb(ioport_t port) { int tmp; for (tmp = 0; tmp < config.num_ser; tmp++) { if (((u_short)(port & ~7)) == com_cfg[tmp].base_port) { @@ -194,8 +194,7 @@ static Bit8u com_readb(ioport_t port, void *arg) return 0; } -static void com_writeb(ioport_t port, Bit8u value, void *arg) -{ +static void com_writeb(ioport_t port, Bit8u value) { int tmp; for (tmp = 0; tmp < config.num_ser; tmp++) { if (((u_short)(port & ~7)) == com_cfg[tmp].base_port) { @@ -261,6 +260,7 @@ static void do_ser_init(int num) /* Define it depending on using standard irqs */ com_cfg[num].irq = default_com[com_cfg[num].real_comport-1].irq; } + com[num].interrupt = pic_irq_list[com_cfg[num].irq]; if (com_cfg[num].base_port == 0) { /* Is base port undefined? */ /* Define it depending on using standard addrs */ @@ -284,6 +284,15 @@ static void do_ser_init(int num) /* FOSSIL emulation is inactive at startup. */ com[num].fossil_active = FALSE; + /* convert irq number to pic_ilevel number and set up interrupt + * if irq is invalid, no interrupt will be assigned + */ + if(!irq_source_num[com_cfg[num].irq]) { + s_printf("SER%d: enabling interrupt %d\n", num, com[num].interrupt); + pic_seti(com[num].interrupt, pic_serial_run, 0, NULL); + } + irq_source_num[com_cfg[num].irq]++; + /*** The following is where the real initialization begins ***/ /* Tell the port manager that we exist and that we're alive */ @@ -295,12 +304,15 @@ static void do_ser_init(int num) io_device.write_portd = NULL; io_device.start_addr = com_cfg[num].base_port; io_device.end_addr = com_cfg[num].end_port; + io_device.irq = (irq_source_num[com_cfg[num].irq] == 1 ? + com_cfg[num].irq : EMU_NO_IRQ); + io_device.fd = -1; io_device.handler_name = default_com[num].handler_name; port_register_handler(io_device, 0); /* Information about serial port added to debug file */ s_printf("SER%d: COM%d, intlevel=%d, base=0x%x, device=%s\n", - num, com_cfg[num].real_comport, com_cfg[num].irq, + num, com_cfg[num].real_comport, com[num].interrupt, com_cfg[num].base_port, com_cfg[num].dev); #if 0 /* first call to serial timer update func to initialize the timer */ @@ -321,7 +333,6 @@ void serial_reset(void) ser_reset_dev(num); fossil_initialised = FALSE; - comredir_reset(); } /* DANG_BEGIN_FUNCTION serial_run @@ -378,11 +389,9 @@ void serial_init(void) com[i].num = i; com[i].cfg = &com_cfg[i]; com[i].fd = -1; - com[i].wr_fd = -1; com[i].opened = 0; com[i].dev_locked = FALSE; - com[i].drv = com_cfg[i].mouse ? &serm_drv : - (com_cfg[i].nullmm ? &nullmm_drv : &tty_drv); + com[i].drv = com_cfg[i].mouse ? &serm_drv : &tty_drv; /* Serial port init is skipped if the port is used for a mouse, and * dosemu is running in Xwindows, or not at the console. This is due @@ -393,8 +402,7 @@ void serial_init(void) } init_dmxs(); - fossil_init(); - comredir_init(); + sigalrm_register_handler(serial_run); } @@ -417,15 +425,6 @@ void serial_close(void) } } -int get_com_idx(int num) -{ - int i; - for (i = 0; i < config.num_ser; i++) { - if (com[i].cfg->real_comport == num) - return i; - } - return -1; -} #define SER_FN0(rt, f) \ rt f(int num) \ diff --git a/src/base/serial/ser_irq.c b/src/base/serial/ser_irq.c index c8fd436..b498099 100644 --- a/src/base/serial/ser_irq.c +++ b/src/base/serial/ser_irq.c @@ -41,7 +41,7 @@ * In short, the serial timer ensures that the serial emulation runs * more smoothly, and does not put a heavy load on the system. */ -/* NOTE: with the async notifications we don't need that any more. +/* NOTE: with the async notifications we dont need that any more. * Disabled -- stsp */ #if 0 @@ -52,7 +52,7 @@ void serial_timer_update(void) unsigned long elapsed; /* No of 115200ths seconds elapsed */ int i; - /* Get system time. PLEASE DON'T CHANGE THIS LINE, unless you can + /* Get system time. PLEASE DONT CHANGE THIS LINE, unless you can * _guarantee_ that the substitute/stored timer value _is_ up to date * at _this_ instant! (i.e: vm86s exit time did not not work well) */ @@ -145,7 +145,7 @@ void transmit_engine(int num) /* Internal 16550 Transmission emulation */ * http://lkml.indiana.edu/hypermail/linux/kernel/1210.1/01456.html * Disable it for now. * - * ... and re-enable thanks to this patch: + * ... and reenable thanks to this patch: * https://lkml.org/lkml/2013/5/5/49 */ if (com[num].tx_cnt) @@ -199,14 +199,10 @@ void modstat_engine(int num) /* Internal Modem Status processing */ com[num].ms_timer += MS_MIN_FREQ; #endif - if(com_cfg[num].pseudo) { - if (com[num].is_closed) - newmsr = 0; - else - newmsr = UART_MSR_CTS | UART_MSR_DSR | UART_MSR_DCD; - } else { + if(com_cfg[num].pseudo) + newmsr = UART_MSR_CTS | UART_MSR_DSR | UART_MSR_DCD; + else newmsr = serial_get_msr(num); - } delta = msr_compute_delta_bits(com[num].MSR, newmsr); com[num].MSR = (com[num].MSR & UART_MSR_DELTA) | newmsr | delta; @@ -225,7 +221,7 @@ void modstat_engine(int num) /* Internal Modem Status processing */ * there will be justification for a simple Line Status housekeeping * function whose purpose is to detect an error condition (mainly a * break signal sent from the remote) and generate a hardware interrupt - * on its occurrence (RLSI). + * on its occurance (RLSI). * * DANG_BEGIN_REMARK * Linux code hackers: How do I detect a break signal without having @@ -247,12 +243,14 @@ void linestat_engine(int num) /* Internal Line Status processing */ * This function is the serial interrupts scheduler. Its purpose is to * update interrupt status and/or invoke a requested serial interrupt. * If interrupts are not enabled, the Interrupt Identification Register - * is still updated and the function returns. + * is still updated and the function returns. See pic_serial_run() below + * it is executed right at the instant the interrupt is actually invoked. * * Since it is not possible to run the interrupt on the spot, it triggers * the interrupt via the pic_request() function (which is in pic.c) * and sets a flag that an interrupt is going to be occur soon. * + * Please read pic_serial_run() for more information about interrupts. * [num = port, int_requested = the requested serial interrupt] * * DANG_END_FUNCTION @@ -278,15 +276,52 @@ void serial_int_engine(int num, int int_requested) /* See if a requested interrupt is enabled */ if (INT_ENAB(num) && INT_REQUEST(num)) { if(s3_printf) s_printf("SER%d: Func pic_request intlevel=%d, int_requested=%d\n", - num, com_cfg[num].irq, int_requested); - pic_request(com_cfg[num].irq); /* Flag PIC for interrupt */ + num, com[num].interrupt, int_requested); + pic_request(com[num].interrupt); /* Flag PIC for interrupt */ } else if(s3_printf) s_printf("SER%d: Interrupt %d (%d) cannot be requested: enable=%d IER=0x%x\n", - num, com_cfg[num].irq, com[num].int_condition, INT_ENAB(num), com[num].IER); + num, com[num].interrupt, com[num].int_condition, INT_ENAB(num), com[num].IER); } +/* DANG_BEGIN_FUNCTION pic_serial_run + * + * This function is called by the priority iunterrupt controller when a + * serial interrupt occurs. It executes the highest priority serial + * interrupt for that port. (Priority order is: RLSI, RDI, THRI, MSI) + * + * Because it is theoretically possible for things to change between the + * interrupt trigger and the actual interrupt, some checks must be + * repeated. + * + * DANG_END_FUNCTION + */ +int pic_serial_run(int ilevel) +{ + int i, ret = 0; + + for (i = 0; i < config.num_ser; i++) { + if (com[i].interrupt != ilevel) + continue; + if (INT_REQUEST(i)) + ret++; + } + + if(s2_printf) s_printf("SER: ---BEGIN INTERRUPT---\n"); + + if (!ret) { + s_printf("SER: Interrupt Error: cancelled serial interrupt!\n"); + /* No interrupt flagged? Then the interrupt was cancelled sometime + * after the interrupt was flagged, but before pic_serial_run executed. + * DANG_FIXTHIS how do we cancel a PIC interrupt, when we have come this far? + */ + } + return ret; +} + + + /**************************************************************************/ /* The MAIN ENGINE LOOP */ /**************************************************************************/ diff --git a/src/base/serial/ser_ports.c b/src/base/serial/ser_ports.c index 6bb81f2..5214c7f 100644 --- a/src/base/serial/ser_ports.c +++ b/src/base/serial/ser_ports.c @@ -29,7 +29,7 @@ /*************************************************************************/ -/* MISCELLANEOUS serial support functions */ +/* MISCELLANOUS serial support functions */ /*************************************************************************/ /* This is a function used for translating a bit to a different bit, @@ -68,8 +68,6 @@ static void clear_int_cond(int num, u_char val) com[num].int_condition &= ~val; /* reset IIR too, to recalculate later */ com[num].IIR.mask = 0; - if (!INT_REQUEST(num)) - pic_untrigger(com_cfg[num].irq); } static void recalc_IIR(int num) @@ -132,7 +130,7 @@ void uart_clear_fifo(int num, int fifo) com[num].rx_buf_start = 0; /* Beginning of rec FIFO queue */ com[num].rx_buf_end = 0; /* End of rec FIFO queue */ com[num].IIR.flg.cti = 0; /* clear timeout */ - com[num].rx_timeout = 0; /* Receive intr already occurred */ + com[num].rx_timeout = 0; /* Receive intr already occured */ clear_int_cond(num, LS_INTR | RX_INTR); /* Clear LS/RX conds */ rx_buffer_dump(num); /* Clear receive buffer */ } @@ -275,7 +273,7 @@ static void put_tx(int num, char val) /* Update the transmit timer */ com[num].tx_timer += com[num].tx_char_time; #endif - clear_int_cond(num, TX_INTR); /* TX interrupt condition satisfied */ + clear_int_cond(num, TX_INTR); /* TX interrupt condition satisifed */ /* Loop-back writes. Parity is currently not calculated. No * UART diagnostics programs including COMTEST.EXE, that I tried, @@ -421,10 +419,9 @@ put_lcr(int num, int val) serial_brkctl(num, !!(val & UART_LCR_SBC)); /* obviously the writes to LCR (except BREAK state) would - * invalidate the rx fifo on a real com port. Pseudo ports do not care. */ + * invalidate the rx fifo. We clear tx too. */ if ((changed & ~UART_LCR_SBC) && !DLAB(num)) { - if (!com[num].cfg->pseudo) - uart_clear_fifo(num, UART_FCR_CLEAR_CMD); + uart_clear_fifo(num, UART_FCR_CLEAR_CMD); ser_termios(num); /* Sets new line settings */ } } @@ -477,6 +474,11 @@ put_mcr(int num, int val) uart_clear_fifo(num,UART_FCR_CLEAR_CMD); } + /* Set interrupt enable flag according to OUT2 bit in MCR */ + if (INT_ENAB(num)) { + if(s3_printf) s_printf("SER%d: Update interrupt status after MCR update\n",num); + } + /* Force RTS & DTR reinitialization if the loopback state has changed */ if (UART_MCR_LOOP) changed |= UART_MCR_RTS | UART_MCR_DTR; @@ -491,14 +493,6 @@ put_mcr(int num, int val) if(s1_printf) s_printf("SER%d: MCR: RTS -> %d\n",num,(val & UART_MCR_RTS)); serial_rts(num, !!(val & UART_MCR_RTS)); } - - /* Set interrupt enable flag according to OUT2 bit in MCR */ - if (INT_ENAB(num)) { - if(s3_printf) s_printf("SER%d: Update interrupt status after MCR update\n",num); - serial_int_engine(num, 0); - } else { - pic_untrigger(com_cfg[num].irq); - } } } @@ -705,8 +699,6 @@ do_serial_out(int num, ioport_t address, int val) com[num].int_condition |= TX_INTR; // is this needed? } com[num].IER = (val & UART_IER_VALID); /* Write to IER */ - if (!INT_REQUEST(num)) - pic_untrigger(com_cfg[num].irq); if(s1_printf) s_printf("SER%d: Write IER = 0x%x\n", num, val); if (tflg) serial_int_engine(num, 0); diff --git a/src/base/serial/sermouse.c b/src/base/serial/sermouse.c index ad014a1..b70352c 100644 --- a/src/base/serial/sermouse.c +++ b/src/base/serial/sermouse.c @@ -52,46 +52,46 @@ static int limit_delta(int delta, int min, int max) static int ser_mouse_accepts(int from, void *udata) { - com_t *c = udata; + com_t *com = udata; if (!serm.opened) return 0; - if (!c) { + if (!com) { dosemu_error("sermouse NULL udata\n"); return 0; } /* if commouse is used, we need to accept any events */ - return (c->cfg->mouse && (config.mouse.dev_type == from || + return (com->cfg->mouse && (config.mouse.dev_type == from || config.mouse.com != -1)); } -static int add_buf(com_t *c, const char *buf, int len) +static int add_buf(com_t *com, const char *buf, int len) { if (!serm.enabled || !serm.opened || serm.div != DIV_1200) return 0; - if (RX_BUF_BYTES(c->num) + len > RX_BUFFER_SIZE) { - if(s3_printf) s_printf("SER%d: Too many bytes (%i) in buffer\n", c->num, - RX_BUF_BYTES(c->num)); + if (RX_BUF_BYTES(com->num) + len > RX_BUFFER_SIZE) { + if(s3_printf) s_printf("SER%d: Too many bytes (%i) in buffer\n", com->num, + RX_BUF_BYTES(com->num)); return 0; } /* Slide the buffer contents to the bottom */ - rx_buffer_slide(c->num); + rx_buffer_slide(com->num); - memcpy(&c->rx_buf[c->rx_buf_end], buf, len); + memcpy(&com->rx_buf[com->rx_buf_end], buf, len); if (debug_level('s') >= 9) { int i; for (i = 0; i < len; i++) - s_printf("SER%d: Got mouse data byte: %#x\n", c->num, - c->rx_buf[c->rx_buf_end + i]); + s_printf("SER%d: Got mouse data byte: %#x\n", com->num, + com->rx_buf[com->rx_buf_end + i]); } - c->rx_buf_end += len; - receive_engine(c->num, len); + com->rx_buf_end += len; + receive_engine(com->num, len); return len; } static void ser_mouse_move_button(int num, int press, void *udata) { - com_t *c = udata; + com_t *com = udata; char buf[3] = {0x40, 0, 0}; s_printf("SERM: button %i %i\n", num, press); @@ -123,13 +123,13 @@ static void ser_mouse_move_button(int num, int press, void *udata) } buf[0] |= serm.but; - add_buf(c, buf, sizeof(buf)); + add_buf(com, buf, sizeof(buf)); } static void ser_mouse_move_buttons(int lbutton, int mbutton, int rbutton, void *udata) { - com_t *c = udata; + com_t *com = udata; char buf[3] = {0x40, 0, 0}; if (serm.lb == lbutton && serm.mb == mbutton && serm.rb == rbutton) @@ -146,7 +146,7 @@ static void ser_mouse_move_buttons(int lbutton, int mbutton, int rbutton, buf[0] |= serm.but; /* change in mbutton is signalled by sending the prev state */ - add_buf(c, buf, sizeof(buf)); + add_buf(com, buf, sizeof(buf)); } static void ser_mouse_move_wheel(int dy, void *udata) @@ -156,7 +156,7 @@ static void ser_mouse_move_wheel(int dy, void *udata) static void ser_mouse_move_mickeys(int dx, int dy, void *udata) { - com_t *c = udata; + com_t *com = udata; char buf[3] = {0x40, 0, 0}; if (!dx && !dy) @@ -171,7 +171,7 @@ static void ser_mouse_move_mickeys(int dx, int dy, void *udata) buf[2] = dy & ~0xC0; buf[0] |= (dy & 0xC0) >> 4; - add_buf(c, buf, sizeof(buf)); + add_buf(com, buf, sizeof(buf)); } static void ser_mouse_move_relative(int dx, int dy, int x_range, int y_range, @@ -222,43 +222,43 @@ CONSTRUCTOR(static void serial_mouse_register(void)) } -static void serm_rx_buffer_dump(com_t *c) +static void serm_rx_buffer_dump(com_t *com) { } -static void serm_tx_buffer_dump(com_t *c) +static void serm_tx_buffer_dump(com_t *com) { } -static int serm_get_tx_queued(com_t *c) +static int serm_get_tx_queued(com_t *com) { return 0; } -static void serm_termios(com_t *c) +static void serm_termios(com_t *com) { - serm.div = ((c->dlm << 8) | c->dll); + serm.div = ((com->dlm << 8) | com->dll); s_printf("SERM: set div to %i\n", serm.div); } -static int serm_brkctl(com_t *c, int flag) +static int serm_brkctl(com_t *com, int flag) { return 0; } -static ssize_t serm_write(com_t *c, char *buf, size_t len) +static ssize_t serm_write(com_t *com, char *buf, size_t len) { return 0; } -static int serm_dtr(com_t *c, int flag) +static int serm_dtr(com_t *com, int flag) { serm.enabled = flag; - modstat_engine(c->num); // update DSR + modstat_engine(com->num); // update DSR return 0; } -static int serm_rts(com_t *c, int flag) +static int serm_rts(com_t *com, int flag) { if (flag && !serm.nrst) { /* ctmouse wrongly expects "M" here. It doesn't work with "M3" */ @@ -267,43 +267,43 @@ static int serm_rts(com_t *c, int flag) * coming from the mouse, during initialization, usually right after * the LCR register is set, so this is why this line of code is here */ - c->LSR |= UART_LSR_FE; /* Set framing error */ + com->LSR |= UART_LSR_FE; /* Set framing error */ if(s3_printf) s_printf("SERM: framing error\n"); - rx_buffer_slide(c->num); - if (c->rx_buf_end >= c->rx_fifo_size) { + rx_buffer_slide(com->num); + if (com->rx_buf_end >= com->rx_fifo_size) { error("SERM: fifo overflow\n"); return 0; } - c->rx_buf[c->rx_buf_end++] = 0; - serial_int_engine(c->num, LS_INTR); /* Update interrupt status */ - add_buf(c, id, strlen(id)); + com->rx_buf[com->rx_buf_end++] = 0; + serial_int_engine(com->num, LS_INTR); /* Update interrupt status */ + add_buf(com, id, strlen(id)); } serm.nrst = flag; - modstat_engine(c->num); // update DSR + modstat_engine(com->num); // update DSR return 0; } -static int serm_open(com_t *c) +static int serm_open(com_t *com) { - s_printf("SERM: open for port %i\n", c->num); - mousedrv_set_udata(ser_mouse.name, c); + s_printf("SERM: open for port %i\n", com->num); + mousedrv_set_udata(ser_mouse.name, com); serm.opened = 1; serm.but = 0; return 1; } -static int serm_close(com_t *c) +static int serm_close(com_t *com) { serm.opened = 0; return 0; } -static int serm_uart_fill(com_t *c) +static int serm_uart_fill(com_t *com) { return 0; } -static int serm_get_msr(com_t *c) +static int serm_get_msr(com_t *com) { return ((serm.enabled && serm.nrst) ? UART_MSR_DSR : 0); } diff --git a/src/base/serial/tty_io.c b/src/base/serial/tty_io.c index 7a1d175..61f0c25 100644 --- a/src/base/serial/tty_io.c +++ b/src/base/serial/tty_io.c @@ -22,30 +22,30 @@ #include #include #include -#include +#if 0 +#include +#endif #include "emu.h" -#include "utilities.h" #include "dosemu_config.h" -#include "ioselect.h" #include "ser_defs.h" #include "tty_io.h" /* This function flushes the internal unix receive buffer [num = port] */ -static void tty_rx_buffer_dump(com_t *c) +static void tty_rx_buffer_dump(com_t *com) { - tcflush(c->fd, TCIFLUSH); + tcflush(com->fd, TCIFLUSH); } /* This function flushes the internal unix transmit buffer [num = port] */ -static void tty_tx_buffer_dump(com_t *c) +static void tty_tx_buffer_dump(com_t *com) { - tcflush(c->fd, TCOFLUSH); + tcflush(com->fd, TCOFLUSH); } -static int tty_get_tx_queued(com_t *c) +static int tty_get_tx_queued(com_t *com) { int ret, queued; - ret = ioctl(c->fd, TIOCOUTQ, &queued); + ret = ioctl(com->fd, TIOCOUTQ, &queued); if (ret < 0) return ret; return queued; @@ -56,65 +56,71 @@ static int tty_get_tx_queued(com_t *c) * stored in the Line Control Register (com[].LCR) and the Baudrate * Divisor Latch Registers (com[].dlm and com[].dll) [num = port] */ -static void do_termios(com_t *c) +static void tty_termios(com_t *com) { speed_t baud; long int rounddiv; - if (c->is_file) + if (com->is_file) return; /* The following is the same as (com[num].dlm * 256) + com[num].dll */ - #define DIVISOR ((c->dlm << 8) | c->dll) + #define DIVISOR ((com->dlm << 8) | com->dll) - s_printf("SER%d: LCR = 0x%x, ",c->num,c->LCR); + /* Return if not a tty */ + if (tcgetattr(com->fd, &com->newset) == -1) { + if(s1_printf) s_printf("SER%d: Line Control: NOT A TTY (%s).\n",com->num,strerror(errno)); + return; + } + + s_printf("SER%d: LCR = 0x%x, ",com->num,com->LCR); /* Set the word size */ - c->newset.c_cflag &= ~CSIZE; - switch (c->LCR & UART_LCR_WLEN8) { + com->newset.c_cflag &= ~CSIZE; + switch (com->LCR & UART_LCR_WLEN8) { case UART_LCR_WLEN5: - c->newset.c_cflag |= CS5; + com->newset.c_cflag |= CS5; s_printf("5"); break; case UART_LCR_WLEN6: - c->newset.c_cflag |= CS6; + com->newset.c_cflag |= CS6; s_printf("6"); break; case UART_LCR_WLEN7: - c->newset.c_cflag |= CS7; + com->newset.c_cflag |= CS7; s_printf("7"); break; case UART_LCR_WLEN8: - c->newset.c_cflag |= CS8; + com->newset.c_cflag |= CS8; s_printf("8"); break; } /* Set the parity. Rarely-used MARK and SPACE parities not supported yet */ - if (c->LCR & UART_LCR_PARITY) { - c->newset.c_cflag |= PARENB; - if (c->LCR & UART_LCR_EPAR) { - c->newset.c_cflag &= ~PARODD; + if (com->LCR & UART_LCR_PARITY) { + com->newset.c_cflag |= PARENB; + if (com->LCR & UART_LCR_EPAR) { + com->newset.c_cflag &= ~PARODD; s_printf("E"); } else { - c->newset.c_cflag |= PARODD; + com->newset.c_cflag |= PARODD; s_printf("O"); } } else { - c->newset.c_cflag &= ~PARENB; + com->newset.c_cflag &= ~PARENB; s_printf("N"); } /* Set the stop bits: UART_LCR_STOP set means 2 stop bits, 1 otherwise */ - if (c->LCR & UART_LCR_STOP) { + if (com->LCR & UART_LCR_STOP) { /* This is actually 1.5 stop bit when word size is 5 bits */ - c->newset.c_cflag |= CSTOPB; + com->newset.c_cflag |= CSTOPB; s_printf("2, "); } else { - c->newset.c_cflag &= ~CSTOPB; + com->newset.c_cflag &= ~CSTOPB; s_printf("1, "); } @@ -197,64 +203,57 @@ static void do_termios(com_t *c) s_printf("divisor 0x%x -> 0x%lx\n", DIVISOR, rounddiv); /* The following does the actual system calls to set the line parameters */ - cfsetispeed(&c->newset, baud); - cfsetospeed(&c->newset, baud); + cfsetispeed(&com->newset, baud); + cfsetospeed(&com->newset, baud); if (debug_level('s') > 7) { - s_printf("SER%d: iflag=%x oflag=%x cflag=%x lflag=%x\n", c->num, - c->newset.c_iflag, c->newset.c_oflag, - c->newset.c_cflag, c->newset.c_lflag); + s_printf("SER%d: iflag=%x oflag=%x cflag=%x lflag=%x\n", com->num, + com->newset.c_iflag, com->newset.c_oflag, + com->newset.c_cflag, com->newset.c_lflag); } + tcsetattr(com->fd, TCSANOW, &com->newset); } -static void tty_termios(com_t *c) -{ - do_termios(c); - tcsetattr(c->fd, TCSANOW, &c->newset); -} - -static int tty_brkctl(com_t *c, int brkflg) +static int tty_brkctl(com_t *com, int brkflg) { int ret; /* there is change of break state */ if (brkflg) { - s_printf("SER%d: Setting BREAK state.\n", c->num); - tcdrain(c->fd); - ret = ioctl(c->fd, TIOCSBRK); + s_printf("SER%d: Setting BREAK state.\n", com->num); + tcdrain(com->fd); + ret = ioctl(com->fd, TIOCSBRK); } else { - s_printf("SER%d: Clearing BREAK state.\n", c->num); - ret = ioctl(c->fd, TIOCCBRK); + s_printf("SER%d: Clearing BREAK state.\n", com->num); + ret = ioctl(com->fd, TIOCCBRK); } return ret; } -static ssize_t tty_write(com_t *c, char *buf, size_t len) +static ssize_t tty_write(com_t *com, char *buf, size_t len) { - int fd; - if (c->cfg->ro && c->wr_fd == -1) + if (com->ro) return len; - fd = (c->wr_fd == -1 ? c->fd : c->wr_fd); - return RPT_SYSCALL(write(fd, buf, len)); /* Attempt char xmit */ + return RPT_SYSCALL(write(com->fd, buf, len)); /* Attempt char xmit */ } -static int tty_dtr(com_t *c, int flag) +static int tty_dtr(com_t *com, int flag) { int ret, control; control = TIOCM_DTR; if (flag) - ret = ioctl(c->fd, TIOCMBIS, &control); + ret = ioctl(com->fd, TIOCMBIS, &control); else - ret = ioctl(c->fd, TIOCMBIC, &control); + ret = ioctl(com->fd, TIOCMBIC, &control); return ret; } -static int tty_rts(com_t *c, int flag) +static int tty_rts(com_t *com, int flag) { int ret, control; control = TIOCM_RTS; if (flag) - ret = ioctl(c->fd, TIOCMBIS, &control); + ret = ioctl(com->fd, TIOCMBIS, &control); else - ret = ioctl(c->fd, TIOCMBIC, &control); + ret = ioctl(com->fd, TIOCMBIC, &control); return ret; } @@ -340,8 +339,8 @@ static int tty_lock(const char *path, int mode) } /* Make sure UUCP owns the lockfile. Required by some packages. */ - if ((pw = getpwnam(owner_tty_locks)) == NULL) { - error("tty: lock: UUCP user %s unknown!\n", owner_tty_locks); + if ((pw = getpwnam(OWNER_LOCKS)) == NULL) { + error("tty: lock: UUCP user %s unknown!\n", OWNER_LOCKS); return(0); /* keep the lock anyway */ } @@ -365,7 +364,7 @@ static int tty_lock(const char *path, int mode) fprintf(fd, "%10d\n", (int)ime); (void) fclose(fd); - (void) chmod(saved_path, 0440); + (void) chmod(saved_path, 0444); return(0); } else { /* unlock */ @@ -390,43 +389,33 @@ static int tty_lock(const char *path, int mode) return(0); } -static void ser_set_params(com_t *c) +static void ser_set_params(com_t *com) { int data = 0; - - /* Return if not a tty */ - if (tcgetattr(c->fd, &c->newset) == -1) { - if(s1_printf) s_printf("SER%d: Line Control: NOT A TTY (%s).\n",c->num,strerror(errno)); - return; - } - c->newset.c_cflag = CS8 | CLOCAL | CREAD; - c->newset.c_iflag = IGNBRK | IGNPAR; - c->newset.c_oflag = 0; - c->newset.c_lflag = 0; - if (c->cfg->virt) { - c->newset.c_lflag |= ISIG; - c->newset.c_cc[VERASE] = 8; // set to BS, its DEL by default - } + com->newset.c_cflag = CS8 | CLOCAL | CREAD; + com->newset.c_iflag = IGNBRK | IGNPAR; + com->newset.c_oflag = 0; + com->newset.c_lflag = 0; #ifdef __linux__ - c->newset.c_line = 0; + com->newset.c_line = 0; #endif - c->newset.c_cc[VMIN] = 1; - c->newset.c_cc[VTIME] = 0; - if (c->cfg->system_rtscts) - c->newset.c_cflag |= CRTSCTS; + com->newset.c_cc[VMIN] = 1; + com->newset.c_cc[VTIME] = 0; + if (com->cfg->system_rtscts) + com->newset.c_cflag |= CRTSCTS; + tcsetattr(com->fd, TCSANOW, &com->newset); - if(s2_printf) s_printf("SER%d: do_ser_init: running ser_termios\n", c->num); - do_termios(c); /* Set line settings now */ - tcsetattr(c->fd, TCSANOW, &c->newset); + if(s2_printf) s_printf("SER%d: do_ser_init: running ser_termios\n", com->num); + tty_termios(com); /* Set line settings now */ /* Pull down DTR and RTS. This is the most natural for most comm */ /* devices including mice so that DTR rises during mouse init. */ - if (!c->cfg->pseudo) { + if (!com->cfg->pseudo) { data = TIOCM_DTR | TIOCM_RTS; - if (ioctl(c->fd, TIOCMBIC, &data) && errno == EINVAL) { - s_printf("SER%d: TIOCMBIC unsupported, setting pseudo flag\n", c->num); - c->cfg->pseudo = 1; + if (ioctl(com->fd, TIOCMBIC, &data) && errno == EINVAL) { + s_printf("SER%d: TIOCMBIC unsupported, setting pseudo flag\n", com->num); + com->cfg->pseudo = 1; } } } @@ -439,15 +428,15 @@ static void ser_set_params(com_t *c) * * [num = port] */ -static int tty_uart_fill(com_t *c) +static int tty_uart_fill(com_t *com) { int size = 0; - if (c->fd < 0) + if (com->fd < 0) return 0; /* Return if in loopback mode */ - if (c->MCR & UART_MCR_LOOP) + if (com->MCR & UART_MCR_LOOP) return 0; /* Is it time to do another read() of the serial device yet? @@ -456,318 +445,219 @@ static int tty_uart_fill(com_t *c) * contains enough data for a full FIFO (at least 16 bytes). * The receive buffer is a sliding buffer. */ - if (RX_BUF_BYTES(c->num) >= RX_BUFFER_SIZE) { - if(s3_printf) s_printf("SER%d: Too many bytes (%i) in buffer\n", c->num, - RX_BUF_BYTES(c->num)); + if (RX_BUF_BYTES(com->num) >= RX_BUFFER_SIZE) { + if(s3_printf) s_printf("SER%d: Too many bytes (%i) in buffer\n", com->num, + RX_BUF_BYTES(com->num)); return 0; } /* Slide the buffer contents to the bottom */ - rx_buffer_slide(c->num); + rx_buffer_slide(com->num); /* Do a block read of data. * Guaranteed minimum requested read size of (RX_BUFFER_SIZE - 16)! */ - size = RPT_SYSCALL(read(c->fd, - &c->rx_buf[c->rx_buf_end], - RX_BUFFER_SIZE - c->rx_buf_end)); - ioselect_complete(c->fd); - if (size < 0) + size = RPT_SYSCALL(read(com->fd, + &com->rx_buf[com->rx_buf_end], + RX_BUFFER_SIZE - com->rx_buf_end)); + if (size <= 0) return 0; - if (size == 0) { - c->is_closed = TRUE; - if(s3_printf) s_printf("SER%d: Got 0 bytes, setting is_closed\n", c->num); - return 0; - } - if(s3_printf) s_printf("SER%d: Got %i bytes, %i in buffer\n", c->num, - size, RX_BUF_BYTES(c->num)); + if(s3_printf) s_printf("SER%d: Got %i bytes, %i in buffer\n", com->num, + size, RX_BUF_BYTES(com->num)); if (debug_level('s') >= 9) { int i; for (i = 0; i < size; i++) - s_printf("SER%d: Got data byte: %#x\n", c->num, - c->rx_buf[c->rx_buf_end + i]); + s_printf("SER%d: Got data byte: %#x\n", com->num, + com->rx_buf[com->rx_buf_end + i]); } - c->rx_buf_end += size; + com->rx_buf_end += size; return size; } -static void async_serial_run(int fd, void *arg) +static void async_serial_run(void *arg) { - com_t *c = arg; + com_t *com = arg; int size; - s_printf("SER%d: Async notification received\n", c->num); - size = tty_uart_fill(c); + s_printf("SER%d: Async notification received\n", com->num); + size = tty_uart_fill(com); if (size > 0) - receive_engine(c->num, size); + receive_engine(com->num, size); } -static int ser_open_existing(com_t *c) +static int ser_open_existing(com_t *com) { struct stat st; int err, io_sel = 0, oflags = O_NONBLOCK; - err = stat(c->cfg->dev, &st); + err = stat(com->cfg->dev, &st); if (err) { - error("SERIAL: stat(%s) failed: %s\n", c->cfg->dev, + error("SERIAL: stat(%s) failed: %s\n", com->cfg->dev, strerror(errno)); - c->fd = -2; + com->fd = -2; return -1; } if (S_ISFIFO(st.st_mode)) { - s_printf("SER%i: %s is fifo, setting pseudo flag\n", c->num, - c->cfg->dev); - c->is_file = TRUE; - c->cfg->pseudo = TRUE; - /* force read-only to avoid SIGPIPE */ - c->cfg->ro = TRUE; + s_printf("SER%i: %s is fifo, setting pseudo flag\n", com->num, + com->cfg->dev); + com->is_file = TRUE; + com->ro = TRUE; + com->cfg->pseudo = TRUE; oflags |= O_RDONLY; io_sel = 1; } else { + com->ro = FALSE; if (S_ISREG(st.st_mode)) { - s_printf("SER%i: %s is file, setting pseudo flag\n", c->num, - c->cfg->dev); - c->is_file = TRUE; - c->cfg->pseudo = TRUE; - oflags |= O_RDONLY; - if (!c->cfg->ro && !c->cfg->wrfile) - c->wr_fd = RPT_SYSCALL(open(c->cfg->dev, O_WRONLY | O_APPEND)); + s_printf("SER%i: %s is file, setting pseudo flag\n", com->num, + com->cfg->dev); + com->is_file = TRUE; + com->cfg->pseudo = TRUE; + oflags |= O_WRONLY | O_APPEND; } else { oflags |= O_RDWR; io_sel = 1; } } - c->fd = RPT_SYSCALL(open(c->cfg->dev, oflags)); - if (c->fd < 0) { + com->fd = RPT_SYSCALL(open(com->cfg->dev, oflags)); + if (com->fd < 0) { error("SERIAL: Unable to open device %s: %s\n", - c->cfg->dev, strerror(errno)); + com->cfg->dev, strerror(errno)); return -1; } - if (!c->is_file && !isatty(c->fd)) { + if (!com->is_file && !isatty(com->fd)) { s_printf("SERIAL: Serial port device %s is not a tty\n", - c->cfg->dev); - c->is_file = TRUE; - c->cfg->pseudo = TRUE; + com->cfg->dev); + com->is_file = TRUE; + com->cfg->pseudo = TRUE; } - if (!c->is_file) { - RPT_SYSCALL(tcgetattr(c->fd, &c->oldset)); - RPT_SYSCALL(tcgetattr(c->fd, &c->newset)); + if (!com->is_file) { + RPT_SYSCALL(tcgetattr(com->fd, &com->oldset)); + RPT_SYSCALL(tcgetattr(com->fd, &com->newset)); #if 0 - if (c->cfg->low_latency) { + if (com->cfg->low_latency) { struct serial_struct ser_info; - int err = ioctl(c->fd, TIOCGSERIAL, &ser_info); + int err = ioctl(com->fd, TIOCGSERIAL, &ser_info); if (err) { error("SER%d: failure getting serial port settings, %s\n", - c->num, strerror(errno)); + com->num, strerror(errno)); } else { ser_info.flags |= ASYNC_LOW_LATENCY; - err = ioctl(c->fd, TIOCSSERIAL, &ser_info); + err = ioctl(com->fd, TIOCSSERIAL, &ser_info); if (err) error("SER%d: failure setting low_latency flag, %s\n", - c->num, strerror(errno)); + com->num, strerror(errno)); else - s_printf("SER%d: low_latency flag set\n", c->num); + s_printf("SER%d: low_latency flag set\n", com->num); } } #endif - ser_set_params(c); + ser_set_params(com); } if (io_sel) - add_to_io_select(c->fd, async_serial_run, (void *)c); + add_to_io_select(com->fd, async_serial_run, (void *)com); return 0; } -static int pty_init(com_t *c) -{ - int pty_fd = posix_openpt(O_RDWR); - if (pty_fd == -1) - { - error("openpt failed %s\n", strerror(errno)); - return -1; - } - unlockpt(pty_fd); - fcntl(pty_fd, F_SETFL, O_NONBLOCK); - return pty_fd; -} - -static int tty_close(com_t *c); - -static void pty_exit(void *arg) -{ - com_t *c = arg; - error("pty process terminated\n"); - tty_close(c); -} - -static int pty_open(com_t *c, const char *cmd) -{ - struct termios t; - const char *argv[] = { "sh", "-c", cmd, NULL }; - const int argc = 4; - int pty_fd; - - pty_fd = pty_init(c); - pid_t pid = run_external_command("/bin/sh", argc, argv, 1, -1, pty_fd); - if (pid == -1) - return -1; - sigchld_register_handler(pid, pty_exit, c); - c->pty_pid = pid; - cfmakeraw(&t); - tcsetattr(pty_fd, TCSANOW, &t); - return pty_fd; -} - -static int pty_close(com_t *c, int fd) -{ - sigchld_enable_handler(c->pty_pid, 0); - return close(fd); -} - /* This function opens ONE serial port for DOSEMU. Normally called only * by do_ser_init below. [num = port, return = file descriptor] */ -static int tty_open(com_t *c) +static int tty_open(com_t *com) { int err; - if (c->cfg->exec) { - c->fd = pty_open(c, c->cfg->exec); - if (c->fd == -1) - return -1; - c->cfg->pseudo = TRUE; - add_to_io_select(c->fd, async_serial_run, (void *)c); - return c->fd; - } - if (c->cfg->pts) { - c->fd = pty_init(c); - if (c->fd == -1) - return -1; - grantpt(c->fd); - err = symlink(ptsname(c->fd), c->cfg->pts); - if (err) { - error("symlink(%s, %s): %s", ptsname(c->fd), c->cfg->pts, - strerror(errno)); - close(c->fd); - c->fd = -2; - return -1; - } - c->cfg->pseudo = TRUE; - add_to_io_select(c->fd, async_serial_run, (void *)c); - return c->fd; - } - if (c->fd != -1) + if (com->fd != -1) return -1; - s_printf("SER%d: Running ser_open, %s, fd=%d\n", c->num, - c->cfg->dev, c->fd); + s_printf("SER%d: Running ser_open, %s, fd=%d\n", com->num, + com->cfg->dev, com->fd); - if (c->fd != -1) - return (c->fd); + if (com->fd != -1) + return (com->fd); - if (c->cfg->virt) + if (com->cfg->virt) { /* don't try to remove any lock: they don't make sense for ttyname(0) */ s_printf("Opening Virtual Port\n"); - c->dev_locked = FALSE; + com->dev_locked = FALSE; } else if (config.tty_lockdir[0]) { - if (tty_lock(c->cfg->dev, 1) >= 0) { /* Lock port */ + if (tty_lock(com->cfg->dev, 1) >= 0) { /* Lock port */ /* We know that we have access to the serial port */ /* If the port is used for a mouse, then don't lock, because * the use of the mouse serial port can be switched between processes, * such as on Linux virtual consoles. */ - c->dev_locked = TRUE; + com->dev_locked = TRUE; } else { /* The port is in use by another process! Don't touch the port! */ - c->dev_locked = FALSE; - c->fd = -2; + com->dev_locked = FALSE; + com->fd = -2; return(-1); } } else { s_printf("Warning: Port locking disabled in the config.\n"); - c->dev_locked = FALSE; + com->dev_locked = FALSE; } - err = access(c->cfg->dev, F_OK); + err = access(com->cfg->dev, F_OK); if (!err) { - err = ser_open_existing(c); + err = ser_open_existing(com); if (err) goto fail_unlock; } else { - c->fd = open(c->cfg->dev, O_WRONLY | O_CREAT | O_EXCL, 0640); - if (c->fd == -1) { - error("SER%i: unable to open or create %s\n", c->num, c->cfg->dev); - goto fail_unlock; - } - } - if (c->cfg->wrfile) { - c->wr_fd = open(c->cfg->wrfile, O_WRONLY | O_CREAT | O_TRUNC, 0640); - if (c->wr_fd == -1) { - error("SER%i: unable to open or create for write %s\n", c->num, c->cfg->dev); + com->fd = open(com->cfg->dev, O_WRONLY | O_CREAT | O_EXCL, 0666); + if (com->fd == -1) { + error("SER%i: unable to open or create %s\n", com->num, com->cfg->dev); goto fail_unlock; } } - modstat_engine(c->num); - return c->fd; + modstat_engine(com->num); + return com->fd; + close(com->fd); + /* fall through */ fail_unlock: - if (c->dev_locked && tty_lock(c->cfg->dev, 0) >= 0) /* Unlock port */ - c->dev_locked = FALSE; + if (com->dev_locked && tty_lock(com->cfg->dev, 0) >= 0) /* Unlock port */ + com->dev_locked = FALSE; - c->fd = -2; // disable permanently + com->fd = -2; // disable permanently return -1; } /* This function closes ONE serial port for DOSEMU. Normally called * only by do_ser_init below. [num = port, return = file error code] */ -static int tty_close(com_t *c) +static int tty_close(com_t *com) { - int ret; - if (c->fd < 0) + int i; + if (com->fd < 0) return -1; - if (c->wr_fd != -1) { - close(c->wr_fd); - c->wr_fd = -1; - } - s_printf("SER%d: Running ser_close\n", c->num); - remove_from_io_select(c->fd); - if (c->cfg->exec) { - ret = pty_close(c, c->fd); - c->fd = -1; - return ret; - } - if (c->cfg->pts) { - unlink(c->cfg->pts); - close(c->fd); - c->fd = -1; - return 0; - } + s_printf("SER%d: Running ser_close\n", com->num); + remove_from_io_select(com->fd); /* save current dosemu settings of the file and restore the old settings * before closing the file down. */ - if (!c->is_file) { - RPT_SYSCALL(tcgetattr(c->fd, &c->newset)); - RPT_SYSCALL(tcsetattr(c->fd, TCSANOW, &c->oldset)); + if (!com->is_file) { + RPT_SYSCALL(tcgetattr(com->fd, &com->newset)); + RPT_SYSCALL(tcsetattr(com->fd, TCSANOW, &com->oldset)); } - ret = RPT_SYSCALL(close(c->fd)); - c->fd = -1; + i = RPT_SYSCALL(close(com->fd)); + com->fd = -1; /* Clear the lockfile from DOSEMU */ - if (c->dev_locked) { - if (tty_lock(c->cfg->dev, 0) >= 0) - c->dev_locked = FALSE; + if (com->dev_locked) { + if (tty_lock(com->cfg->dev, 0) >= 0) + com->dev_locked = FALSE; } - return ret; + return (i); } -static int tty_get_msr(com_t *c) +static int tty_get_msr(com_t *com) { int control, err; - err = ioctl(c->fd, TIOCMGET, &control); + err = ioctl(com->fd, TIOCMGET, &control); if (err) return 0; return (((control & TIOCM_CTS) ? UART_MSR_CTS : 0) | diff --git a/src/base/sound/midi.c b/src/base/sound/midi.c index 2e43394..75e9cc2 100644 --- a/src/base/sound/midi.c +++ b/src/base/sound/midi.c @@ -35,35 +35,31 @@ #define MAX_IN_PLUGINS 1 static struct pcm_holder out[ST_MAX][MAX_OUT_PLUGINS]; static struct pcm_holder in[MAX_IN_PLUGINS]; -#define OUT_PLUGIN(i, j) ((const struct midi_out_plugin *)out[i][j].plugin) +#define OUT_PLUGIN(i) ((const struct midi_out_plugin *)out[synth_type][i].plugin) +#define OUT_PLUGIN2(i, j) ((const struct midi_out_plugin *)out[i][j].plugin) #define IN_PLUGIN(i) ((const struct midi_in_plugin *)in[i].plugin) static int out_registered[ST_MAX], in_registered; -static int out_enabled[ST_MAX]; static struct rng_s midi_in; #define MAX_DL_HANDLES 10 static void *dl_handles[MAX_DL_HANDLES]; static int num_dl_handles; static enum SynthType synth_type; -void midi_write(unsigned char val, enum SynthType type) +void midi_write(unsigned char val) { int i; - enum SynthType stype = (type == ST_ANY ? synth_type : type); - /* if no plugin of requested type, then try to use anything */ - if (!out_enabled[stype] && out_enabled[synth_type]) - stype = synth_type; - for (i = 0; i < out_registered[stype]; i++) - if (out[stype][i].opened) - OUT_PLUGIN(stype, i)->write(val); + for (i = 0; i < out_registered[synth_type]; i++) + if (out[synth_type][i].opened) + OUT_PLUGIN(i)->write(val); for (i = 0; i < out_registered[ST_ANY]; i++) if (out[ST_ANY][i].opened) - OUT_PLUGIN(ST_ANY, i)->write(val); + OUT_PLUGIN2(ST_ANY, i)->write(val); // idle(0, 0, 0, "midi"); } void midi_init(void) { - int i, j; + int i; #ifdef USE_DL_PLUGINS #define LOAD_PLUGIN(x) \ dl_handles[num_dl_handles] = load_plugin(x); \ @@ -80,21 +76,12 @@ void midi_init(void) #endif #endif rng_init(&midi_in, 64, 1); - for (i = 0; i < ST_MAX; i++) { + for (i = 0; i < ST_MAX; i++) pcm_init_plugins(out[i], out_registered[i]); - for (j = 0; j < out_registered[i]; j++) { - if (out[i][j].opened) - out_enabled[i]++; - } - } pcm_init_plugins(in, in_registered); - if (out_enabled[ST_GM]) - synth_type = ST_GM; - else if (out_enabled[ST_MT32]) - synth_type = ST_MT32; if (!midi_set_synth_type_from_string(config.midi_synth)) - S_printf("MIDI: unsupported synth mode %s\n", config.midi_synth); + error("MIDI: unsupported synth mode %s\n", config.midi_synth); } void midi_done(void) @@ -118,8 +105,8 @@ void midi_stop(void) int i, j; for (i = 0; i < ST_MAX; i++) { for (j = 0; j < out_registered[i]; j++) - if (OUT_PLUGIN(i, j)->stop && out[i][j].opened) - OUT_PLUGIN(i, j)->stop(out[i][j].arg); + if (OUT_PLUGIN2(i, j)->stop && out[i][j].opened) + OUT_PLUGIN2(i, j)->stop(out[i][j].arg); } for (i = 0; i < in_registered; i++) if (IN_PLUGIN(i)->stop && in[i].opened) @@ -131,8 +118,8 @@ void midi_timer(void) int i, j; for (i = 0; i < ST_MAX; i++) { for (j = 0; j < out_registered[i]; j++) - if (OUT_PLUGIN(i, j)->run && out[i][j].opened) - OUT_PLUGIN(i, j)->run(); + if (OUT_PLUGIN2(i, j)->run && out[i][j].opened) + OUT_PLUGIN2(i, j)->run(); } } @@ -178,7 +165,7 @@ int midi_register_input_plugin(const struct midi_in_plugin *plugin) int midi_set_synth_type(enum SynthType st) { - if (st == ST_ANY || st >= ST_MAX || !out_enabled[st]) + if (st == ST_ANY || st >= ST_MAX) return 0; synth_type = st; return 1; @@ -191,10 +178,13 @@ enum SynthType midi_get_synth_type(void) int midi_set_synth_type_from_string(const char *stype) { - if (strcmp(stype, "gm") == 0) - return midi_set_synth_type(ST_GM); - if (strcmp(stype, "mt32") == 0) - return midi_set_synth_type(ST_MT32); - midi_set_synth_type(ST_GM); - return 0; + if (strcmp(stype, "gm") == 0) { + midi_set_synth_type(ST_GM); + } else if (strcmp(stype, "mt32") == 0) { + midi_set_synth_type(ST_MT32); + } else { + midi_set_synth_type(ST_GM); + return 0; + } + return 1; } diff --git a/src/base/sound/sndpcm.c b/src/base/sound/sndpcm.c index 20bff71..30ecd36 100644 --- a/src/base/sound/sndpcm.c +++ b/src/base/sound/sndpcm.c @@ -107,8 +107,8 @@ struct stream { long long buf_cnt; int state; int flags; - unsigned int stretch:1; - unsigned int prepared:1; + int stretch:1; + int prepared:1; void *vol_arg; double start_time; double stop_time; @@ -195,7 +195,6 @@ static int checkid2_dummy(void *id2, void *arg) return 1; } -#if defined(USE_LIBAO) || defined(SDL_SUPPORT) static int pcm_get_cfg(const char *name) { int i; @@ -206,7 +205,6 @@ static int pcm_get_cfg(const char *name) } return -1; } -#endif int pcm_init(void) { @@ -1289,7 +1287,6 @@ int pcm_init_plugins(struct pcm_holder *plu, int num) struct pcm_holder *p = &plu[i]; if (p->opened || p->failed || (p->plugin->flags & PCM_F_EXPLICIT) || - (p->cfg_flags & PCM_CF_DISABLED) || !(p->plugin->flags & PCM_F_PASSTHRU)) continue; p->opened = SAFE_OPEN(p); @@ -1308,7 +1305,6 @@ int pcm_init_plugins(struct pcm_holder *plu, int num) struct pcm_holder *p = &plu[i]; if (p->opened || p->failed || (p->plugin->flags & PCM_F_EXPLICIT) || - (p->cfg_flags & PCM_CF_DISABLED) || (p->plugin->flags & PCM_F_PASSTHRU)) continue; if (p->plugin->weight > max_w) { @@ -1422,13 +1418,6 @@ int pcm_parse_cfg(const char *string, const char *name) { char *p; int l; - char *on = pcm_parse_params(config.snd_plugin_params, name, "enabled"); - int off = (on && on[0] == '0'); - free(on); - if (off) { - pcm_printf("PCM: %s driver disabled in the config\n", name); - return PCM_CF_DISABLED; - } l = strlen(name); p = strstr(string, name); if (p && (p == string || p[-1] == ',') && (p[l] == 0 || p[l] == ',')) { @@ -1446,9 +1435,9 @@ char *pcm_parse_params(const char *string, const char *name, const char *param) assert(l > 0); p = strstr(string, buf); free(buf); - if (p && (p == string || p[-1] == ' ')) { + if (p && (p == string || p[-1] == ',')) { char *val = strdup(p + l); - char *c = strchr(val, ' '); + char *c = strchr(val, ','); if (c) *c = 0; pcm_printf("PCM: Param \"%s\" for driver \"%s\": %s\n", param, name, val); diff --git a/src/base/speaker/console_speaker.c b/src/base/speaker/console_speaker.c index 486ae95..139391f 100644 --- a/src/base/speaker/console_speaker.c +++ b/src/base/speaker/console_speaker.c @@ -6,7 +6,7 @@ #include #ifdef __linux__ -#include "Sys/kd.h" +#include #endif diff --git a/src/base/speaker/speaker.c b/src/base/speaker/speaker.c index a684f49..7d05098 100644 --- a/src/base/speaker/speaker.c +++ b/src/base/speaker/speaker.c @@ -13,7 +13,7 @@ * * Actuall emulation is done in src/base/dev/misc/timers.c in do_sound. * - * Currently emulation is only done when the new keyboard is enabled but with a + * Currenly emulation is only done when the new keyboard is enabled but with a * little extra work it should be possible to enable it for the old keyboard * code if necessary. * @@ -30,7 +30,7 @@ * 'speaker_on' always overrides whatever previous speaker sound was previously * given. No mixing happens. * - * For code that wants to implement speaker emulation. The recommended method + * For code that wants to implement speaker emulation. The recommeded method * is to add a file in src/base/speaker with the necessary code. Declare it's * methods in speaker.h (or somewhere accessible to your code). And call * @@ -93,10 +93,7 @@ static int speaker_is_on; static void dumb_speaker_on(void * gp, unsigned ms, unsigned short period) { - FILE *out = (config.tty_stderr ? stderr : stdout); - putc('\007', out); - if (!config.tty_stderr) - fflush(stdout); + putchar('\007'); } static void dumb_speaker_off(void *gp) { @@ -159,8 +156,8 @@ void speaker_pause (void) switch (config.speaker) { case SPKR_NATIVE: - saved_port_val = port_inb (0x61); - std_port_outb (0x61, saved_port_val & 0xFC); /* clear timer & speaker bits */ + saved_port_val = port_safe_inb (0x61); + port_safe_outb (0x61, saved_port_val & 0xFC); /* clear timer & speaker bits */ break; case SPKR_EMULATED: speaker_off (); @@ -175,10 +172,10 @@ void speaker_resume (void) switch (config.speaker) { case SPKR_NATIVE: - std_port_outb (0x61, saved_port_val); /* restore timer & speaker bits */ + port_safe_outb (0x61, saved_port_val); /* restore timer & speaker bits */ break; case SPKR_EMULATED: -// do_sound(pit[2].write_latch & 0xffff); + do_sound (pit [2].write_latch & 0xffff); break; case SPKR_OFF: break; diff --git a/src/base/video/instremu.c b/src/base/video/instremu.c index f086be5..1dd296d 100644 --- a/src/base/video/instremu.c +++ b/src/base/video/instremu.c @@ -46,9 +46,11 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "emu.h" +#include "vgaemu.h" #include "emudpmi.h" +#include "emu-ldt.h" #include "cpu.h" -#include "dos2linux.h" +#include "dis8086.h" #include "instremu.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -62,6 +64,9 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define DEBUG_INSTR 0 /* (<= 2) instruction emulation */ +#define COUNT 150 /* bail out when this #instructions were simulated + after a VGA r/w access */ + #define R_LO(a) LO_BYTE_d(a) #define R_HI(a) HI_BYTE_d(a) #define R_WORD(a) LO_WORD(a) @@ -84,6 +89,37 @@ #define BP (R_WORD(x86->ebp)) #define EFLAGS (R_DWORD(x86->eflags)) #define FLAGS (R_WORD(EFLAGS)) +#define OP_JCC(cond) eip += (cond) ? 2 + *(signed char *)MEM_BASE32(cs + eip + 1) : 2; break; + +/* assembly macros to speed up x86 on x86 emulation: the cpu helps us in setting + the flags */ + +#define OPandFLAG0(eflags, insn, op1, istype) __asm__ __volatile__("\n\ + "#insn" %0\n\ + pushf; pop %1\n \ + " : #istype (op1), "=g" (eflags) : "0" (op1)); + +#define OPandFLAG1(eflags, insn, op1, istype) __asm__ __volatile__("\n\ + "#insn" %0, %0\n\ + pushf; pop %1\n \ + " : #istype (op1), "=g" (eflags) : "0" (op1)); + +#define OPandFLAG(eflags, insn, op1, op2, istype, type) __asm__ __volatile__("\n\ + "#insn" %3, %0\n\ + pushf; pop %1\n \ + " : #istype (op1), "=g" (eflags) : "0" (op1), #type (op2)); + +#define OPandFLAGC(eflags, insn, op1, op2, istype, type) __asm__ __volatile__("\n\ + shr $1, %0\n\ + "#insn" %4, %1\n\ + pushf; pop %0\n \ + " : "=r" (eflags), #istype (op1) : "0" (eflags), "1" (op1), #type (op2)); + + +#if !defined True +#define False 0 +#define True 1 +#endif #define instr_msg(x...) v_printf("instremu: " x) @@ -97,11 +133,6 @@ enum {REPNZ = 0, REPZ = 1, REP_NONE = 2}; -struct rm { - unsigned char *r; - dosaddr_t m; -}; - typedef struct x86_regs { unsigned eax, ecx, edx, ebx, esp, ebp, esi, edi; /* this sequence is important because this is the cpu's order and thus @@ -115,9 +146,11 @@ typedef struct x86_regs { unsigned address_size; /* in bytes so either 4 or 2 */ unsigned operand_size; unsigned prefixes, rep; - unsigned (*instr_read)(struct rm rm); - void (*instr_write)(struct rm rm, unsigned u); - struct rm (*modrm)(unsigned char *cp, struct x86_regs *x86, int *inst_len); + unsigned (*instr_binary)(unsigned op, unsigned op1, + unsigned op2, unsigned *eflags); + unsigned (*instr_read)(const unsigned char *addr); + void (*instr_write)(unsigned char *addr, unsigned u); + unsigned char *(*modrm)(unsigned char *cp, struct x86_regs *x86, int *inst_len); } x86_regs; #if DEBUG_INSTR >= 1 @@ -152,18 +185,38 @@ static unsigned char it[0x100] = { /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static unsigned seg, lock, rep; +static int count; #define vga_base vga.mem.bank_base #define vga_end (vga_base + vga.mem.bank_len) static unsigned arg_len(unsigned char *, int); -static unsigned instr_read_word(struct rm rm); -static unsigned instr_read_dword(struct rm rm); -static void instr_write_word(struct rm rm, unsigned u); -static void instr_write_dword(struct rm rm, unsigned u); -static dosaddr_t sib(unsigned char *cp, x86_regs *x86, int *inst_len); -static struct rm modrm32(unsigned char *cp, x86_regs *x86, int *inst_len); -static struct rm modrm16(unsigned char *cp, x86_regs *x86, int *inst_len); +static unsigned char instr_read_byte(const unsigned char *addr); +static unsigned instr_read_word(const unsigned char *addr); +static unsigned instr_read_dword(const unsigned char *addr); +static void instr_write_byte(unsigned char *addr, unsigned char u); +static void instr_write_word(unsigned char *addr, unsigned u); +static void instr_write_dword(unsigned char *addr, unsigned u); +static void instr_flags(unsigned val, unsigned smask, unsigned *eflags); +static unsigned instr_shift(unsigned op, unsigned op1, unsigned op2, unsigned size, unsigned *eflags); +static unsigned char *sib(unsigned char *cp, x86_regs *x86, int *inst_len); +static unsigned char *modrm32(unsigned char *cp, x86_regs *x86, int *inst_len); +static unsigned char *modrm16(unsigned char *cp, x86_regs *x86, int *inst_len); + +static void dump_x86_regs(x86_regs *x86) +{ + instr_deb( + "eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x ebp=%08x esp=%08x\n", + x86->eax, x86->ebx, x86->ecx, x86->edx, x86->esi, x86->edi, x86-> ebp, x86->esp + ); + instr_deb( + "eip=%08x cs=%04x/%08x ds=%04x/%08x es=%04x/%08x d=%u c=%u p=%u a=%u z=%u s=%u o=%u\n", + x86->eip, x86->cs, x86->cs_base, x86->ds, x86->ds_base, x86->es, x86->es_base, + (EFLAGS&DF)>>10, + EFLAGS&CF,(EFLAGS&PF)>>2,(EFLAGS&AF)>>4, + (EFLAGS&ZF)>>6,(EFLAGS&SF)>>7,(EFLAGS&OF)>>11 + ); +} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -225,30 +278,9 @@ int instr_len(unsigned char *p, int is_32) if(*p == 0x0f) { p++; switch (*p) { - case 0x80 ... 0x8f: - p += osp ? 5 : 3; - return p - p0; - case 0xa4: - p++; - p += (u = arg_len(p, asp)); - if(!u) p = p0; - return p + 1 - p0; case 0xba: p += 4; return p - p0; - case 0xa5: - case 0xb6: - case 0xb7: - case 0xbe: - case 0xbf: - case 0: - case 1: - case 0x20: - case 0x22: - p++; - p += (u = arg_len(p, asp)); - if(!u) p = p0; - return p - p0; default: /* not yet */ error("unsupported instr_len %x %x\n", p[0], p[1]); @@ -315,7 +347,7 @@ int instr_len(unsigned char *p, int is_32) } -static unsigned arg_len(unsigned char *p, int asp) +unsigned arg_len(unsigned char *p, int asp) { unsigned u = 0, m, s = 0; @@ -362,20 +394,42 @@ static unsigned arg_len(unsigned char *p, int asp) * */ -unsigned instr_read_word(struct rm rm) +unsigned char instr_read_byte(const unsigned char *address) +{ + unsigned char u; + dosaddr_t addr = DOSADDR_REL(address); + + if(addr >= vga_base && addr < vga_end) { + count = COUNT; + u = vga_read(addr); + } + else { + u = *address; + } +#if DEBUG_INSTR >= 2 + instr_deb2("Read byte 0x%x", u); + if (addr<0x8000000) v_printf(" from address %x\n", addr); else v_printf("\n"); +#endif + + return u; +} + +unsigned instr_read_word(const unsigned char *address) { unsigned u; - if (rm.r) { - memcpy(&u, rm.r, 2); - return u; - } - /* * segment wrap-arounds within a data word are not allowed since * at least i286, so no problems here */ - u = read_word(rm.m); + dosaddr_t addr = DOSADDR_REL(address); + if(addr >= vga_base && addr < vga_end) { + count = COUNT; + u = 0; + R_LO(u) = vga_read(addr); + R_HI(u) = vga_read(addr+1); + } else + u = *(const unsigned short *)address; #if DEBUG_INSTR >= 2 instr_deb2("Read word 0x%x", u); @@ -384,20 +438,23 @@ unsigned instr_read_word(struct rm rm) return u; } -unsigned instr_read_dword(struct rm rm) +unsigned instr_read_dword(const unsigned char *address) { unsigned u; - if (rm.r) { - memcpy(&u, rm.r, 4); - return u; - } - /* * segment wrap-arounds within a data word are not allowed since * at least i286, so no problems here */ - u = read_dword(rm.m); + dosaddr_t addr = DOSADDR_REL(address); + if(addr >= vga_base && addr < vga_end) { + count = COUNT; + R_LO(u) = vga_read(addr); + R_HI(u) = vga_read(addr+1); + ((unsigned char *) &u)[2] = vga_read(addr+2); + ((unsigned char *) &u)[3] = vga_read(addr+3); + } else + u = *(const unsigned *)address; #if DEBUG_INSTR >= 2 instr_deb2("Read word 0x%x", u); @@ -406,20 +463,39 @@ unsigned instr_read_dword(struct rm rm) return u; } -void instr_write_word(struct rm rm, unsigned u) +void instr_write_byte(unsigned char *address, unsigned char u) { - if (rm.r) { - memcpy(rm.r, &u, 2); - return; - } + dosaddr_t addr = DOSADDR_REL(address); + if(addr >= vga_base && addr < vga_end) { + count = COUNT; + vga_write(addr, u); + } + else { + *address = u; + } +#if DEBUG_INSTR >= 2 + instr_deb2("Write byte 0x%x", u); + if (addr<0x8000000) v_printf(" at address %x\n", addr); else v_printf("\n"); +#endif +} + +void instr_write_word(unsigned char *address, unsigned u) +{ + dosaddr_t dst = DOSADDR_REL(address); /* * segment wrap-arounds within a data word are not allowed since * at least i286, so no problems here. * we assume application do not try to mix here */ - write_word(rm.m, u); + if(dst >= vga_base && dst < vga_end) { + count = COUNT; + vga_write(dst, R_LO(u)); + vga_write(dst+1, R_HI(u)); + } + else + *(unsigned short *)address = u; #if DEBUG_INSTR >= 2 instr_deb2("Write word 0x%x", u); @@ -427,12 +503,9 @@ void instr_write_word(struct rm rm, unsigned u) #endif } -void instr_write_dword(struct rm rm, unsigned u) +void instr_write_dword(unsigned char *address, unsigned u) { - if (rm.r) { - memcpy(rm.r, &u, 4); - return; - } + dosaddr_t dst = DOSADDR_REL(address); /* * segment wrap-arounds within a data word are not allowed since @@ -440,7 +513,15 @@ void instr_write_dword(struct rm rm, unsigned u) * we assume application do not try to mix here */ - write_dword(rm.m, u); + if(dst >= vga_base && dst < vga_end) { + count = COUNT; + vga_write(dst, R_LO(u)); + vga_write(dst+1, R_HI(u)); + vga_write(dst+2, ((unsigned char *) &u)[2]); + vga_write(dst+3, ((unsigned char *) &u)[3]); + } + else + *(unsigned *)address = u; #if DEBUG_INSTR >= 2 instr_deb2("Write word 0x%x", u); @@ -448,18 +529,253 @@ void instr_write_dword(struct rm rm, unsigned u) #endif } +/* We use the cpu itself to set the flags, which is easy since we are + emulating x86 on x86. */ +void instr_flags(unsigned val, unsigned smask, unsigned *eflags) +{ + unsigned long flags; + + *eflags &= ~(OF|ZF|SF|PF|CF); + if (val & smask) + *eflags |= SF; + OPandFLAG1(flags, orl, val, =r); + *eflags |= flags & (ZF|PF); +} + +/* 6 logical and arithmetic "RISC" core functions + follow +*/ +unsigned char instr_binary_byte(unsigned char op, unsigned char op1, unsigned char op2, unsigned *eflags) +{ + unsigned long flags; + + switch (op&0x7){ + case 1: /* or */ + OPandFLAG(flags, orb, op1, op2, =q, q); + *eflags = (*eflags & ~(OF|ZF|SF|PF|CF)) | (flags & (OF|ZF|SF|PF|CF)); + return op1; + case 4: /* and */ + OPandFLAG(flags, andb, op1, op2, =q, q); + *eflags = (*eflags & ~(OF|ZF|SF|PF|CF)) | (flags & (OF|ZF|SF|PF|CF)); + return op1; + case 6: /* xor */ + OPandFLAG(flags, xorb, op1, op2, =q, q); + *eflags = (*eflags & ~(OF|ZF|SF|PF|CF)) | (flags & (OF|ZF|SF|PF|CF)); + return op1; + case 0: /* add */ + *eflags &= ~CF; /* Fall through */ + case 2: /* adc */ + flags = *eflags; + OPandFLAGC(flags, adcb, op1, op2, =q, q); + *eflags = (*eflags & ~(OF|ZF|SF|AF|PF|CF)) | (flags & (OF|ZF|AF|SF|PF|CF)); + return op1; + case 5: /* sub */ + case 7: /* cmp */ + *eflags &= ~CF; /* Fall through */ + case 3: /* sbb */ + flags = *eflags; + OPandFLAGC(flags, sbbb, op1, op2, =q, q); + *eflags = (*eflags & ~(OF|ZF|SF|AF|PF|CF)) | (flags & (OF|ZF|AF|SF|PF|CF)); + return op1; + } + return 0; +} + +unsigned instr_binary_word(unsigned op, unsigned op1, unsigned op2, unsigned *eflags) +{ + unsigned long flags; + unsigned short opw1 = op1; + unsigned short opw2 = op2; + + switch (op&0x7){ + case 1: /* or */ + OPandFLAG(flags, orw, opw1, opw2, =r, r); + *eflags = (*eflags & ~(OF|ZF|SF|PF|CF)) | (flags & (OF|ZF|SF|PF|CF)); + return opw1; + case 4: /* and */ + OPandFLAG(flags, andw, opw1, opw2, =r, r); + *eflags = (*eflags & ~(OF|ZF|SF|PF|CF)) | (flags & (OF|ZF|SF|PF|CF)); + return opw1; + case 6: /* xor */ + OPandFLAG(flags, xorw, opw1, opw2, =r, r); + *eflags = (*eflags & ~(OF|ZF|SF|PF|CF)) | (flags & (OF|ZF|SF|PF|CF)); + return opw1; + case 0: /* add */ + *eflags &= ~CF; /* Fall through */ + case 2: /* adc */ + flags = *eflags; + OPandFLAGC(flags, adcw, opw1, opw2, =r, r); + *eflags = (*eflags & ~(OF|ZF|SF|AF|PF|CF)) | (flags & (OF|ZF|AF|SF|PF|CF)); + return opw1; + case 5: /* sub */ + case 7: /* cmp */ + *eflags &= ~CF; /* Fall through */ + case 3: /* sbb */ + flags = *eflags; + OPandFLAGC(flags, sbbw, opw1, opw2, =r, r); + *eflags = (*eflags & ~(OF|ZF|SF|AF|PF|CF)) | (flags & (OF|ZF|AF|SF|PF|CF)); + return opw1; + } + return 0; +} + +unsigned instr_binary_dword(unsigned op, unsigned op1, unsigned op2, unsigned *eflags) +{ + unsigned long flags; + + switch (op&0x7){ + case 1: /* or */ + OPandFLAG(flags, orl, op1, op2, =r, r); + *eflags = (*eflags & ~(OF|ZF|SF|PF|CF)) | (flags & (OF|ZF|SF|PF|CF)); + return op1; + case 4: /* and */ + OPandFLAG(flags, andl, op1, op2, =r, r); + *eflags = (*eflags & ~(OF|ZF|SF|PF|CF)) | (flags & (OF|ZF|SF|PF|CF)); + return op1; + case 6: /* xor */ + OPandFLAG(flags, xorl, op1, op2, =r, r); + *eflags = (*eflags & ~(OF|ZF|SF|PF|CF)) | (flags & (OF|ZF|SF|PF|CF)); + return op1; + case 0: /* add */ + *eflags &= ~CF; /* Fall through */ + case 2: /* adc */ + flags = *eflags; + OPandFLAGC(flags, adcl, op1, op2, =r, r); + *eflags = (*eflags & ~(OF|ZF|SF|AF|PF|CF)) | (flags & (OF|ZF|AF|SF|PF|CF)); + return op1; + case 5: /* sub */ + case 7: /* cmp */ + *eflags &= ~CF; /* Fall through */ + case 3: /* sbb */ + flags = *eflags; + OPandFLAGC(flags, sbbl, op1, op2, =r, r); + *eflags = (*eflags & ~(OF|ZF|SF|AF|PF|CF)) | (flags & (OF|ZF|AF|SF|PF|CF)); + return op1; + } + return 0; +} + +unsigned instr_shift(unsigned op, unsigned op1, unsigned op2, unsigned size, unsigned *eflags) +{ + unsigned result, carry; + unsigned width = size * 8; + unsigned mask = wordmask[size]; + unsigned smask = (mask >> 1) + 1; + op2 &= 31; + + switch (op&0x7){ + case 0: /* rol */ + op2 &= width-1; + result = (((op1 << op2) | ((op1&mask) >> (width-op2)))) & mask; + if (op2 > 0) { + *eflags &= ~(CF|OF); + *eflags |= (result & CF) | ((((result >> (width-1)) ^ result) << 11) & OF); + } + return result; + case 1:/* ror */ + op2 &= width-1; + result = ((((op1&mask) >> op2) | (op1 << (width-op2)))) & mask; + if (op2 > 0) { + *eflags &= ~(CF|OF); + carry = (result >> (width-1)) & CF; + *eflags |= carry | (((carry ^ (result >> (width-2))) << 11) & OF); + } + return result; + case 2: /* rcl */ + op2 %= width+1; + result = (((op1 << op2) | ((op1&mask) >> (width+1-op2))) | ((*eflags&CF) << (op2-1))) & mask; + if (op2 > 0) { + *eflags &= ~(CF|OF); + carry = (op1>>(width-op2))&CF; + *eflags |= carry | ((((result >> (width-1)) ^ carry) << 11) & OF); + } + return result; + case 3:/* rcr */ + op2 %= width+1; + result = ((((op1&mask) >> op2) | (op1 << (width+1-op2))) | ((*eflags&CF) << (width-op2))) & mask; + if (op2 > 0) { + *eflags &= ~(CF|OF); + carry = (op1>>(op2-1))&CF; + *eflags |= carry | ((((result >> (width-1)) ^ (result >> (width-2))) << 11) & OF); + } + return result; + case 4: /* shl */ + result = (op1 << op2) & mask; + if (op2 > 0) { + instr_flags(result, smask, eflags); + *eflags &= ~(CF|OF); + *eflags |= ((op1 >> (width-op2))&CF) | + ((((op1 >> (width-1)) ^ (op1 >> (width-2))) << 11) & OF); + } + return result; + case 5: /* shr */ + result = ((unsigned)(op1&mask) >> op2); + if (op2 > 0) { + instr_flags(result, smask, eflags); + *eflags &= ~(CF|OF); + *eflags |= ((op1 >> (op2-1)) & CF) | (((op1 >> (width-1)) << 11) & OF); + } + return result; + /* case 6 - sal? */ + case 7: /* sar */ + result = op1 >> op2; + if (op2 > 0) { + instr_flags(result, smask, eflags); + *eflags &= ~(CF|OF); + *eflags |= (op1 >> (op2-1)) & CF; + } + return result; + } + return 0; +} + +static inline void push(unsigned val, x86_regs *x86) +{ + unsigned char *mem; + + if (x86->_32bit) + x86->esp -= x86->operand_size; + else + SP -= x86->operand_size; + mem = MEM_BASE32(x86->ss_base + (x86->esp & wordmask[(x86->_32bit+1)*2])); + if (x86->operand_size == 4) + instr_write_dword(mem, val); + else + instr_write_word(mem, val); +} + static inline void pop(unsigned *val, x86_regs *x86) { - struct rm mem = {}; - - mem.m = x86->ss_base + (x86->esp & wordmask[(x86->_32bit+1)*2]); + unsigned char *mem = MEM_BASE32(x86->ss_base + (x86->esp & wordmask[(x86->_32bit+1)*2])); if (x86->_32bit) x86->esp += x86->operand_size; else - LO_WORD(x86->esp) += x86->operand_size; + SP += x86->operand_size; *val = (x86->operand_size == 4 ? instr_read_dword(mem) : instr_read_word(mem)); } +/* + * DANG_BEGIN_FUNCTION instr_sim + * + * description: + * instr_sim is used to simulate instructions that access the + * VGA video memory in planar modes when using X as the video output + * device. + * + * It is necessary to do this in order to simulate the effects + * of the hardware VGA controller in X mode. + * + * If the return value is 0, it means the instruction was not one + * that for which a simulation is provided. The return value is 1 for success, + * but the function exits because we need to go back to the DOSEMU's main loop + * or count runs out. + * + * arguments: + * x86: the structure holding everything about the cpu-state we need. + * + * DANG_END_FUNCTION + */ + /* helper functions/macros reg8/reg/sreg/sib/modrm16/32 for instr_sim for address and register decoding */ @@ -468,7 +784,7 @@ static inline void pop(unsigned *val, x86_regs *x86) #define sreg(reg, x86) ((&((x86)->es))+((reg)&0x7)) #define sreg_idx(reg) (es_INDEX+((reg)&0x7)) -dosaddr_t sib(unsigned char *cp, x86_regs *x86, int *inst_len) +unsigned char *sib(unsigned char *cp, x86_regs *x86, int *inst_len) { unsigned addr = 0; @@ -491,24 +807,23 @@ dosaddr_t sib(unsigned char *cp, x86_regs *x86, int *inst_len) case 0x03: case 0x06: case 0x07: - return (addr + *reg(cp[2], x86) + x86->seg_base); + return MEM_BASE32(addr + *reg(cp[2], x86) + x86->seg_base); case 0x04: /* esp */ - return (addr + x86->esp + x86->seg_ss_base); + return MEM_BASE32(addr + x86->esp + x86->seg_ss_base); case 0x05: if (cp[1] >= 0x40) - return (addr + x86->ebp + x86->seg_ss_base); + return MEM_BASE32(addr + x86->ebp + x86->seg_ss_base); else { *inst_len += 4; - return (addr + R_DWORD(cp[3]) + x86->seg_base); + return MEM_BASE32(addr + R_DWORD(cp[3]) + x86->seg_base); } } return 0; /* keep gcc happy */ } -struct rm modrm16(unsigned char *cp, x86_regs *x86, int *inst_len) +unsigned char *modrm16(unsigned char *cp, x86_regs *x86, int *inst_len) { unsigned addr = 0; - struct rm rm = {}; *inst_len = 0; switch(cp[1] & 0xc0) { /* decode modifier */ @@ -522,51 +837,41 @@ struct rm modrm16(unsigned char *cp, x86_regs *x86, int *inst_len) break; case 0xc0: if (cp[0]&1) /*(d)word*/ - rm.r = (unsigned char *)reg(cp[1], x86); + return (unsigned char *)reg(cp[1], x86); else - rm.r = reg8(cp[1], x86); - return rm; + return reg8(cp[1], x86); } switch(cp[1] & 0x07) { /* decode address */ case 0x00: - rm.m = (((addr + x86->ebx + x86->esi) & 0xffff) + x86->seg_base); - break; + return MEM_BASE32(((addr + x86->ebx + x86->esi) & 0xffff) + x86->seg_base); case 0x01: - rm.m = (((addr + x86->ebx + x86->edi) & 0xffff) + x86->seg_base); - break; + return MEM_BASE32(((addr + x86->ebx + x86->edi) & 0xffff) + x86->seg_base); case 0x02: - rm.m = (((addr + x86->ebp + x86->esi) & 0xffff) + x86->seg_ss_base); - break; + return MEM_BASE32(((addr + x86->ebp + x86->esi) & 0xffff) + x86->seg_ss_base); case 0x03: - rm.m = (((addr + x86->ebp + x86->edi) & 0xffff) + x86->seg_ss_base); - break; + return MEM_BASE32(((addr + x86->ebp + x86->edi) & 0xffff) + x86->seg_ss_base); case 0x04: - rm.m = (((addr + x86->esi) & 0xffff) + x86->seg_base); - break; + return MEM_BASE32(((addr + x86->esi) & 0xffff) + x86->seg_base); case 0x05: - rm.m = (((addr + x86->edi) & 0xffff) + x86->seg_base); - break; + return MEM_BASE32(((addr + x86->edi) & 0xffff) + x86->seg_base); case 0x06: if (cp[1] >= 0x40) - rm.m = (((addr + x86->ebp) & 0xffff) + x86->seg_ss_base); + return MEM_BASE32(((addr + x86->ebp) & 0xffff) + x86->seg_ss_base); else { *inst_len += 2; - rm.m = (R_WORD(cp[2]) + x86->seg_base); + return MEM_BASE32(R_WORD(cp[2]) + x86->seg_base); } - break; case 0x07: - rm.m = (((addr + x86->ebx) & 0xffff) + x86->seg_base); - break; + return MEM_BASE32(((addr + x86->ebx) & 0xffff) + x86->seg_base); } - return rm; + return 0; /* keep gcc happy */ } -struct rm modrm32(unsigned char *cp, x86_regs *x86, int *inst_len) +unsigned char *modrm32(unsigned char *cp, x86_regs *x86, int *inst_len) { unsigned addr = 0; - struct rm rm = {}; *inst_len = 0; switch(cp[1] & 0xc0) { /* decode modifier */ @@ -580,12 +885,10 @@ struct rm modrm32(unsigned char *cp, x86_regs *x86, int *inst_len) break; case 0xc0: if (cp[0]&1) /*(d)word*/ - rm.r = ((unsigned char *)reg(cp[1], x86)); + return ((unsigned char *)reg(cp[1], x86)); else - rm.r = reg8(cp[1], x86); - return rm; + return reg8(cp[1], x86); } - switch(cp[1] & 0x07) { /* decode address */ case 0x00: case 0x01: @@ -593,22 +896,19 @@ struct rm modrm32(unsigned char *cp, x86_regs *x86, int *inst_len) case 0x03: case 0x06: case 0x07: - rm.m = (addr + *reg(cp[1], x86) + x86->seg_base); - break; + return MEM_BASE32(addr + *reg(cp[1], x86) + x86->seg_base); case 0x04: /* sib byte follows */ *inst_len += 1; - rm.m = sib(cp, x86, inst_len); - break; + return sib(cp, x86, inst_len); case 0x05: if (cp[1] >= 0x40) - rm.m = (addr + x86->ebp + x86->seg_ss_base); + return MEM_BASE32(addr + x86->ebp + x86->seg_ss_base); else { *inst_len += 4; - rm.m = (R_DWORD(cp[2]) + x86->seg_base); + return MEM_BASE32(R_DWORD(cp[2]) + x86->seg_base); } - break; } - return rm; + return 0; /* keep gcc happy */ } static int handle_prefixes(x86_regs *x86) @@ -647,9 +947,11 @@ static int handle_prefixes(x86_regs *x86) prefix++; x86->operand_size = 6 - x86->operand_size; if (x86->operand_size == 4) { + x86->instr_binary = instr_binary_dword; x86->instr_read = instr_read_dword; x86->instr_write = instr_write_dword; } else { + x86->instr_binary = instr_binary_word; x86->instr_read = instr_read_word; x86->instr_write = instr_write_word; } @@ -684,17 +986,1375 @@ static void prepare_x86(x86_regs *x86) x86->rep = REP_NONE; if (x86->operand_size == 4) { + x86->instr_binary = instr_binary_dword; x86->instr_read = instr_read_dword; x86->instr_write = instr_write_dword; } else { + x86->instr_binary = instr_binary_word; x86->instr_read = instr_read_word; x86->instr_write = instr_write_word; } } -#define M(a) (struct rm){.m = (a)} +/* return value: 1 => instruction known; 0 => instruction not known */ +static inline int instr_sim(x86_regs *x86, int pmode) +{ + unsigned char *reg_8; + unsigned char uc; + unsigned short uns; + unsigned *dstreg; + unsigned und, und2, repcount; + unsigned long unl; + unsigned char *mem; + int i, i2, inst_len; + int loop_inc = (EFLAGS&DF) ? -1 : 1; // make it a char ? + unsigned eip = x86->eip; + unsigned cs = x86->cs_base; -static void scp_to_x86_regs(x86_regs *x86, cpuctx_t *scp, int pmode) +#if DEBUG_INSTR >= 2 + { + int refseg, rc; + unsigned char frmtbuf[256]; + refseg = x86->cs; + dump_x86_regs(x86); + rc = dis_8086(MEM_BASE32(cs+eip), frmtbuf, x86->_32bit, &refseg, MEM_BASE32(cs)); + instr_deb("vga_emu_fault: about to simulate %d: %s\n", count, frmtbuf); + } +#endif + + if (x86->prefixes) { + prepare_x86(x86); + } + + x86->prefixes = handle_prefixes(x86); + eip += x86->prefixes; + + if (x86->rep != REP_NONE) { + /* TODO: All these rep instruction can still be heavily optimized */ + i2 = 0; + if (x86->address_size == 4) { + repcount = x86->ecx; + switch(*(unsigned char *)MEM_BASE32(cs + eip)) { + case 0xa4: /* rep movsb */ +#if DEBUG_INSTR >= 1 + if (x86->es_base >= 0xa0000 && x86->es_base < 0xb0000 && + x86->seg_base >= 0xa0000 && x86->seg_base < 0xb0000) + instr_deb("VGAEMU: Video to video memcpy, ecx=%x\n", x86->ecx); + /* TODO: accelerate this using memcpy */ +#endif + for (i = 0, und = 0; und < repcount; + i += loop_inc, und++) + instr_write_byte(MEM_BASE32(x86->es_base + x86->edi+i), + instr_read_byte(MEM_BASE32(x86->seg_base + x86->esi+i))); + x86->edi += i; + x86->esi += i; + break; + + case 0xa5: /* rep movsw/d */ + /* TODO: accelerate this using memcpy */ + for (i = 0, und = 0; und < repcount; + i += loop_inc*x86->operand_size, und++) + x86->instr_write(MEM_BASE32(x86->es_base + x86->edi+i), + x86->instr_read(MEM_BASE32(x86->seg_base + x86->esi+i))); + x86->edi += i; + x86->esi += i; + break; + + case 0xa6: /* rep cmpsb */ + for (i = 0, und = 0; und < repcount;) { + instr_binary_byte(7, instr_read_byte(MEM_BASE32(x86->seg_base + x86->esi+i)), + instr_read_byte(MEM_BASE32(x86->es_base + x86->edi+i)), &EFLAGS); + i += loop_inc; + und++; + if (((EFLAGS & ZF) >> 6) != x86->rep) /* 0xf2 repnz 0xf3 repz */ { + i2 = 1; /* we're fine now! */ + break; + } + } + x86->edi += i; + x86->esi += i; + break; + + case 0xa7: /* rep cmpsw/d */ + for (i = 0, und = 0; und < repcount;) { + x86->instr_binary(7, instr_read_byte(MEM_BASE32(x86->seg_base + x86->esi+i)), + x86->instr_read(MEM_BASE32(x86->es_base + x86->edi+i)), &EFLAGS); + i += loop_inc*x86->operand_size; + und++; + if (((EFLAGS & ZF) >> 6) != x86->rep) /* 0xf2 repnz 0xf3 repz */ { + i2 = 1; /* we're fine now! */ + break; + } + } + x86->edi += i; + x86->esi += i; + break; + + case 0xaa: /* rep stosb */ + /* TODO: accelerate this using memset */ + for (und2 = x86->edi, und = 0; und < repcount; + und2 += loop_inc, und++) + instr_write_byte(MEM_BASE32(x86->es_base + und2), AL); + x86->edi = und2; + break; + + case 0xab: /* rep stosw */ + /* TODO: accelerate this using memset */ + for (und2 = x86->edi, und = 0; und < repcount; + und2 += loop_inc*x86->operand_size, und++) + x86->instr_write(MEM_BASE32(x86->es_base + und2), x86->eax); + x86->edi = und2; + break; + + case 0xae: /* rep scasb */ + for (und2 = x86->edi, und = 0; und < repcount;) { + instr_binary_byte(7, AL, instr_read_byte(MEM_BASE32(x86->es_base + und2)), &EFLAGS); + und2 += loop_inc; + und++; + if (((EFLAGS & ZF) >> 6) != x86->rep) /* 0x0 repnz 0x1 repz */ { + i2 = 1; /* we're fine now! */ + break; + } + } + x86->edi = und2; + break; + + case 0xaf: /* rep scasw */ + for (und2 = x86->edi, und = 0; und < repcount;) { + x86->instr_binary(7, x86->eax, x86->instr_read(MEM_BASE32(x86->es_base + und2)), &EFLAGS); + und2 += loop_inc*x86->operand_size; + und++; + if (((EFLAGS & ZF) >> 6) != x86->rep) /* 0x0 repnz 0x1 repz */ { + i2 = 1; /* we're fine now! */ + break; + } + } + x86->edi = und2; + break; + + default: + return 0; + } + + x86->ecx -= und; + if (x86->ecx > 0 && i2 == 0) return 1; + + } else { + repcount = CX; + switch(*(unsigned char *)MEM_BASE32(cs + eip)) { + case 0xa4: /* rep movsb */ +#if DEBUG_INSTR >= 1 + if (x86->es_base >= 0xa0000 && x86->es_base < 0xb0000 && + x86->seg_base >= 0xa0000 && x86->seg_base < 0xb0000) + instr_deb("VGAEMU: Video to video memcpy, cx=%x\n", CX); + /* TODO: accelerate this using memcpy */ +#endif + for (i = 0, und = 0; und < repcount; + i += loop_inc, und++) + instr_write_byte(MEM_BASE32(x86->es_base + ((x86->edi+i) & 0xffff)), + instr_read_byte(MEM_BASE32(x86->seg_base + ((x86->esi+i) & 0xffff)))); + DI += i; + SI += i; + break; + + case 0xa5: /* rep movsw/d */ + /* TODO: accelerate this using memcpy */ + for (i = 0, und = 0; und < repcount; + i += loop_inc*x86->operand_size, und++) + x86->instr_write(MEM_BASE32(x86->es_base + ((x86->edi+i) & 0xffff)), + x86->instr_read(MEM_BASE32(x86->seg_base + ((x86->esi+i) & 0xffff)))); + DI += i; + SI += i; + break; + + case 0xa6: /* rep?z cmpsb */ + for (i = 0, und = 0; und < repcount;) { + instr_binary_byte(7, instr_read_byte(MEM_BASE32(x86->seg_base + ((x86->esi+i) & 0xffff))), + instr_read_byte(MEM_BASE32(x86->es_base + ((x86->edi+i) & 0xffff))), &EFLAGS); + i += loop_inc; + und++; + if (((EFLAGS & ZF) >> 6) != x86->rep) /* 0x0 repnz 0x1 repz */ { + i2 = 1; /* we're fine now! */ + break; + } + } + DI += i; + SI += i; + break; + + case 0xa7: /* rep?z cmpsw/d */ + for (i = 0, und = 0; und < repcount;) { + x86->instr_binary(7, x86->instr_read(MEM_BASE32(x86->seg_base + ((x86->esi+i) & 0xffff))), + x86->instr_read(MEM_BASE32(x86->es_base + ((x86->edi+i) & 0xffff))), &EFLAGS); + i += loop_inc * x86->operand_size; + und++; + if (((EFLAGS & ZF) >> 6) != x86->rep) /* 0x0 repnz 0x1 repz */ { + i2 = 1; /* we're fine now! */ + break; + } + } + DI += i; + SI += i; + break; + + case 0xaa: /* rep stosb */ + /* TODO: accelerate this using memset */ + for (uns = DI, und = 0; und < repcount; + uns += loop_inc, und++) + instr_write_byte(MEM_BASE32(x86->es_base + uns), AL); + DI = uns; + break; + + case 0xab: /* rep stosw/d */ + /* TODO: accelerate this using memset */ + for (uns = DI, und = 0; und < repcount; + uns += loop_inc*x86->operand_size, und++) + x86->instr_write(MEM_BASE32(x86->es_base + uns), (x86->operand_size == 4 ? x86->eax : AX)); + DI = uns; + break; + + case 0xae: /* rep scasb */ + for (uns = DI, und = 0; und < repcount;) { + instr_binary_byte(7, AL, instr_read_byte(MEM_BASE32(x86->es_base + uns)), &EFLAGS); + uns += loop_inc; + und++; + if (((EFLAGS & ZF) >> 6) != x86->rep) /* 0x0 repnz 0x1 repz */ { + i2 = 1; /* we're fine now! */ + break; + } + } + DI = uns; + break; + + case 0xaf: /* rep scasw/d */ + for (uns = DI, und = 0; und < repcount;) { + x86->instr_binary(7, AX, instr_read_word(MEM_BASE32(x86->es_base + uns)), &EFLAGS); + uns += loop_inc*x86->operand_size; + und++; + if (((EFLAGS & ZF) >> 6) != x86->rep) /* 0x0 repnz 0x1 repz */ { + i2 = 1; /* we're fine now! */ + break; + } + } + DI = uns; + break; + + default: + return 0; + } + CX -= und; + if (CX > 0 && i2 == 0) return 1; + } + eip++; + } + else switch(*(unsigned char *)MEM_BASE32(cs + eip)) { + case 0x00: /* add r/m8,reg8 */ + case 0x08: /* or r/m8,reg8 */ + case 0x10: /* adc r/m8,reg8 */ + case 0x18: /* sbb r/m8,reg8 */ + case 0x20: /* and r/m8,reg8 */ + case 0x28: /* sub r/m8,reg8 */ + case 0x30: /* xor r/m8,reg8 */ + case 0x38: /* cmp r/m8,reg8 */ + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + uc = instr_binary_byte((*(unsigned char *)MEM_BASE32(cs + eip))>>3, + instr_read_byte(mem), *reg8((*(unsigned char *)MEM_BASE32(cs + eip + 1))>>3, x86), &EFLAGS); + if (*(unsigned char *)MEM_BASE32(cs + eip)<0x38) + instr_write_byte(mem, uc); + eip += 2 + inst_len; break; + + case 0x01: /* add r/m16,reg16 */ + case 0x09: /* or r/m16,reg16 */ + case 0x11: /* adc r/m16,reg16 */ + case 0x19: /* sbb r/m16,reg16 */ + case 0x21: /* and r/m16,reg16 */ + case 0x29: /* sub r/m16,reg16 */ + case 0x31: /* xor r/m16,reg16 */ + case 0x39: /* cmp r/m16,reg16 */ + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + und = x86->instr_binary(*(unsigned char *)MEM_BASE32(cs + eip)>>3, x86->instr_read(mem), *reg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86), &EFLAGS); + if (*(unsigned char *)MEM_BASE32(cs + eip)<0x38) + x86->instr_write(mem, und); + eip += 2 + inst_len; break; + + case 0x02: /* add reg8,r/m8 */ + case 0x0a: /* or reg8,r/m8 */ + case 0x12: /* adc reg8,r/m8 */ + case 0x1a: /* sbb reg8,r/m8 */ + case 0x22: /* and reg8,r/m8 */ + case 0x2a: /* sub reg8,r/m8 */ + case 0x32: /* xor reg8,r/m8 */ + case 0x3a: /* cmp reg8,r/m8 */ + reg_8 = reg8(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86); + uc = instr_binary_byte(*(unsigned char *)MEM_BASE32(cs + eip)>>3, + *reg_8, instr_read_byte(x86->modrm(MEM_BASE32(cs + eip), + x86, &inst_len)), &EFLAGS); + if (*(unsigned char *)MEM_BASE32(cs + eip)<0x38) *reg_8 = uc; + eip += 2 + inst_len; break; + + case 0x03: /* add reg,r/m16 */ + case 0x0b: /* or reg,r/m16 */ + case 0x13: /* adc reg,r/m16 */ + case 0x1b: /* sbb reg,r/m16 */ + case 0x23: /* and reg,r/m16 */ + case 0x2b: /* sub reg,r/m16 */ + case 0x33: /* xor reg,r/m16 */ + case 0x3b: /* cmp reg,r/m16 */ + dstreg = reg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86); + und = x86->instr_binary(*(unsigned char *)MEM_BASE32(cs + eip)>>3, + *dstreg, x86->instr_read(x86->modrm(MEM_BASE32(cs + eip), x86, + &inst_len)), &EFLAGS); + if (*(unsigned char *)MEM_BASE32(cs + eip)<0x38) { + if (x86->operand_size == 2) + R_WORD(*dstreg) = und; + else + *dstreg = und; + } + eip += 2 + inst_len; break; + + case 0x04: /* add al,imm8 */ + case 0x0c: /* or al,imm8 */ + case 0x14: /* adc al,imm8 */ + case 0x1c: /* sbb al,imm8 */ + case 0x24: /* and al,imm8 */ + case 0x2c: /* sub al,imm8 */ + case 0x34: /* xor al,imm8 */ + case 0x3c: /* cmp al,imm8 */ + uc = instr_binary_byte(*(unsigned char *)MEM_BASE32(cs + eip)>>3, AL, + *(unsigned char *)MEM_BASE32(cs + eip + 1), &EFLAGS); + if (*(unsigned char *)MEM_BASE32(cs + eip)<0x38) AL = uc; + eip += 2; break; + + case 0x05: /* add ax,imm16 */ + case 0x0d: /* or ax,imm16 */ + case 0x15: /* adc ax,imm16 */ + case 0x1d: /* sbb ax,imm16 */ + case 0x25: /* and ax,imm16 */ + case 0x2d: /* sub ax,imm16 */ + case 0x35: /* xor ax,imm16 */ + case 0x3d: /* cmp ax,imm16 */ + und = x86->instr_binary(*(unsigned char *)MEM_BASE32(cs + eip)>>3, + x86->eax, R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)), &EFLAGS); + if (x86->operand_size == 2) { + if (*(unsigned char *)MEM_BASE32(cs + eip)<0x38) AX = und; + eip += 3; + } else { + if (*(unsigned char *)MEM_BASE32(cs + eip)<0x38) x86->eax = und; + eip += 5; + } + break; + + case 0x06: /* push sreg */ + case 0x0e: + case 0x16: + case 0x1e: + push(*sreg(*(unsigned char *)MEM_BASE32(cs + eip)>>3, x86), x86); + eip++; break; + + case 0x07: /* pop es */ + if (pmode || x86->operand_size == 4) + return 0; + else { + pop(&x86->es, x86); + SREG(es) = x86->es; + x86->es_base = SEGOFF2LINEAR(x86->es, 0); + eip++; + } + break; + + /* don't do 0x0f (extended instructions) for now */ + /* 0x17 pop ss is a bit dangerous and rarely used */ + + case 0x1f: /* pop ds */ + if (pmode || x86->operand_size == 4) + return 0; + else { + pop(&x86->ds, x86); + SREG(ds) = x86->ds; + x86->ds_base = SEGOFF2LINEAR(x86->ds, 0); + x86->seg_base = x86->ds_base; + eip++; + } + break; + + case 0x27: /* daa */ + if (((AL & 0xf) > 9) || (EFLAGS&AF)) { + AL += 6; + EFLAGS |= AF; + } else + EFLAGS &= ~AF; + if ((AL > 0x9f) || (EFLAGS&CF)) { + AL += 0x60; + instr_flags(AL, 0x80, &EFLAGS); + EFLAGS |= CF; + } else + instr_flags(AL, 0x80, &EFLAGS); + eip++; break; + + case 0x2f: /* das */ + if (((AL & 0xf) > 9) || (EFLAGS&AF)) { + AL -= 6; + EFLAGS |= AF; + } else + EFLAGS &= ~AF; + if ((AL > 0x9f) || (EFLAGS&CF)) { + AL -= 0x60; + instr_flags(AL, 0x80, &EFLAGS); + EFLAGS |= CF; + } else + instr_flags(AL, 0x80, &EFLAGS); + eip++; break; + + case 0x37: /* aaa */ + if (((AL & 0xf) > 9) || (EFLAGS&AF)) { + AL = (x86->eax+6) & 0xf; + AH++; + EFLAGS |= (CF|AF); + } else + EFLAGS &= ~(CF|AF); + eip++; break; + + case 0x3f: /* aas */ + if (((AL & 0xf) > 9) || (EFLAGS&AF)) { + AL = (x86->eax-6) & 0xf; + AH--; + EFLAGS |= (CF|AF); + } else + EFLAGS &= ~(CF|AF); + eip++; break; + + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: /* inc reg */ + EFLAGS &= ~(OF|ZF|SF|PF|AF); + dstreg = reg(*(unsigned char *)MEM_BASE32(cs + eip), x86); + if (x86->operand_size == 2) { + OPandFLAG0(unl, incw, R_WORD(*dstreg), =r); + } else { + OPandFLAG0(unl, incl, *dstreg, =r); + } + EFLAGS |= unl & (OF|ZF|SF|PF|AF); + eip++; break; + + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: /* dec reg */ + EFLAGS &= ~(OF|ZF|SF|PF|AF); + dstreg = reg(*(unsigned char *)MEM_BASE32(cs + eip), x86); + if (x86->operand_size == 2) { + OPandFLAG0(unl, decw, R_WORD(*dstreg), =r); + } else { + OPandFLAG0(unl, decl, *dstreg, =r); + } + EFLAGS |= unl & (OF|ZF|SF|PF|AF); + eip++; break; + + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: /* push reg */ + push(*reg(*(unsigned char *)MEM_BASE32(cs + eip),x86), x86); + eip++; break; + + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: /* pop reg */ + pop(&und, x86); + if (x86->operand_size == 2) + R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + eip),x86)) = und; + else + *reg(*(unsigned char *)MEM_BASE32(cs + eip),x86) = und; + eip++; break; + + /* 0x60 */ + case 0x68: /* push imm16 */ + push(R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)), x86); + eip += x86->operand_size + 1; break; + + case 0x6a: /* push imm8 */ + push((int)*(signed char *)MEM_BASE32(cs + eip + 1), x86); + eip += 2; break; + + case 0x70: OP_JCC(EFLAGS & OF); /*jo*/ + case 0x71: OP_JCC(!(EFLAGS & OF)); /*jno*/ + case 0x72: OP_JCC(EFLAGS & CF); /*jc*/ + case 0x73: OP_JCC(!(EFLAGS & CF)); /*jnc*/ + case 0x74: OP_JCC(EFLAGS & ZF); /*jz*/ + case 0x75: OP_JCC(!(EFLAGS & ZF)); /*jnz*/ + case 0x76: OP_JCC(EFLAGS & (ZF|CF)); /*jbe*/ + case 0x77: OP_JCC(!(EFLAGS & (ZF|CF))); /*ja*/ + case 0x78: OP_JCC(EFLAGS & SF); /*js*/ + case 0x79: OP_JCC(!(EFLAGS & SF)); /*jns*/ + case 0x7a: OP_JCC(EFLAGS & PF); /*jp*/ + case 0x7b: OP_JCC(!(EFLAGS & PF)); /*jnp*/ + case 0x7c: OP_JCC((EFLAGS & SF)^((EFLAGS & OF)>>4)) /*jl*/ + case 0x7d: OP_JCC(!((EFLAGS & SF)^((EFLAGS & OF)>>4))) /*jnl*/ + case 0x7e: OP_JCC((EFLAGS & (SF|ZF))^((EFLAGS & OF)>>4)) /*jle*/ + case 0x7f: OP_JCC(!((EFLAGS & (SF|ZF))^((EFLAGS & OF)>>4))) /*jg*/ + + case 0x80: /* logical r/m8,imm8 */ + case 0x82: + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + uc = instr_binary_byte(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, + instr_read_byte(mem), *(unsigned char *)MEM_BASE32(cs + eip + 2 + inst_len), &EFLAGS); + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38) < 0x38) + instr_write_byte(mem, uc); + eip += 3 + inst_len; break; + + case 0x81: /* logical r/m,imm */ + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + und = x86->instr_binary(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, + x86->instr_read(mem), R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 2 + inst_len)), &EFLAGS); + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38) < 0x38) x86->instr_write(mem, und); + eip += x86->operand_size + 2 + inst_len; + break; + + case 0x83: /* logical r/m,imm8 */ + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + und = x86->instr_binary(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, + x86->instr_read(mem), (int)*(signed char *)MEM_BASE32(cs + eip + 2 + inst_len), + &EFLAGS); + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38) < 0x38) + x86->instr_write(mem, und); + eip += inst_len + 3; break; + + case 0x84: /* test r/m8, reg8 */ + instr_flags(instr_read_byte(x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len)) & + *reg8(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3,x86), + 0x80, &EFLAGS); + eip += inst_len + 2; break; + + case 0x85: /* test r/m16, reg */ + if (x86->operand_size == 2) + instr_flags(instr_read_word(x86->modrm(MEM_BASE32(cs + eip), x86, + &inst_len)) & R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3,x86)), + 0x8000, &EFLAGS); + else + instr_flags(instr_read_dword(x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len)) & + *reg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3,x86), + 0x80000000, &EFLAGS); + eip += inst_len + 2; break; + + case 0x86: /* xchg r/m8,reg8 */ + reg_8 = reg8(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86); + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + uc = *reg_8; + *reg_8 = instr_read_byte(mem); + instr_write_byte(mem, uc); + eip += inst_len + 2; break; + + case 0x87: /* xchg r/m16,reg */ + dstreg = reg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86); + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + und = *dstreg; + if (x86->operand_size == 2) + R_WORD(*dstreg) = instr_read_word(mem); + else + *dstreg = instr_read_dword(mem); + x86->instr_write(mem, und); + eip += inst_len + 2; break; + + case 0x88: /* mov r/m8,reg8 */ + instr_write_byte(x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len), + *reg8(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86)); + eip += inst_len + 2; break; + + case 0x89: /* mov r/m16,reg */ + x86->instr_write(x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len), + *reg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86)); + eip += inst_len + 2; break; + + case 0x8a: /* mov reg8,r/m8 */ + *reg8(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86) = + instr_read_byte(x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len)); + eip += inst_len + 2; break; + + case 0x8b: /* mov reg,r/m16 */ + if (x86->operand_size == 2) + R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86)) = + instr_read_word(x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len)); + else + *reg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86) = + instr_read_dword(x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len)); + eip += inst_len + 2; break; + + case 0x8c: /* mov r/m16,segreg */ + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1) & 0xc0) == 0xc0) /* compensate for mov r,segreg */ + mem = (unsigned char *)reg(*(unsigned char *)MEM_BASE32(cs + eip + 1), x86); + instr_write_word(mem, *sreg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, x86)); + eip += inst_len + 2; break; + + case 0x8d: /* lea */ + { + unsigned mem = x86->seg_ss_base; + x86->seg_ss_base = x86->seg_base; + if (x86->operand_size == 2) + R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3,x86)) = + x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len) - (unsigned char *)MEM_BASE32(x86->seg_base); + else + *reg(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3,x86) = + x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len) - (unsigned char *)MEM_BASE32(x86->seg_base); + x86->seg_ss_base = mem; + eip += inst_len + 2; break; + } + + case 0x8e: /* mov segreg,r/m16 */ + if (pmode || x86->operand_size == 4) + return 0; + else switch (*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38) { + case 0: + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1) & 0xc0) == 0xc0) /* compensate for mov r,segreg */ + mem = (unsigned char *)reg(*(unsigned char *)MEM_BASE32(cs + eip + 1), x86); + SREG(es) = x86->es = instr_read_word(mem); + x86->es_base = SEGOFF2LINEAR(x86->es, 0); + eip += inst_len + 2; break; + case 0x18: + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1) & 0xc0) == 0xc0) /* compensate for mov es,reg */ + mem = (unsigned char *)reg(*(unsigned char *)MEM_BASE32(cs + eip + 1), x86); + SREG(ds) = x86->ds = instr_read_word(mem); + x86->ds_base = SEGOFF2LINEAR(x86->ds, 0); + x86->seg_base = x86->ds_base; + eip += inst_len + 2; break; + default: + return 0; + } + break; + + case 0x8f: /*pop*/ + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38) == 0){ + pop(&und, x86); + x86->instr_write(x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len), und); + eip += inst_len + 2; + } else + return 0; + break; + + case 0x90: /* nop */ + eip++; break; + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: /* xchg reg, ax */ + dstreg = reg(*(unsigned char *)MEM_BASE32(cs + eip),x86); + und = x86->eax; + if (x86->operand_size == 2) { + AX = *dstreg; + R_WORD(*dstreg) = und; + } else { + x86->eax = *dstreg; + *dstreg = und; + } + eip++; break; + + case 0x98: + if (x86->operand_size == 2) { /* cbw */ + AH = (AL & 0x80) ? 0xff : 0; + } else { /* cwde */ + if (AX & 0x8000) + x86->eax |= 0xffff0000; + else + x86->eax &= 0x0000ffff; + } + eip++; break; + + case 0x99: + if (x86->operand_size == 2) /* cwd */ + DX = (AX > 0x7fff ? 0xffff : 0); + else /* cdq */ + x86->edx = (x86->eax > 0x7fffffff ? 0xffffffff : 0); + eip++; break; + + case 0x9a: /*call far*/ + if (pmode || x86->operand_size == 4) + return 0; + else { + push(x86->cs, x86); + push(eip + 5, x86); + x86->cs = R_WORD(*(unsigned char *)MEM_BASE32(cs + eip + 3)); + SREG(cs) = x86->cs; + x86->cs_base = SEGOFF2LINEAR(x86->cs, 0); + eip = R_WORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)); + cs = x86->cs_base; + } + break; + /* NO: 0x9b wait 0x9c pushf 0x9d popf*/ + + case 0x9e: /* sahf */ + R_LO(EFLAGS) = AH; + eip++; break; + + case 0x9f: /* lahf */ + AH = R_LO(EFLAGS); + eip++; break; + + case 0xa0: /* mov al,moff16 */ + AL = instr_read_byte(MEM_BASE32((R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)) & + wordmask[x86->address_size])+x86->seg_base)); + eip += 1 + x86->address_size; break; + + case 0xa1: /* mov ax,moff16 */ + if (x86->operand_size == 2) + AX = instr_read_word(MEM_BASE32((R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)) & + wordmask[x86->address_size])+x86->seg_base)); + else + x86->eax = instr_read_dword(MEM_BASE32((R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)) & + wordmask[x86->address_size])+x86->seg_base)); + eip += 1 + x86->address_size; break; + + case 0xa2: /* mov moff16,al */ + instr_write_byte(MEM_BASE32((R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)) & + wordmask[x86->address_size])+x86->seg_base), AL); + eip += 1 + x86->address_size; break; + + case 0xa3: /* mov moff16,ax */ + x86->instr_write(MEM_BASE32((R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)) & + wordmask[x86->address_size])+x86->seg_base), x86->eax); + eip += 1 + x86->address_size; break; + + case 0xa4: /* movsb */ + if (x86->address_size == 4) { + instr_write_byte(MEM_BASE32(x86->es_base + x86->edi), + instr_read_byte(MEM_BASE32(x86->seg_base + x86->esi))); + x86->edi += loop_inc; + x86->esi += loop_inc; + } else { + instr_write_byte(MEM_BASE32(x86->es_base + DI), + instr_read_byte(MEM_BASE32(x86->seg_base + SI))); + DI += loop_inc; + SI += loop_inc; + } + eip++; break; + + case 0xa5: /* movsw */ + if (x86->address_size == 4) { + x86->instr_write(MEM_BASE32(x86->es_base + x86->edi), + x86->instr_read(MEM_BASE32(x86->seg_base + x86->esi))); + x86->edi += loop_inc * x86->operand_size; + x86->esi += loop_inc * x86->operand_size; + } + else { + x86->instr_write(MEM_BASE32(x86->es_base + DI), + x86->instr_read(MEM_BASE32(x86->seg_base + SI))); + DI += loop_inc * x86->operand_size; + SI += loop_inc * x86->operand_size; + } + eip++; break; + + case 0xa6: /*cmpsb */ + if (x86->address_size == 4) { + instr_binary_byte(7, instr_read_byte(MEM_BASE32(x86->seg_base + x86->esi)), + instr_read_byte(MEM_BASE32(x86->es_base + x86->edi)), &EFLAGS); + x86->edi += loop_inc; + x86->esi += loop_inc; + } else { + instr_binary_byte(7, instr_read_byte(MEM_BASE32(x86->seg_base + SI)), + instr_read_byte(MEM_BASE32(x86->es_base + DI)), &EFLAGS); + DI += loop_inc; + SI += loop_inc; + } + eip++; break; + + case 0xa7: /* cmpsw */ + if (x86->address_size == 4) { + x86->instr_binary(7, x86->instr_read(MEM_BASE32(x86->seg_base + x86->esi)), + x86->instr_read(MEM_BASE32(x86->es_base + x86->edi)), &EFLAGS); + x86->edi += loop_inc * x86->operand_size; + x86->esi += loop_inc * x86->operand_size; + } else { + x86->instr_binary(7, x86->instr_read(MEM_BASE32(x86->seg_base + SI)), + x86->instr_read(MEM_BASE32(x86->es_base + DI)), &EFLAGS); + DI += loop_inc * x86->operand_size; + SI += loop_inc * x86->operand_size; + } + eip++; break; + + case 0xa8: /* test al, imm */ + instr_flags(AL & *(unsigned char *)MEM_BASE32(cs + eip + 1), 0x80, &EFLAGS); + eip += 2; break; + + case 0xa9: /* test ax, imm */ + if (x86->operand_size == 2) { + instr_flags(AX & R_WORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)), 0x8000, &EFLAGS); + eip += 3; break; + } else { + instr_flags(x86->eax & R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)), 0x80000000, &EFLAGS); + eip += 5; break; + } + + case 0xaa: /* stosb */ + if (x86->address_size == 4) { + instr_write_byte(MEM_BASE32(x86->es_base + x86->edi), AL); + x86->edi += loop_inc; + } else { + instr_write_byte(MEM_BASE32(x86->es_base + DI), AL); + DI += loop_inc; + } + eip++; break; + + case 0xab: /* stosw */ + if (x86->address_size == 4) { + x86->instr_write(MEM_BASE32(x86->es_base + x86->edi), x86->eax); + x86->edi += loop_inc * x86->operand_size; + } else { + x86->instr_write(MEM_BASE32(x86->es_base + DI), x86->eax); + DI += loop_inc * x86->operand_size; + } + eip++; break; + + case 0xac: /* lodsb */ + if (x86->address_size == 4) { + AL = instr_read_byte(MEM_BASE32(x86->seg_base + x86->esi)); + x86->esi += loop_inc; + } else { + AL = instr_read_byte(MEM_BASE32(x86->seg_base + SI)); + SI += loop_inc; + } + eip++; break; + + case 0xad: /* lodsw */ + if (x86->address_size == 4) { + und = x86->instr_read(MEM_BASE32(x86->seg_base + x86->esi)); + x86->esi += loop_inc * x86->operand_size; + } else { + und = x86->instr_read(MEM_BASE32(x86->seg_base + SI)); + SI += loop_inc * x86->operand_size; + } + if (x86->operand_size == 2) + AX = und; + else + x86->eax = und; + eip++; break; + + case 0xae: /* scasb */ + if (x86->address_size == 4) { + instr_binary_byte(7, AL, instr_read_byte(MEM_BASE32(x86->es_base + x86->edi)), &EFLAGS); + x86->edi += loop_inc; + } else { + instr_binary_byte(7, AL, instr_read_byte(MEM_BASE32(x86->es_base + DI)), &EFLAGS); + DI += loop_inc; + } + eip++; break; + + case 0xaf: /* scasw */ + if (x86->address_size == 4) { + x86->instr_binary(7, x86->eax, x86->instr_read(MEM_BASE32(x86->es_base + x86->edi)), &EFLAGS); + x86->edi += loop_inc * x86->operand_size; + } else { + x86->instr_binary(7, x86->eax, x86->instr_read(MEM_BASE32(x86->es_base + DI)), &EFLAGS); + DI += loop_inc * x86->operand_size; + } + eip++; break; + + case 0xb0: + case 0xb1: + case 0xb2: + case 0xb3: + case 0xb4: + case 0xb5: + case 0xb6: + case 0xb7: + *reg8(*(unsigned char *)MEM_BASE32(cs + eip), x86) = *(unsigned char *)MEM_BASE32(cs + eip + 1); + eip += 2; break; + + case 0xb8: + case 0xb9: + case 0xba: + case 0xbb: + case 0xbc: + case 0xbd: + case 0xbe: + case 0xbf: + if (x86->operand_size == 2) { + R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + eip), x86)) = + R_WORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)); + eip += 3; break; + } else { + *reg(*(unsigned char *)MEM_BASE32(cs + eip), x86) = + R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)); + eip += 5; break; + } + + case 0xc0: /* shift byte, imm8 */ + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38)==0x30) return 0; + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + instr_write_byte(mem,instr_shift(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, (signed char) instr_read_byte(mem), + *(unsigned char *)MEM_BASE32(cs + eip + 2+inst_len), 1, &EFLAGS)); + eip += inst_len + 3; break; + + case 0xc1: /* shift word, imm8 */ + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38)==0x30) return 0; + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + if (x86->operand_size == 2) + instr_write_word(mem, instr_shift(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, (short)instr_read_word(mem), + *(unsigned char *)MEM_BASE32(cs + eip + 2+inst_len), 2, &EFLAGS)); + else + instr_write_dword(mem, instr_shift(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, instr_read_dword(mem), + *(unsigned char *)MEM_BASE32(cs + eip + 2+inst_len), 4, &EFLAGS)); + eip += inst_len + 3; break; + + case 0xc2: /* ret imm16*/ + pop(&und, x86); + if (x86->_32bit) + x86->esp += R_WORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)); + else + SP += R_WORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)); + eip = und; + break; + + case 0xc3: /* ret */ + pop(&eip, x86); + break; + + case 0xc4: /* les */ + if (pmode || x86->operand_size == 4) + return 0; + else { + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + x86->es = instr_read_word(mem+2); + SREG(es) = x86->es; + x86->es_base = SEGOFF2LINEAR(x86->es, 0); + R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + eip + 1) >> 3, x86)) = instr_read_word(mem); + eip += inst_len + 2; break; + } + + case 0xc5: /* lds */ + if (pmode || x86->operand_size == 4) + return 0; + else { + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + x86->ds = instr_read_word(mem+2); + SREG(ds) = x86->ds; + x86->ds_base = x86->seg_base = SEGOFF2LINEAR(x86->ds, 0); + R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + eip + 1) >> 3, x86)) = instr_read_word(mem); + eip += inst_len + 2; break; + } + + case 0xc6: /* mov r/m8,imm8 */ + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + instr_write_byte(mem, *(unsigned char *)MEM_BASE32(cs + eip + 2 + inst_len)); + eip += inst_len + 3; break; + + case 0xc7: /* mov r/m,imm */ + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + x86->instr_write(mem, R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 2 + inst_len))); + eip += x86->operand_size + inst_len + 2; + break; + /* 0xc8 enter */ + + case 0xc9: /*leave*/ + if (x86->_32bit) + x86->esp = x86->ebp; + else + SP = BP; + pop(&x86->ebp, x86); + eip++; break; + + case 0xca: /*retf imm 16*/ + if (pmode || x86->operand_size == 4) + return 0; + else { + pop(&und, x86); + pop(&x86->cs, x86); + SREG(cs) = x86->cs; + x86->cs_base = SEGOFF2LINEAR(x86->cs, 0); + SP += R_WORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)); + cs = x86->cs_base; + eip = und; + } + break; + + case 0xcb: /*retf*/ + if (pmode || x86->operand_size == 4) + return 0; + else { + pop(&eip, x86); + pop(&x86->cs, x86); + SREG(cs) = x86->cs; + x86->cs_base = SEGOFF2LINEAR(x86->cs, 0); + cs = x86->cs_base; + } + break; + + /* 0xcc int3 0xcd int 0xce into 0xcf iret */ + + case 0xd0: /* shift r/m8, 1 */ + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38)==0x30) return 0; + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + instr_write_byte(mem, instr_shift(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, + (signed char) instr_read_byte(mem), + 1, 1, &EFLAGS)); + eip += inst_len + 2; break; + + case 0xd1: /* shift r/m16, 1 */ + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38)==0x30) return 0; + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + if (x86->operand_size == 2) + instr_write_word(mem, instr_shift(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, (short) instr_read_word(mem), + 1, 2, &EFLAGS)); + else + instr_write_dword(mem, instr_shift(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, instr_read_dword(mem), 1, 4, &EFLAGS)); + eip += inst_len + 2; break; + + case 0xd2: /* shift r/m8, cl */ + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38)==0x30) return 0; + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + instr_write_byte(mem,instr_shift(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, (signed char) instr_read_byte(mem), + CL, 1, &EFLAGS)); + eip += inst_len + 2; break; + + case 0xd3: /* shift r/m16, cl */ + if ((*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38)==0x30) return 0; + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + if (x86->operand_size == 2) + instr_write_word(mem, instr_shift(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, (short) instr_read_word(mem), + CL, 2, &EFLAGS)); + else + instr_write_dword(mem, instr_shift(*(unsigned char *)MEM_BASE32(cs + eip + 1)>>3, instr_read_dword(mem), + CL, 4, &EFLAGS)); + eip += inst_len + 2; break; + + case 0xd4: /* aam byte */ + AH = AL / *(unsigned char *)MEM_BASE32(cs + eip + 1); + AL = AL % *(unsigned char *)MEM_BASE32(cs + eip + 1); + instr_flags(AL, 0x80, &EFLAGS); + eip += 2; break; + + case 0xd5: /* aad byte */ + AL = AH * *(unsigned char *)MEM_BASE32(cs + eip + 1) + AL; + AH = 0; + instr_flags(AL, 0x80, &EFLAGS); + eip += 2; break; + + case 0xd6: /* salc */ + AL = EFLAGS & CF ? 0xff : 0; + eip++; break; + + case 0xd7: /* xlat */ + AL = instr_read_byte(MEM_BASE32(x86->seg_base+(x86->ebx & wordmask[x86->address_size])+AL)); + eip++; break; + /* 0xd8 - 0xdf copro */ + + case 0xe0: /* loopnz */ + eip += ( (x86->address_size == 4 ? --x86->ecx : --CX) && !(EFLAGS & ZF) ? + 2 + *(signed char *)MEM_BASE32(cs + eip + 1) : 2); break; + + case 0xe1: /* loopz */ + eip += ( (x86->address_size == 4 ? --x86->ecx : --CX) && (EFLAGS & ZF) ? + 2 + *(signed char *)MEM_BASE32(cs + eip + 1) : 2); break; + + case 0xe2: /* loop */ + eip += ( (x86->address_size == 4 ? --x86->ecx : --CX) ? + 2 + *(signed char *)MEM_BASE32(cs + eip + 1) : 2); break; + + case 0xe3: /* jcxz */ + eip += ((x86->address_size == 4 ? x86->ecx : CX) ? 2 : + 2 + *(signed char *)MEM_BASE32(cs + eip + 1)); + break; + + /* 0xe4 in ib 0xe5 in iw 0xe6 out ib 0xe7 out iw */ + + case 0xe8: /* call near */ + push(eip + 1 + x86->operand_size, x86); + /* fall through */ + + case 0xe9: /* jmp near */ + eip += x86->operand_size + 1 + (R_DWORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)) & wordmask[x86->operand_size]); + break; + + case 0xea: /*jmp far*/ + if (pmode || x86->operand_size == 4) + return 0; + else { + x86->cs = R_WORD(*(unsigned char *)MEM_BASE32(cs + eip+3)); + SREG(cs) = x86->cs; + x86->cs_base = SEGOFF2LINEAR(x86->cs, 0); + eip = R_WORD(*(unsigned char *)MEM_BASE32(cs + eip + 1)); + cs = x86->cs_base; + } + break; + + case 0xeb: /* jmp short */ + eip += 2 + *(signed char *)MEM_BASE32(cs + eip + 1); break; + + case 0xec: /* in al, dx */ + /* Note that we short circuit if we can */ + if ((uc=VGA_emulate_inb(DX))!=0xff) { + AL = uc; + eip++; break; + } + else + return 0; + /* 0xed in ax,dx */ + + case 0xee: /* out dx, al */ + /* Note that we short circuit if we can */ + if (VGA_emulate_outb(DX, AL) && vga.inst_emu) + eip++; + else + return 0; + break; + + case 0xef: /* out dx, ax */ + if ((x86->operand_size == 2) && + VGA_emulate_outb(DX, AL) && + VGA_emulate_outb(DX + 1, AH) && + vga.inst_emu) + eip++; + else + return 0; + break; + + /* 0xf0 lock 0xf1 int1 */ + + /* 0xf2 repnz 0xf3 repz handled above */ + /* 0xf4 hlt */ + + case 0xf5: /* cmc */ + EFLAGS ^= CF; + eip++; break; + + case 0xf6: + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + switch (*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38) { + case 0x00: /* test mem byte, imm */ + instr_flags(instr_read_byte(mem) & *(unsigned char *)MEM_BASE32(cs + eip + 2+inst_len), 0x80, &EFLAGS); + eip += inst_len + 3; break; + case 0x08: return 0; + case 0x10: /*not byte*/ + instr_write_byte(mem, ~instr_read_byte(mem)); + eip += inst_len + 2; break; + case 0x18: /*neg byte*/ + instr_write_byte(mem, instr_binary_byte(7, 0, instr_read_byte(mem), &EFLAGS)); + eip += inst_len + 2; break; + case 0x20: /*mul byte*/ + AX = AL * instr_read_byte(mem); + EFLAGS &= ~(CF|OF); + if (AH) + EFLAGS |= (CF|OF); + eip += inst_len + 2; break; + case 0x28: /*imul byte*/ + AX = (signed char)AL * (signed char)instr_read_byte(mem); + EFLAGS &= ~(CF|OF); + if (AH) + EFLAGS |= (CF|OF); + eip += inst_len + 2; break; + case 0x30: /*div byte*/ + und = AX; + uc = instr_read_byte(mem); + if (uc == 0) return 0; + und2 = und / uc; + if (und2 & 0xffffff00) return 0; + AL = und2 & 0xff; + AH = und % uc; + eip += inst_len + 2; break; + case 0x38: /*idiv byte*/ + i = (short)AX; + uc = instr_read_byte(mem); + if (uc == 0) return 0; + i2 = i / (signed char)uc; + if (i2<-128 || i2>127) return 0; + AL = i2 & 0xff; + AH = i % (signed char)uc; + eip += inst_len + 2; break; + } + break; + + case 0xf7: + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + switch (*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38) { + case 0x00: /* test mem word, imm */ + if (x86->operand_size == 4) return 0; + instr_flags(instr_read_word(mem) & R_WORD(*(unsigned char *)MEM_BASE32(cs + eip + 2+inst_len)), 0x8000, &EFLAGS); + eip += inst_len + 4; break; + case 0x08: return 0; + case 0x10: /*not word*/ + x86->instr_write(mem, ~x86->instr_read(mem)); + eip += inst_len + 2; break; + case 0x18: /*neg word*/ + x86->instr_write(mem, x86->instr_binary(7, 0, x86->instr_read(mem), &EFLAGS)); + eip += inst_len + 2; break; + case 0x20: /*mul word*/ + if (x86->operand_size == 4) return 0; + und = AX * instr_read_word(mem); + AX = und & 0xffff; + DX = und >> 16; + EFLAGS &= ~(CF|OF); + if (DX) + EFLAGS |= (CF|OF); + eip += inst_len + 2; break; + case 0x28: /*imul word*/ + if (x86->operand_size == 4) return 0; + i = (short)AX * (short)instr_read_word(mem); + AX = i & 0xffff; + DX = i >> 16; + EFLAGS &= ~(CF|OF); + if (DX) + EFLAGS |= (CF|OF); + eip += inst_len + 2; break; + case 0x30: /*div word*/ + if (x86->operand_size == 4) return 0; + und = ((uint32_t)DX<<16) + AX; + uns = instr_read_word(mem); + if (uns == 0) return 0; + und2 = und / uns; + if (und2 & 0xffff0000) return 0; + AX = und2 & 0xffff; + DX = und % uns; + eip += inst_len + 2; break; + case 0x38: /*idiv word*/ + if (x86->operand_size == 4) return 0; + i = ((uint32_t)DX<<16) + AX; + uns = instr_read_word(mem); + if (uns == 0) return 0; + i2 = i / (short)uns; + if (i2<-32768 || i2>32767) return 0; + AX = i2 & 0xffff; + DX = i % (short)uns; + eip += inst_len + 2; break; + } + break; + + case 0xf8: /* clc */ + EFLAGS &= ~CF; + eip++; break; + + case 0xf9: /* stc */ + EFLAGS |= CF; + eip++; break; + + /* 0xfa cli 0xfb sti */ + + case 0xfc: /* cld */ + EFLAGS &= ~DF; + loop_inc = 1; + eip++; break; + + case 0xfd: /* std */ + EFLAGS |= DF; + loop_inc = -1; + eip++; break; + + case 0xfe: /* inc/dec mem */ + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + uc = instr_read_byte(mem); + switch (*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38) { + case 0x00: + EFLAGS &= ~(OF|ZF|SF|PF|AF); + OPandFLAG0(unl, incb, uc, =q); + EFLAGS |= unl & (OF|ZF|SF|PF|AF); + instr_write_byte(mem, uc); + eip += inst_len + 2; break; + case 0x08: + EFLAGS &= ~(OF|ZF|SF|PF|AF); + OPandFLAG0(unl, decb, uc, =q); + EFLAGS |= unl & (OF|ZF|SF|PF|AF); + instr_write_byte(mem, uc); + eip += inst_len + 2; break; + default: + return 0; + } + break; + + case 0xff: + if (x86->operand_size == 4) return 0; + mem = x86->modrm(MEM_BASE32(cs + eip), x86, &inst_len); + uns = instr_read_word(mem); + switch (*(unsigned char *)MEM_BASE32(cs + eip + 1)&0x38) { + case 0x00: /* inc */ + EFLAGS &= ~(OF|ZF|SF|PF|AF); + OPandFLAG0(unl, incw, uns, =r); + EFLAGS |= unl & (OF|ZF|SF|PF|AF); + instr_write_word(mem, uns); + eip += inst_len + 2; break; + case 0x08: /* dec */ + EFLAGS &= ~(OF|ZF|SF|PF|AF); + OPandFLAG0(unl, decw, uns, =r); + EFLAGS |= unl & (OF|ZF|SF|PF|AF); + instr_write_word(mem, uns); + eip += inst_len + 2; break; + case 0x10: /*call near*/ + push(eip + inst_len + 2, x86); + eip = uns; + break; + + case 0x18: /*call far*/ + if (pmode || x86->operand_size == 4) + return 0; + else { + push(x86->cs, x86); + x86->cs = instr_read_word(mem+2); + push(eip + inst_len + 2, x86); + SREG(cs) = x86->cs; + x86->cs_base = SEGOFF2LINEAR(x86->cs, 0); + eip = uns; + cs = x86->cs_base; + } + break; + + case 0x20: /*jmp near*/ + eip = uns; + break; + + case 0x28: /*jmp far*/ + if (pmode || x86->operand_size == 4) + return 0; + else { + x86->cs = instr_read_word(mem+2); + SREG(cs) = x86->cs; + x86->cs_base = SEGOFF2LINEAR(x86->cs, 0); + eip = uns; + cs = x86->cs_base; + } + break; + + case 0x30: /*push*/ + push(uns, x86); + eip += inst_len + 2; break; + default: + return 0; + } + break; + + default: /* First byte doesn't match anything */ + return 0; + } /* switch (cs[eip]) */ + + eip &= wordmask[(x86->_32bit + 1) * 2]; + x86->eip = eip; + +#if DEBUG_INSTR >= 2 + dump_x86_regs(x86); +#endif + + return 1; +} + +static void scp_to_x86_regs(x86_regs *x86, sigcontext_t *scp, int pmode) { if(pmode) { x86->eax = _eax; @@ -749,7 +2409,7 @@ static void scp_to_x86_regs(x86_regs *x86, cpuctx_t *scp, int pmode) prepare_x86(x86); } -static void x86_regs_to_scp(x86_regs *x86, cpuctx_t *scp, int pmode) +static void x86_regs_to_scp(x86_regs *x86, sigcontext_t *scp, int pmode) { if(pmode) { _cs = x86->cs; @@ -783,10 +2443,66 @@ static void x86_regs_to_scp(x86_regs *x86, cpuctx_t *scp, int pmode) } } -int decode_modify_segreg_insn(cpuctx_t *scp, int pmode, +/* + * DANG_BEGIN_FUNCTION instr_emu + * + * description: + * instr_emu is the main interface to instr_sim. It puts the processor + * state in the x86 structure. + * + * arguments: + * scp - A pointer to a sigcontext_t holding some relevant data. + * pmode - flags protected mode + * cnt - number of instructions to be simulated + * + * DANG_END_FUNCTION + */ + +int instr_emu(sigcontext_t *scp, int pmode, int cnt) +{ +#if DEBUG_INSTR >= 1 + int refseg, rc; +#endif + int i = 0; + x86_regs x86; + + scp_to_x86_regs(&x86, scp, pmode); + count = cnt ? : COUNT + 1; + x86.prefixes = 1; + + do { + if (!instr_sim(&x86, pmode)) { + if (debug_level('v')) { +#ifdef USE_MHPDBG + dosaddr_t cp = SEGOFF2LINEAR(x86.cs, x86.eip); + unsigned int ref; + char frmtbuf[256]; + dis_8086(cp, frmtbuf, x86._32bit ? 3 : 0, &ref, x86.cs_base); + instr_deb("vga_emu_fault: %u bytes not simulated %d: %s\n", + instr_len(MEM_BASE32(cp), x86._32bit), count, frmtbuf); +#endif + dump_x86_regs(&x86); + } + break; + } + i++; + if (!cnt && signal_pending()) + break; + } while (--count > 0); + + if (debug_level('v') >= 5) + instr_deb("simulated %i, left %i\n", i, count); + if (i == 0) /* really an unknown instruction from the beginning */ + return False; + + x86_regs_to_scp(&x86, scp, pmode); + return True; +} + +int decode_modify_segreg_insn(sigcontext_t *scp, int pmode, unsigned int *new_val) { - struct rm mem = {}; + unsigned char *mem; unsigned cs; int inst_len, ret = -1; x86_regs x86; @@ -802,9 +2518,8 @@ int decode_modify_segreg_insn(cpuctx_t *scp, int pmode, ret = sreg_idx(*(unsigned char *)MEM_BASE32(cs + x86.eip + 1) >> 3); mem = x86.modrm(MEM_BASE32(cs + x86.eip), &x86, &inst_len); if ((*(unsigned char *)MEM_BASE32(cs + x86.eip + 1) & 0xc0) == 0xc0) /* compensate for mov r,segreg */ - memcpy(new_val, reg(*(unsigned char *)MEM_BASE32(cs + x86.eip + 1), &x86), 2); - else - *new_val = instr_read_word(mem); + mem = (unsigned char *)reg(*(unsigned char *)MEM_BASE32(cs + x86.eip + 1), &x86); + *new_val = instr_read_word(mem); x86.eip += inst_len + 2; break; @@ -835,8 +2550,8 @@ int decode_modify_segreg_insn(cpuctx_t *scp, int pmode, case 0xea: /* jmp seg:off16/off32 */ { unsigned tmp_eip; - tmp_eip = x86.instr_read(M(x86.cs_base + x86.eip + 1)); - *new_val = instr_read_word(M(x86.cs_base + x86.eip + 1 + x86.operand_size)); + tmp_eip = x86.instr_read(MEM_BASE32(x86.cs_base + x86.eip + 1)); + *new_val = instr_read_word(MEM_BASE32(x86.cs_base + x86.eip + 1 + x86.operand_size)); ret = cs_INDEX; x86.eip = tmp_eip; } @@ -844,7 +2559,7 @@ int decode_modify_segreg_insn(cpuctx_t *scp, int pmode, case 0xc4: /* les */ mem = x86.modrm(MEM_BASE32(cs + x86.eip), &x86, &inst_len); - *new_val = instr_read_word(M(mem.m+x86.operand_size)); + *new_val = instr_read_word(mem+x86.operand_size); if (x86.operand_size == 2) R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + x86.eip + 1) >> 3, &x86)) = instr_read_word(mem); else @@ -855,7 +2570,7 @@ int decode_modify_segreg_insn(cpuctx_t *scp, int pmode, case 0xc5: /* lds */ mem = x86.modrm(MEM_BASE32(cs + x86.eip), &x86, &inst_len); - *new_val = instr_read_word(M(mem.m+x86.operand_size)); + *new_val = instr_read_word(mem+x86.operand_size); if (x86.operand_size == 2) R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + x86.eip + 1) >> 3, &x86)) = instr_read_word(mem); else @@ -884,7 +2599,7 @@ int decode_modify_segreg_insn(cpuctx_t *scp, int pmode, case 0xb2: /* lss */ mem = x86.modrm(MEM_BASE32(cs + x86.eip), &x86, &inst_len); - *new_val = instr_read_word(M(mem.m+x86.operand_size)); + *new_val = instr_read_word(mem+x86.operand_size); if (x86.operand_size == 2) R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + x86.eip + 1) >> 3, &x86)) = instr_read_word(mem); else @@ -895,7 +2610,7 @@ int decode_modify_segreg_insn(cpuctx_t *scp, int pmode, case 0xb4: /* lfs */ mem = x86.modrm(MEM_BASE32(cs + x86.eip), &x86, &inst_len); - *new_val = instr_read_word(M(mem.m+x86.operand_size)); + *new_val = instr_read_word(mem+x86.operand_size); if (x86.operand_size == 2) R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + x86.eip + 1) >> 3, &x86)) = instr_read_word(mem); else @@ -906,7 +2621,7 @@ int decode_modify_segreg_insn(cpuctx_t *scp, int pmode, case 0xb5: /* lgs */ mem = x86.modrm(MEM_BASE32(cs + x86.eip), &x86, &inst_len); - *new_val = instr_read_word(M(mem.m+x86.operand_size)); + *new_val = instr_read_word(mem+x86.operand_size); if (x86.operand_size == 2) R_WORD(*reg(*(unsigned char *)MEM_BASE32(cs + x86.eip + 1) >> 3, &x86)) = instr_read_word(mem); else diff --git a/src/base/video/render.c b/src/base/video/render.c index 41a95d9..74181bc 100644 --- a/src/base/video/render.c +++ b/src/base/video/render.c @@ -29,7 +29,7 @@ static struct rmcalls_wrp rmcalls[MAX_REMAPS]; static int num_remaps; static int is_updating; static pthread_mutex_t upd_mtx = PTHREAD_MUTEX_INITIALIZER; -static pthread_rwlock_t text_mtx = PTHREAD_RWLOCK_INITIALIZER; +static pthread_mutex_t text_mtx = PTHREAD_MUTEX_INITIALIZER; #if RENDER_THREADED static pthread_t render_thr; #endif @@ -58,7 +58,6 @@ struct render_wrp { }; static struct render_wrp Render; static int initialized; -static int cur_mode_class; __attribute__((warn_unused_result)) static int render_lock(void) @@ -103,7 +102,7 @@ static void check_locked(void) static void render_text_begin(void) { - pthread_rwlock_rdlock(&text_mtx); + pthread_mutex_lock(&text_mtx); text_lock(); Render.render_text++; } @@ -113,7 +112,7 @@ static void render_text_end(void) text_unlock(); Render.render_text--; assert(!Render.text_locked); - pthread_rwlock_unlock(&text_mtx); + pthread_mutex_unlock(&text_mtx); } static void render_text_lock(void *opaque) @@ -332,20 +331,12 @@ static void refresh_graphics_palette(void) dirty_all_video_pages(); } -static int font_is_changed(void) -{ - return memcmp(vga.backup_font, vga.mem.base + 0x20000, 256 * 32); -} - static int suitable_mode_class(void) { /* Add more checks here. * Need to treat any weird text mode as gfx. */ if (vga.char_width < 8 || vga.char_width > 9 || vga.char_height < 8) return GRAPH; - /* check if font wasn't changed */ - if (font_is_changed()) - return GRAPH; return TEXT; } @@ -576,13 +567,9 @@ int render_update_vidmode(void) { int ret = 0; if (Video->setmode) { - struct vid_mode_params vmp; pthread_rwlock_wrlock(&mode_mtx); - vmp = get_mode_parameters(); - ret = Video->setmode(vmp); + ret = Video->setmode(get_mode_parameters()); pthread_rwlock_unlock(&mode_mtx); - if (ret) - cur_mode_class = vmp.mode_class; } return ret; } @@ -613,9 +600,7 @@ int update_screen(void) int upd = render_is_updating(); /* update vidmode before doing any rendering. */ - if(vga.reconfig.display || (cur_mode_class == TEXT && font_is_changed()) || - (vga.mode_class == TEXT && cur_mode_class == GRAPH && - !font_is_changed())) { + if(vga.reconfig.display) { if (upd) return 1; v_printf( @@ -642,6 +627,9 @@ int update_screen(void) Video->update_screen(); } + if (Video->handle_events) + Video->handle_events(); + if(vga.config.video_off) { v_printf("update_screen: nothing done (video_off = 0x%x)\n", vga.config.video_off); return 1; @@ -655,10 +643,10 @@ int update_screen(void) void redraw_text_screen(void) { - pthread_rwlock_wrlock(&text_mtx); + pthread_mutex_lock(&text_mtx); dirty_text_screen(); dirty_all_vga_colors(); - pthread_rwlock_unlock(&text_mtx); + pthread_mutex_unlock(&text_mtx); } void render_gain_focus(void) diff --git a/src/base/video/text.c b/src/base/video/text.c index edc9d59..dd7677b 100644 --- a/src/base/video/text.c +++ b/src/base/video/text.c @@ -49,24 +49,23 @@ static int num_texts; Boolean have_focus; static unsigned prev_cursor_location = -1; -static uint16_t prev_cursor_shape = NO_CURSOR; +static ushort prev_cursor_shape = NO_CURSOR; static int blink_state = 1; static int blink_count = 8; static int need_redraw_cursor; static unsigned char *text_canvas; -static uint16_t prev_screen[MAX_COLUMNS * MAX_LINES]; /* pointer to currently displayed screen */ -static u_char prev_font[256 * 32]; +static ushort prev_screen[MAX_COLUMNS * MAX_LINES]; /* pointer to currently displayed screen */ #if CONFIG_SELECTION static int sel_start_row = -1, sel_end_row = - -1, sel_start_col, sel_end_col, sel_col, sel_row; + -1, sel_start_col, sel_end_col; static unsigned short *sel_start = NULL, *sel_end = NULL; static t_unicode *sel_text = NULL; -static Boolean doing_selection, visible_selection, rect_selection; +static Boolean doing_selection = FALSE, visible_selection = FALSE; #endif -/* macros for accessing video memory. w is an uint16_t* +/* macros for accessing video memory. w is an ushort* to a character cell, attr is a byte. */ @@ -74,22 +73,8 @@ static Boolean doing_selection, visible_selection, rect_selection; #define ATTR(w) (*(((Bit8u *)(w))+1)) #if CONFIG_SELECTION -#define SEL_ACTIVE(x, y) sel_active(x, y) - -static int sel_active(int x, int y) -{ - if (!visible_selection) - return 0; - if (y < sel_start_row || y > sel_end_row) - return 0; - if (x < sel_start_col && (y == sel_start_row || rect_selection)) - return 0; - if (x > sel_end_col && (y == sel_end_row || rect_selection)) - return 0; - return 1; -} - -static Bit8u sel_attr(Bit8u a) +#define SEL_ACTIVE(w) (visible_selection && ((w) >= sel_start) && ((w) <= sel_end)) +static inline Bit8u sel_attr(Bit8u a) { /* adapted from Linux vgacon code */ if (vga.mode_type == TEXT_MONO) @@ -99,12 +84,12 @@ static Bit8u sel_attr(Bit8u a) return a; } -#define XATTR(w, x, y) (SEL_ACTIVE(x, y) ? sel_attr(ATTR(w)) : ATTR(w)) +#define XATTR(w) (SEL_ACTIVE(w) ? sel_attr(ATTR(w)) : ATTR(w)) #else -#define XATTR(w, x, y) (ATTR(w)) +#define XATTR(w) (ATTR(w)) #endif -#define XREAD_WORD(w, x, y) ((XATTR(w, x, y)<<8)|CHAR(w)) +#define XREAD_WORD(w) ((XATTR(w)<<8)|CHAR(w)) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -231,8 +216,8 @@ static void restore_cell(unsigned cursor_location) oldsp = prev_screen + cursor_location / 2; c = CHAR(sp); - *oldsp = XREAD_WORD(sp, x, y); - draw_string(x, y, &c, 1, XATTR(sp, x, y)); + *oldsp = XREAD_WORD(sp); + draw_string(x, y, &c, 1, XATTR(sp)); } /* @@ -241,7 +226,7 @@ static void restore_cell(unsigned cursor_location) */ static void draw_cursor(void) { - int x, y, i, cs, ce; + int x, y, i; if (check_cursor_location (memoffs_to_location(vga.crtc.cursor_location), &x, &y) @@ -250,14 +235,9 @@ static void draw_cursor(void) for (i = 0; i < num_texts; i++) { if (Text[i]->flags & TEXTF_DISABLED) continue; - cs = CURSOR_START(vga.crtc.cursor_shape) & 0x1f; - ce = CURSOR_END(vga.crtc.cursor_shape) & 0x1f; - if (cs > ce) - ce = (CURSOR_END(vga.crtc.cursor_shape) + vga.char_height) & 0x1f; - if (cs > ce) - return; - Text[i]->Draw_cursor(Text[i]->opaque, x, y, XATTR(cursor, x, y), - cs, ce, have_focus); + Text[i]->Draw_cursor(Text[i]->opaque, x, y, XATTR(cursor), + CURSOR_START(vga.crtc.cursor_shape), + CURSOR_END(vga.crtc.cursor_shape), have_focus); } } } @@ -332,7 +312,6 @@ struct bitmap_desc draw_bitmap_line(int x, int y, float ul, int linelen, return BMP(text_canvas, vga.width, vga.height, vga.width); } -#if 0 void reset_redraw_text_screen(void) { unsigned compare; @@ -354,7 +333,6 @@ void reset_redraw_text_screen(void) memcpy(&prev_screen[compare / 2], vga.mem.base, vga.scan_len * vga.text_height - compare); } -#endif static void refresh_text_pal(DAC_entry * col, int index, void *udata) { @@ -415,7 +393,7 @@ static void text_redraw_text_screen(void) refresh_text_palette(); if (vga.text_width > MAX_COLUMNS) { - x_msg("X_redraw_text_screen: unable to handle %d columns\n", + x_msg("X_redraw_text_screen: unable to handle %d colums\n", vga.text_width); return; } @@ -432,31 +410,24 @@ static void text_redraw_text_screen(void) do { /* scan in a string of chars of the same attribute */ bp = charbuff; start_x = x; - attr = XATTR(sp, x, y); + attr = XATTR(sp); do { /* conversion of string to X */ - *oldsp++ = XREAD_WORD(sp, x, y); + *oldsp++ = XREAD_WORD(sp); *bp++ = CHAR(sp); sp++; x++; - } while (XATTR(sp, x, y) == attr && x < vga.text_width); + } while (XATTR(sp) == attr && x < vga.text_width); *bp = '\0'; draw_string(start_x, y, charbuff, x - start_x, attr); } while (x < vga.text_width); oldsp += vga.scan_len / 2 - vga.text_width; } - - memcpy(prev_font, vga.mem.base + 0x20000, 256 * 32); } void dirty_text_screen(void) { - memset(prev_screen, 0xff, MAX_COLUMNS * MAX_LINES * sizeof(uint16_t)); -} - -static int text_font_changed(void) -{ - return memcmp(prev_font, vga.mem.base + 0x20000, 256 * 32); + memset(prev_screen, 0xff, MAX_COLUMNS * MAX_LINES * sizeof(ushort)); } int text_is_dirty(void) @@ -468,19 +439,16 @@ int text_is_dirty(void) memoffs_to_location(vga.crtc.cursor_location) != prev_cursor_location) return 1; - - if (text_font_changed()) - return 1; - sp = vga.mem.base + location_to_memoffs(0); + if (vga.text_height <= vga.line_compare) return memcmp(prev_screen, sp, - vga.text_width * vga.text_height * sizeof(uint16_t)); + vga.text_width * vga.text_height * sizeof(ushort)); compare = vga.line_compare * vga.scan_len; ret = memcmp(prev_screen, sp, compare); if (ret == 0) - ret = memcmp(&prev_screen[compare / sizeof(uint16_t)], vga.mem.base, + ret = memcmp(&prev_screen[compare / sizeof(ushort)], vga.mem.base, vga.scan_len * vga.text_height - compare); return ret; } @@ -510,8 +478,8 @@ static void update_cursor(void) return; blink_count = config.X_blinkrate; - if (blink_count) - blink_state ^= 1; + blink_state = !blink_state; + if (blink_state) draw_cursor(); @@ -523,7 +491,7 @@ static void update_cursor(void) * Blink the cursor. Called from SIGALRM handler. * Do nothing in graphics modes. */ -void blink_cursor(void) +void blink_cursor() { if (!have_focus) return; @@ -600,7 +568,7 @@ struct bitmap_desc convert_bitmap_string(int x, int y, const char *text, len = vga.width / vga.char_width - x; } - /* would use vgaemu_xy2ofs, but not usable for US, NOW! */ + /* would use vgaemu_xy2ofs, but not useable for US, NOW! */ srcp = vga.width * y * height; srcp += x * vga.char_width; @@ -699,7 +667,7 @@ void update_text_screen(void) do { /* find a non-matching character position */ start_x = x; - while (XREAD_WORD(sp, x, y) == *oldsp) { + while (XREAD_WORD(sp) == *oldsp) { sp++; oldsp++; x++; @@ -716,21 +684,21 @@ void update_text_screen(void) start_x = x; #if CONFIG_SELECTION /* don't show selection if the DOS app changed it */ - if (SEL_ACTIVE(x, y) && *sp != *oldsp) + if (SEL_ACTIVE(sp) && *sp != *oldsp) visible_selection = FALSE; #endif - attr = XATTR(sp, x, y); + attr = XATTR(sp); unchanged = 0; /* counter for unchanged chars */ while (1) { *bp++ = CHAR(sp); - *oldsp++ = XREAD_WORD(sp, x, y); + *oldsp++ = XREAD_WORD(sp); sp++; x++; - if ((XATTR(sp, x, y) != attr) || (x == vga.text_width)) + if ((XATTR(sp) != attr) || (x == vga.text_width)) break; - if (XREAD_WORD(sp, x, y) == *oldsp) { + if (XREAD_WORD(sp) == *oldsp) { if (unchanged > MAX_UNCHANGED) break; unchanged++; @@ -738,7 +706,7 @@ void update_text_screen(void) unchanged = 0; #if CONFIG_SELECTION /* don't show selection if the DOS app changed it */ - if (SEL_ACTIVE(x, y) && *sp != *oldsp) + if (SEL_ACTIVE(sp) && *sp != *oldsp) visible_selection = FALSE; #endif } @@ -767,11 +735,9 @@ void update_text_screen(void) redraw_cursor(); } } - - memcpy(prev_font, vga.mem.base + 0x20000, 256 * 32); } -void text_lose_focus(void) +void text_lose_focus() { if (!have_focus) return; @@ -781,7 +747,7 @@ void text_lose_focus(void) need_redraw_cursor = TRUE; } -void text_gain_focus(void) +void text_gain_focus() { if (have_focus) return; @@ -797,11 +763,33 @@ void text_gain_focus(void) static void calculate_selection(void) { unsigned start, end; + int co = vga.scan_len / 2; - start = location_to_memoffs(sel_start_row * vga.scan_len + + if ((sel_end_row < sel_start_row) || + ((sel_end_row == sel_start_row) && (sel_end_col < sel_start_col))) { + if (sel_start_col == 0) { + assert(sel_start_row && sel_end_row < sel_start_row); + sel_start_row--; + sel_start_col = co; + } + start = + location_to_memoffs(sel_end_row * vga.scan_len + sel_end_col * 2); + end = + location_to_memoffs(sel_start_row * vga.scan_len + + (sel_start_col - 1) * 2); + } else { + if (sel_end_col == 0) { + assert(sel_end_row && sel_end_row > sel_start_row); + sel_end_row--; + sel_end_col = co; + } + start = + location_to_memoffs(sel_start_row * vga.scan_len + sel_start_col * 2); - end = location_to_memoffs(sel_end_row * vga.scan_len + - sel_end_col * 2); + end = + location_to_memoffs(sel_end_row * vga.scan_len + + (sel_end_col - 1) * 2); + } sel_start = (Bit16u *) (vga.mem.base + start); sel_end = (Bit16u *) (vga.mem.base + end); } @@ -835,7 +823,7 @@ void clear_selection_data(void) * Check if we should clear selection. * Clear if cursor is in or before selected area. */ -void clear_if_in_selection(void) +void clear_if_in_selection() { unsigned cursor_row, cursor_col; @@ -863,11 +851,10 @@ void clear_if_in_selection(void) /* * Start the selection process (mouse button 1 pressed). */ -void start_selection(int col, int row, int rect) +void start_selection(int col, int row) { - sel_start_col = sel_end_col = sel_col = col; - sel_start_row = sel_end_row = sel_row = row; - rect_selection = rect; + sel_start_col = sel_end_col = col; + sel_start_row = sel_end_row = row; doing_selection = visible_selection = TRUE; X_printf("X:start selection , start %d %d, end %d %d\n", sel_start_col, sel_start_row, sel_end_col, sel_end_row); @@ -879,30 +866,12 @@ void start_selection(int col, int row, int rect) */ void extend_selection(int col, int row) { - int dstart = 0; if (!doing_selection) return; - if (row < sel_row) { - sel_start_row = row; - sel_end_row = sel_row; - } else { - sel_end_row = row; - sel_start_row = sel_row; - } - if (rect_selection) { - if (col < sel_col) - dstart++; - } else { - if (row < sel_row || (row == sel_row && col < sel_col)) - dstart++; - } - if (dstart) { - sel_start_col = col; - sel_end_col = sel_col; - } else { - sel_end_col = col; - sel_start_col = sel_col; - } + if ((sel_end_col == col) && (sel_end_row == row)) + return; + sel_end_col = col; + sel_end_row = row; X_printf("X:extend selection , start %d %d, end %d %d\n", sel_start_col, sel_start_row, sel_end_col, sel_end_row); calculate_selection(); // make selection visible @@ -918,12 +887,23 @@ void start_extend_selection(int col, int row) if (!visible_selection) return; doing_selection = TRUE; - extend_selection(col, row); + if ((sel_end_col == col) && (sel_end_row == row)) + return; + if (row < sel_start_row || (row == sel_start_row && col < sel_start_col)) { + sel_start_col = col; + sel_start_row = row; + } else { + sel_end_col = col; + sel_end_row = row; + } + X_printf("X:extend selection , start %d %d, end %d %d\n", + sel_start_col, sel_start_row, sel_end_col, sel_end_row); + calculate_selection(); // make selection visible } static void save_selection(int col1, int row1, int col2, int row2) { - int row, col, co; + int row, col, line_start_col, line_end_col, co; u_char *sel_text_dos, *sel_text_ptr; t_unicode *sel_text_unicode, *prev_sel_text_unicode; size_t sel_space, sel_text_bytes; @@ -943,18 +923,17 @@ static void save_selection(int col1, int row1, int col2, int row2) sel_text_unicode = sel_text = malloc(sel_space * sizeof(t_unicode)); /* Copy the text data. */ - for (row = row1; row <= row2; row++) { + for (row = row1; (row <= row2); row++) { prev_sel_text_unicode = sel_text_unicode; + line_start_col = ((row == row1) ? col1 : 0); + line_end_col = ((row == row2) ? col2 : vga.text_width - 1); p = sel_text_ptr = sel_text_dos; - sel_text_bytes = 0; - for (col = 0; col < vga.text_width; col++) { - if (!SEL_ACTIVE(col, row)) - continue; + for (col = line_start_col; (col <= line_end_col); col++) { *p++ = CHAR(screen_adr + location_to_memoffs(2 * (row * co + col)) / 2); - sel_text_bytes++; } + sel_text_bytes = line_end_col - line_start_col + 1; while (sel_text_bytes) { t_unicode symbol; size_t result; @@ -982,10 +961,8 @@ static void save_selection(int col1, int row1, int col2, int row2) error("BUG: pasting OOM\n"); leavedos(91); } - if (row < row2) { - *sel_text_unicode++ = '\n'; - sel_space--; - } + *sel_text_unicode++ = '\n'; + sel_space--; } } free(sel_text_dos); @@ -1031,7 +1008,7 @@ static void save_selection_data(void) /* * End of selection (button released). */ -t_unicode *end_selection(void) +t_unicode *end_selection() { if (!doing_selection) return NULL; diff --git a/src/base/video/video.c b/src/base/video/video.c index 37ad024..b5b4e1e 100644 --- a/src/base/video/video.c +++ b/src/base/video/video.c @@ -66,7 +66,7 @@ static int no_real_terminal(void) if ( term == NULL || !strcmp(term,"dumb") /* most cron's have this */ || !strcmp(term,"none") /* ... some have this */ - || !strcmp(term,"dosemu-none") /* ... when called recursively */ + || !strcmp(term,"dosemu-none") /* ... when called recursivly */ ) { /* * We assume we are running without a terminal (e.g. in a cronjob). @@ -105,7 +105,7 @@ static int using_kms(void) if (!on_console()) return 0; // not using KMS under X if (!pcibios_init()) return 0; - pcirec = pcibios_find_primary_vga(); + pcirec = pcibios_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0); if (!pcirec) return 0; bus = pcirec->bdf >> 8; @@ -193,11 +193,10 @@ static void init_video_none(void) */ static int video_init(void) { - if (!config.term && config.console_video != 1 && - config.cardtype != CARD_NONE && using_kms()) + if (!config.term && config.cardtype != CARD_NONE && using_kms()) { config.vga = config.console_video = config.mapped_bios = config.pci_video = 0; -#ifdef SDL_SUPPORT +#if SDL_SUPPORT warn("KMS detected: using SDL mode.\n"); load_plugin("sdl"); config.sdl = 1; @@ -212,7 +211,7 @@ static int video_init(void) error("failed to load sdl plugin\n"); } #else -#ifdef USE_SLANG +#if USE_SLANG warn("KMS detected: using terminal mode.\n"); config.term = 1; #else @@ -277,14 +276,6 @@ done: if (config.term) { config.X = 0; config.sdl = 0; -#ifndef USE_SLANG - if (config.dumb_video) { - config.term = 0; - } else { - error("terminal support not compiled in\n"); - leavedos(2); - } -#endif } return 0; @@ -355,13 +346,7 @@ static void reserve_video_memory(void) if (config.umb_b0 && !config.dualmon) { if (!config.umb_a0) do_reserve_vmem(GRAPH_BASE, GRAPH_SIZE); - if (!config.umb_b8) - do_reserve_vmem(VGA_PHYS_TEXT_BASE, VGA_TEXT_SIZE); - } else if (config.umb_b8) { - if (!config.umb_a0) - do_reserve_vmem(GRAPH_BASE, GRAPH_SIZE); - if (!config.umb_b0) - do_reserve_vmem(MDA_PHYS_TEXT_BASE, VGA_TEXT_SIZE); + do_reserve_vmem(VGA_PHYS_TEXT_BASE, VGA_TEXT_SIZE); } else { if (!config.umb_a0) do_reserve_vmem(VMEM_BASE, VMEM_SIZE); @@ -382,13 +367,9 @@ gettermcap(int i, int *co, int *li) } if (*co > MAX_COLUMNS || *li > MAX_LINES) { - error("Screen size is too large: %dx%d, max is %dx%d, ", + error("Screen size is too large: %dx%d, max is %dx%d\n", *co, *li, MAX_COLUMNS, MAX_LINES); - if (*li > MAX_LINES) - *li = MAX_LINES; - if (*co > MAX_COLUMNS) - *co = MAX_COLUMNS; - error("@Using %dx%d\n", *co, *li); + leavedos(0x63); } if (*li == 0 || *co == 0) { @@ -461,13 +442,6 @@ void video_post_init(void) } } - /* init vgaemu & render before initing video subsystem */ - if (!config.vga) { - vga_emu_pre_init(); - if (!config.dumb_video) - render_init(); - } - if (Video && Video->init) { c_printf("VID: initializing video %s\n", Video->name); err = Video->init(); @@ -519,6 +493,11 @@ void video_post_init(void) /* leavedos does not exit immediately. */ return; } + + if (!config.vga) { + vga_emu_pre_init(); + render_init(); + } } void video_late_init(void) diff --git a/src/bindist/bat/dosrc.d/3uhook.bat b/src/bindist/bat/dosrc.d/3uhook.bat deleted file mode 100644 index 159220d..0000000 --- a/src/bindist/bat/dosrc.d/3uhook.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -if exist %USERDRV%:\userhook.bat call %USERDRV%:\userhook.bat diff --git a/src/bindist/bat/dosrc.d/7mouse.bat b/src/bindist/bat/dosrc.d/7mouse.bat new file mode 100644 index 0000000..8b6fe5b --- /dev/null +++ b/src/bindist/bat/dosrc.d/7mouse.bat @@ -0,0 +1,2 @@ +@echo off +emumouse c 1 diff --git a/src/bindist/bat/exechlp.bat b/src/bindist/bat/exechlp.bat index 43e8268..8ea310f 100644 --- a/src/bindist/bat/exechlp.bat +++ b/src/bindist/bat/exechlp.bat @@ -1,14 +1,11 @@ @echo off system %1 %2 %3 +if "%DOSEMU_SYS_CMD%" == "" goto done if not "%DOSEMU_SYS_DRV%" == "" %DOSEMU_SYS_DRV%: if ERRORLEVEL 1 exitemu 1 if not "%DOSEMU_SYS_DIR%" == "" cd %DOSEMU_SYS_DIR% if ERRORLEVEL 1 exitemu 1 -if "%DOSEMU_SYS_CMD%" == "exit" goto cont -if "%DOSEMU_SYS_CMD%" == "" goto done -call %DOSEMU_SYS_CMD% -set SHELL_LOADHIGH_DEFAULT= -:cont +%COMSPEC% /E:1024 /C %DOSEMU_SYS_CMD% if "%DOSEMU_EXIT%" == "1" exitemu %ERRORLEVEL% C: :done diff --git a/src/bindist/fdautoem.bat b/src/bindist/fdautoem.bat index 30fe101..4d9aad2 100644 --- a/src/bindist/fdautoem.bat +++ b/src/bindist/fdautoem.bat @@ -6,9 +6,7 @@ if exist f:\gnu\nul path %PATH%;f:\bin;f:\gnu if exist c:\bin\nul path %PATH%;c:\bin set HELPPATH=f:\help if exist c:\help\nul set HELPPATH=c:\help -if exist c:\tmp\nul goto noswapdrv if exist e:\tmp\nul call swapdrv.bat c: e: -:noswapdrv set TEMP=c:\tmp if not exist %TEMP%\nul mkdir %TEMP% emusound -e diff --git a/src/bindist/fdppauto.bat b/src/bindist/fdppauto.bat index 0423453..3d7ef92 100644 --- a/src/bindist/fdppauto.bat +++ b/src/bindist/fdppauto.bat @@ -4,10 +4,9 @@ path %DOSEMUDRV%:\dosemu if not "%SHELLDRV%" == "" path %PATH%;%SHELLDRV%:\ if not "%FREEDOSDRV%" == "" path %PATH%;%FREEDOSDRV%:\bin;%FREEDOSDRV%:\gnu if not "%USERDRV%" == "" set TEMP=%USERDRV%:\tmp -rem first run external plugins. -E commands may depend on them. +for %%b in (%DOSEMUDRV%:\dosemu\dosrc.d\*.bat) do call %%b if "%XBATDRV%" == "" goto noxbat path %PATH%;%XBATDRV%:\ for %%b in (%XBATDRV%:\dosrc.d\*.bat) do call %%b :noxbat -rem run dosemu2 plugins, including vars and -E commands. -for %%b in (%DOSEMUDRV%:\dosemu\dosrc.d\*.bat) do call %%b +if exist %USERDRV%:\userhook.bat call %USERDRV%:\userhook.bat diff --git a/src/bindist/fdppconf.sys b/src/bindist/fdppconf.sys index 5418185..322a3cd 100644 --- a/src/bindist/fdppconf.sys +++ b/src/bindist/fdppconf.sys @@ -1,20 +1,15 @@ rem config.sys for DOSEMU2 + FDPP SWITCHES=#0 COUNTRY=#1 -; early hook for external himem etc -CHAIN=@globhook.sys -DOS=UMB +CHAIN=@userhook.sys +DOS=UMB,HIGH dosdata=umb -fileshigh=128 lastdrive=Z int0divz=off device=dosemu\umb.sys -; hook for EMM driver -CHAIN=@emmhook.sys devicehigh=dosemu\ems.sys rem emufs.sys /all replaces emufs.com devicehigh=dosemu\emufs.sys /all devicehigh=dosemu\cdrom.sys set SHELL_ALLOW_EXIT=1 -shellhigh=#2 /M2 -CHAIN=@%0\userhook.sys +shellhigh=command.com /e:384 /p /k %FDPP_AUTOEXEC% diff --git a/src/doc/HOWTO/tweaks.sgml b/src/doc/HOWTO/tweaks.sgml index 9fca270..d698370 100644 --- a/src/doc/HOWTO/tweaks.sgml +++ b/src/doc/HOWTO/tweaks.sgml @@ -116,24 +116,6 @@ Solution: set $_umb_f0 = (off) in your dosemu.conf or .dosemurc. - -see here for details - - - - - -Sound is crackling. - - -Solution: set - -$_dos_up = (off) - -in your dosemu.conf or .dosemurc. -The only "explanation" we can provide, is a conspiracy theory that -prehistoric is trying to slander third-party DOSes that put LoL/SDA -to UMB. @@ -311,7 +293,6 @@ Apply the following patch to vmp.com: see here for details - @@ -347,65 +328,4 @@ these drive letters are occupied. Solution is to copy the game to C:. - -Tetris Classic, Super Tetris - - -Game is too slow. - - -Solution: set - -$_timer_tweaks = (on) - - - - - - -Street Fighter 2 - - -Game crashes on intro screen. - - -Solution: set - -$_timer_tweaks = (on) - - - - - - -Game Wizard (GW) - - -Hangs on start. - - -Solution: set - -$_dos_up = (off) - - - - - - -Seven Cities of Gold - - -Game hangs on start-up - - -Apply the following patch to 7cities.exe: - -000049DE: 72 90 -000049DF: D8 90 - - - - - diff --git a/src/doc/README/Makefile b/src/doc/README/Makefile index 257522f..477d659 100644 --- a/src/doc/README/Makefile +++ b/src/doc/README/Makefile @@ -14,11 +14,11 @@ TECHSECTIONS = config-tech port-io vif newnewkbd newkbd \ HOGTHRESHOLD priv timing pentium DANG-tech mkfatimage16 doc sound-tech \ dma pic dosdebug serial recover net cpuemu mfsnls -all: $(HTML) +all: $(HTML) -txt: $(TXT) +txt: $(TXT) -html: $(HTML) +html: $(HTML) %.txt: %.sgml # sgml2txt 2>/dev/null $< diff --git a/src/doc/README/Windows b/src/doc/README/Windows index 4bd9017..7842011 100644 --- a/src/doc/README/Windows +++ b/src/doc/README/Windows @@ -13,12 +13,13 @@ a few caveats however, and if you have some problems, read on. In Windows, the mouse cursor is not always in sync with the native X mouse cursor. This problem can be easily avoided by enabling mouse grab. -There also exist an - -alternative mouse driver - -specially written to work in ungrabbed mode under many emulators or -on a real machine. +There also exist an alternative mouse driver specially written to +work in ungrabbed mode: + +https://github.com/stsp/win31-mouse-driver/tree/master/out +. +This driver is not limited to use with dosemu2: it can be used with +any other emulator and under bare-metal machine. diff --git a/src/doc/tools/doSgmlTools.pl b/src/doc/tools/doSgmlTools.pl index d6651aa..2fdc65c 100755 --- a/src/doc/tools/doSgmlTools.pl +++ b/src/doc/tools/doSgmlTools.pl @@ -130,7 +130,7 @@ sub getSoftwareVersions { print "Found Jade version $1\n"; } } - + # Check for Lynx $result = `lynx -version`; diff --git a/src/dosemu b/src/dosemu index bc50d9a..fb76d94 100644 --- a/src/dosemu +++ b/src/dosemu @@ -5,11 +5,10 @@ get_binary() { echo "$BINARY does not exist" exit 1 fi - if [ "$BINDIR" = "$(realpath -q $LOCAL_BUILD_PATH/$LOCAL_BIN_DIR)" ]; then - [ -h ~/.fonts/dosemu2 ] || (mkdir -p ~/.fonts && ln -sf "$LOCAL_BUILD_PATH/etc/ttf" ~/.fonts/dosemu2) - OPTS="$OPTS --Fcmddir $LOCAL_BUILD_PATH/commands \ - --Flibdir $LOCAL_BUILD_PATH/etc \ - --Fplugindir $BINDIR \ + if [ "$BINDIR" == "$LOCAL_BUILD_PATH/$LOCAL_BIN_DIR" ]; then + OPTS="$OPTS --Fcmddir "$LOCAL_BUILD_PATH/commands" \ + --Flibdir "$LOCAL_BUILD_PATH/etc" \ + --Fplugindir "$BINDIR" \ " fi } @@ -25,7 +24,7 @@ USAGE: THISDIR="$PWD" ARG0="$0" -unset STRING_I USE_SUDO OPTS +unset STRING_I USE_SUDO INPUT OPTS mkdir -p ~/.dosemu @@ -33,7 +32,7 @@ SUFFIX="" while [ $# -gt 0 ] ; do case "$1" in -dumb) - OPTS="$OPTS -td -ks" + OPTS="$OPTS -td -kt" exec 4>&2 2>~/.dosemu/stderr.log.$BASHPID shift ;; @@ -62,21 +61,30 @@ while [ $# -gt 0 ] ; do echo "$1 is not installed" exit 1 fi - OPTS="$OPTS --Flocal_dir %I/install/$1" - LOG_FILE=~/.dosemu/boot.$1.log + OPTS="$OPTS --Fdrive_c %I/install/$1/drive_c --Fimagedir %I/install/$1" + if [ -f ~/.dosemu/install/$1/.dosemurc ]; then + OPTS="$OPTS -f %I/install/$1/.dosemurc" + else + OPTS="$OPTS -n" + fi + LOG_FILE=~/.dosemu/install/$1/boot.log shift ;; -quiet) # Note: this switches to dumb mode rather than to work with # -dumb because -dumb expects to redirect only errors to the # log file, not the whole dosemu output of stderr. - OPTS="$OPTS -tde -ks" + OPTS="$OPTS -tde -kt" exec 2>/dev/null shift ;; -input) - OPTS="$OPTS -i `echo \"$2\" | sed 's/ /\\\\_/g'`" - shift 2 + INPUT=1 + if [ -n "$2" -a -n "${2%%-*}" ]; then + STRING_I="$STRING_I keystroke "'"'"$2"'"' + shift + fi + shift ;; -license) printf "$license" @@ -108,7 +116,7 @@ while [ $# -gt 0 ] ; do SUFFIX="$SUFFIX \"$1\"" shift ;; - -t | -t[a-z] | -t[a-z][a-z] | -t[a-z][a-z][a-z]) + -t) exec 4>&2 2>~/.dosemu/stderr.log.$BASHPID SUFFIX="$SUFFIX \"$1\"" shift @@ -122,13 +130,6 @@ while [ $# -gt 0 ] ; do DBG="gdb --args" shift ;; - -perf) - DBG="perf record --call-graph dwarf --" - shift - ;; - --) - break - ;; *) # this should avoid avoid resulting substitution odds SUFFIX="$SUFFIX \"$1\"" @@ -136,7 +137,6 @@ while [ $# -gt 0 ] ; do ;; esac done -SUFFIX="$SUFFIX $*" [ -z "$DOSEMU_QUIET" ] || OPTS="$OPTS -q" [ -z "$DOSEMU_LOG_FILE" ] || LOG_FILE="$DOSEMU_LOG_FILE" @@ -145,13 +145,12 @@ SUFFIX="$SUFFIX $*" MAX_LOGS=3 if [ -f "$LOG_FILE" ]; then - NL="`ls -1 "$LOG_FILE".[0-9] 2> /dev/null | tail -n 1`" + NL="`ls "$LOG_FILE".[0-9] 2> /dev/null | tail -n 1`" NL="${NL##*.}" if [ -z "$NL" ]; then NL="1" elif [ "$NL" -ge "$MAX_LOGS" ]; then - NL="`ls -t -1 "$LOG_FILE".[0-9] 2> /dev/null | tail -n 1`" - NL="${NL##*.}" + NL="1" else NL="`expr $NL + 1`" fi @@ -161,50 +160,45 @@ fi get_binary "$0" if [ "`id -ur`" -eq 0 ]; then - if [ -z "$USE_SUDO" ]; then - echo "Running dosemu2 with root privs is recommended with: $(basename $0) -s" - else - # we still need to pass -s so just don't use sudo - unset USE_SUDO - fi - if [ -n "$SUDO_USER" -a -z "$SUDO_HOME" ]; then - export SUDO_HOME=`getent passwd "$SUDO_USER" | cut -d: -f6` - fi + echo "Running dosemu2 as root is highly discouraged" + exit 1 fi SUDO="" +# set sudo_uid/sudo_gid so that somebody who does "sudo dosemu" +# really gets root +if [ -n "$SUDO_UID" ] ; then + SUDO_UID=0 +fi +if [ -n "$SUDO_GID" ] ; then + SUDO_GID=0 +fi if [ -n "$USE_SUDO" ] ; then SUDO=sudo - # preserve env, most importantly HOME - SUDOOPTS="-E --preserve-env=HOME" - # sudo doesn't set SUDO_HOME but maybe it will - use another var - export DOSEMU_SUDO_HOME="$HOME" + SUDOOPTS=-E fi # for address sanitizer export ASAN_OPTIONS='handle_segv=0:abort_on_error=1:detect_leaks=0' -export LSAN_OPTIONS='report_objects=1:fast_unwind_on_malloc=0:exitcode=0' -export UBSAN_OPTIONS='print_stacktrace=1' - -# this is needed to show dosemu icon -export SDL_VIDEO_X11_WMCLASS=dosemu eval "set -- $SUFFIX" COMMAND="$SUDO $SUDOOPTS $DBG $BINARY -o $LOG_FILE $OPTS" +DOSEMU_INVOKED_NAME="$0" +export DOSEMU_INVOKED_NAME if [ -n "$STRING_I" ] ; then COMMAND="$COMMAND -I '$STRING_I'" fi exec 3>&1 # in a non-bash case, $BASHPID won't work and we fail the cleanup - no problem -DPID="$(echo "$BASHPID"; exec 1<&3; exec $COMMAND -L "Command line: `echo $COMMAND $* | tr -s ' '`" "$@")" +DPID="$(echo "$BASHPID"; exec 1<&3; exec $COMMAND -L "Command line: `echo $COMMAND | tr -s ' '`" "$@")" EC=$? exec 3>&- if [ -f ~/.dosemu/stderr.log.$BASHPID ]; then cat ~/.dosemu/stderr.log.$BASHPID >&4 rm -f ~/.dosemu/stderr.log.$BASHPID fi -RUNDIR="/var/run/user/$UID/dosemu2" +RUNDIR="$HOME/.dosemu/run" STALE="`ls "$RUNDIR"/*."$DPID" 2>/dev/null`" if [ -n "$STALE" ]; then echo "removing stale files:" @@ -212,12 +206,7 @@ if [ -n "$STALE" ]; then rm -f $STALE stty sane kbd_mode -a 2>/dev/null - # disable xterm mouse tracking - printf "\033[?1006l\033[?1003l\033[?1002l\033[?1000l\033[?9l" - # disable xterm cursor keys - printf "\033[?1l" fi -exec 4>&- if [ $EC -gt 128 ]; then SIG=`expr $EC - 128` @@ -230,10 +219,6 @@ if [ -f "$LOG_FILE" -a -x "/usr/bin/dpkg-query" ]; then dpkg-query -W dosemu2 >>$LOG_FILE 2>/dev/null dpkg-query --show --showformat='fdpp: ${db:Status-Status}\n' fdpp >>$LOG_FILE 2>/dev/null dpkg-query -W fdpp >>$LOG_FILE 2>/dev/null - dpkg-query --show --showformat='dj64: ${db:Status-Status}\n' dj64 >>$LOG_FILE 2>/dev/null - dpkg-query -W dj64 >>$LOG_FILE 2>/dev/null - dpkg-query --show --showformat='comcom64: ${db:Status-Status}\n' comcom64 >>$LOG_FILE 2>/dev/null - dpkg-query -W comcom64 >>$LOG_FILE 2>/dev/null fi exit $EC diff --git a/src/dosemu.systemwide b/src/dosemu.systemwide index 28f0c5f..4cab9aa 100644 --- a/src/dosemu.systemwide +++ b/src/dosemu.systemwide @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#! /bin/bash # # dosemu2 - virtual machine for running DOS # Copyright (C) 2014-2020, stsp & dosemu2 contributors diff --git a/src/dosext/builtins/Makefile b/src/dosext/builtins/Makefile index 7718c80..21c490f 100644 --- a/src/dosext/builtins/Makefile +++ b/src/dosext/builtins/Makefile @@ -7,8 +7,8 @@ top_builddir=../../.. include $(top_builddir)/Makefile.conf -CFILES=commands.c lredir.c xmode.c emumouse.c emuconf.c msetenv.c \ - unix.c system.c builtins.c blaster.c fossil.c +CFILES=commands.c lredir.c xmode.c emumouse.c dosdbg.c msetenv.c \ + unix.c system.c builtins.c blaster.c all: lib diff --git a/src/dosext/builtins/blaster.c b/src/dosext/builtins/blaster.c index be4d86b..4e5f791 100644 --- a/src/dosext/builtins/blaster.c +++ b/src/dosext/builtins/blaster.c @@ -25,7 +25,7 @@ #include "blaster.h" -#include "utilities.h" +#include "emu.h" #include "sound.h" #include "sound/midi.h" @@ -68,7 +68,7 @@ static void blaster_setenv(void) } snprintf(blaster, sizeof(blaster), "SYNTH:%d MAP:%c MODE:%d", - SYNTH_MPU401, MAP_EXTENDED, /*get_mode_num()*/ 0); + SYNTH_MPU401, MAP_EXTENDED, get_mode_num()); com_printf("MIDI=%s\n", blaster); if (msetenv("MIDI", blaster) == -1) { @@ -83,14 +83,10 @@ static void show_settings(void) if (config.sb_hdma) { com_printf(", DMA16=%d", config.sb_hdma); } - com_printf("\n"); - com_printf("MPU-401 at 0x%x-0x%x, IRQ=%d\n", + + com_printf(". MPU-401 at 0x%x-0x%x, IRQ=%d.\n", config.mpu401_base, config.mpu401_base+1, - config.mpu401_irq); - com_printf("\n"); - com_printf("MT32 MPU-401 at 0x%x-0x%x, IRQ=%d\n", - config.mpu401_base_mt32, config.mpu401_base_mt32+1, - config.mpu401_irq_mt32); + get_mpu401_irq_num()); com_printf("MIDI synth mode is %s\n", smode[get_mode_num()]); } @@ -124,7 +120,7 @@ int emusound_main(int argc, char **argv) return 0; } - GETOPT_RESET(); + optind = 0; while ((c = getopt(argc, argv, "cehs:")) != -1) { switch (c) { case 'c': diff --git a/src/dosext/builtins/builtins.c b/src/dosext/builtins/builtins.c index 0b8b12d..6f5daa1 100644 --- a/src/dosext/builtins/builtins.c +++ b/src/dosext/builtins/builtins.c @@ -39,7 +39,6 @@ #include "redirect.h" #include "plugin_config.h" #include "msetenv.h" -#include "system.h" #include "builtins.h" /* hope 2K is enough */ @@ -112,7 +111,7 @@ static int load_and_run_DOS_program(const char *command, const char *cmdline) BMEM(pa4)->fcb2 = MK_FARt(com_psp_seg(), offsetof(struct PSP, FCB2)); SREG(es) = DOSEMU_LMHEAP_SEG; LWORD(ebx) = DOSEMU_LMHEAP_OFFS_OF(BMEM(pa4)); - /* path of program to load */ + /* path of programm to load */ SREG(ds) = DOSEMU_LMHEAP_SEG; LWORD(edx) = DOSEMU_LMHEAP_OFFS_OF(BMEM(cmd)); @@ -510,7 +509,7 @@ int commands_plugin_inte6(void) if (p) *p = '\0'; } -// assert(psp->cmdline_len < sizeof(cmdbuf)); // len uint8_t, can't assert +// assert(psp->cmdline_len < sizeof(cmdbuf)); // len uint8_t, cant assert memcpy(cmdbuf, psp->cmdline, psp->cmdline_len); cmdbuf[psp->cmdline_len] = '\0'; if (pool_used >= MAX_NESTING) { @@ -556,5 +555,4 @@ int commands_plugin_inte6_set_retcode(void) void commands_plugin_inte6_reset(void) { pool_used = 0; - system_com_reset(); } diff --git a/src/dosext/builtins/commands.c b/src/dosext/builtins/commands.c index adee90b..ba3098f 100644 --- a/src/dosext/builtins/commands.c +++ b/src/dosext/builtins/commands.c @@ -38,9 +38,8 @@ #include "xmode.h" #include "unix.h" #include "system.h" -#include "emuconf.h" +#include "dosdbg.h" #include "blaster.h" -#include "fossil.h" /* ============= old .com ported ================= */ @@ -67,7 +66,7 @@ static int do_doshelper(int ax, int bx) break; case DOS_HELPER_GARROT_HELPER: /* Mouse garrot helper */ if (!bx) /* Wait sub-function requested */ - idle_enable(50, 0, "mouse_garrot"); + idle_enable(0, 50, 0, "mouse_garrot"); else /* Get Hogthreshold value sub-function */ ret = config.hogthreshold; break; @@ -112,7 +111,7 @@ static int emudpmi_main(int argc, char **argv) com_printf("+--------------------------+-----------+----+---------------------------------+\n\n"); } else { int c = 0; - GETOPT_RESET(); + optind = 0; while ((c = getopt(argc, argv, "m:p:n:t:")) != -1) { switch (c) { case 'm': @@ -164,7 +163,7 @@ static int emudpmi_main(int argc, char **argv) static int eject_main(int argc, char **argv) { do_doshelper(DOS_HELPER_CDROM_HELPER, 0xc00); /* unlock door */ - GETOPT_RESET(); + optind = 0; switch (getopt(argc, argv, "t")) { case 't': do_doshelper(DOS_HELPER_CDROM_HELPER, 0xe00); /* close tray */ @@ -268,57 +267,6 @@ static int emufs_main(int argc, char **argv) return ret; } -static int comredir_main(int argc, char **argv) -{ - struct REGPACK r = REGPACK_INIT; - int suppr = 0, flags = 0; - int c; - - GETOPT_RESET(); - while ((c = getopt(argc, argv, "hsf:")) != -1) { - switch (c) { - case 'h': - com_printf("comredir redirects console to com port\n"); - com_printf("usage: comredir [-s] [-f flags] []\n"); - com_printf("options:\n"); - com_printf("\t-s - suppress console output from DOS programs\n"); - com_printf("\t-f - communication flags (ORed value of the below):\n"); - com_printf("\t\t1 - suppress output (same as -s)\n"); - com_printf("\t\t2 - append NL to CR on output\n"); - com_printf("\t\t4 - prepend CR to NL on output\n"); - com_printf("\t\t8 - append NL to CR on input\n"); - com_printf("\t\t10h - prepend CR to NL on input\n"); - com_printf("\t-h - this help\n"); - return EXIT_SUCCESS; - case 's': - suppr++; - break; - case 'f': - flags = atoi(optarg); - break; - default: - com_printf("Unknown option\n"); - return EXIT_FAILURE; - } - } - if (argc - optind < 1) { - com_printf("usage: comredir []\n"); - return 1; - } - - r.r_ax = (DOS_HELPER_SERIAL_HELPER | (DOS_SUBHELPER_SERIAL_COMREDIR_INIT << 8)) & 0xffff; - r.r_bx = atoi(argv[optind]); - if (argc - optind > 1) - r.r_cx = atoi(argv[optind + 1]); - else - r.r_cx = r.r_bx; - if (suppr) - r.r_cx |= 1 << 8; - r.r_cx |= flags << 8; - com_intr(DOS_HELPER_INT, &r); - return 0; -} - CONSTRUCTOR(static void commands_plugin_init(void)) { register_com_program("EMUDPMI", emudpmi_main); @@ -334,6 +282,4 @@ CONSTRUCTOR(static void commands_plugin_init(void)) register_com_program("SYSTEM", system_main); register_com_program("EMUFS", emufs_main); register_com_program("EMUSOUND", emusound_main); - register_com_program("FOSSIL", fossil_main); - register_com_program("COMREDIR", comredir_main); } diff --git a/src/dosext/builtins/emuconf.c b/src/dosext/builtins/dosdbg.c similarity index 72% rename from src/dosext/builtins/emuconf.c rename to src/dosext/builtins/dosdbg.c index 6e66b9e..f860df0 100644 --- a/src/dosext/builtins/emuconf.c +++ b/src/dosext/builtins/dosdbg.c @@ -42,7 +42,12 @@ #include "doshelpers.h" #include "builtins.h" -#include "emuconf.h" +#include "dosdbg.h" + +#define printf com_printf +#define FP_OFF(x) DOSEMU_LMHEAP_OFFS_OF(x) +#define FP_SEG(x) DOSEMU_LMHEAP_SEG + typedef unsigned char uint8; typedef unsigned int uint16; @@ -54,19 +59,19 @@ typedef unsigned int uint16; static void Usage(void) { - com_printf("Usage: EMUCONF [string|HELP]\n"); - com_printf("If no string is specified, then EMUCONF will show the current debug settings.\n"); - com_printf(" If HELP is specified, then this screen is displayed. Otherwise \n"); - com_printf(" is parsed and used to change the current debug settings.\n\n"); - com_printf(" can contain letters, and the '+' and '-' characters.\n"); - com_printf(" Letters denote specific message classes, except for 'a' which is\n"); - com_printf(" shorthand for all classes\n\n"); - com_printf("Any classes following a '+', up until the end of string or a '-',\n"); - com_printf(" will be turned on. Likewise, any classes following a '-', to the\n"); - com_printf(" end of string or a '+' will be turned off.\n\n"); - com_printf("The character 'a' acts like a string of all possible debugging classes,\n"); - com_printf(" so \"-a\" turns all message off, and \"+a-RW\" would turn all messages\n"); - com_printf(" on except for disk Read and Write messages."); + printf("Usage: EMUCONF [string|HELP]\n"); + printf("If no string is specified, then EMUCONF will show the current debug settings.\n"); + printf(" If HELP is specified, then this screen is displayed. Otherwise \n"); + printf(" is parsed and used to change the current debug settings.\n\n"); + printf(" can contain letters, and the '+' and '-' characters.\n"); + printf(" Letters denote specific message classes, except for 'a' which is\n"); + printf(" shorthand for all classes\n\n"); + printf("Any classes following a '+', up until the end of string or a '-',\n"); + printf(" will be turned on. Likewise, any classes following a '-', to the\n"); + printf(" end of string or a '+' will be turned off.\n\n"); + printf("The character 'a' acts like a string of all possible debugging classes,\n"); + printf(" so \"-a\" turns all message off, and \"+a-RW\" would turn all messages\n"); + printf(" on except for disk Read and Write messages."); } static uint16 SetDebugString(char *debugStr) @@ -78,12 +83,12 @@ static void ShowDebugString(void) { char s[1024]; - com_printf("Current debug message class settings:\n"); + printf("Current debug message class settings:\n"); if (!GetDebugInfoHelper(s, sizeof s)) - com_printf("Warning: output truncated!\n"); + printf("Warning: output truncated!\n"); - com_printf("%s\n", s); + printf("%s\n", s); } static uint16 ParseAndSetDebugString(char *userDebugStr) @@ -135,7 +140,7 @@ static uint16 ParseAndSetDebugString(char *userDebugStr) ccode = SetDebugString(debugStr); if (ccode == 0) { - com_printf("Debug settings were adjusted...\n"); + printf("Debug settings were adjusted...\n"); ShowDebugString(); } diff --git a/src/dosext/builtins/emuconf.h b/src/dosext/builtins/dosdbg.h similarity index 100% rename from src/dosext/builtins/emuconf.h rename to src/dosext/builtins/dosdbg.h diff --git a/src/dosext/builtins/emumouse.c b/src/dosext/builtins/emumouse.c index 2010cbb..f53180a 100644 --- a/src/dosext/builtins/emumouse.c +++ b/src/dosext/builtins/emumouse.c @@ -35,6 +35,7 @@ #include "emumouse.h" +#define printf com_printf #define SETHIGH(x, v) HI_BYTE_d(x) = (v) #define SETLO_WORD(x, v) LO_WORD(x) = (v) #define SETLO_BYTE(x, v) LO_BYTE_d(x) = (v) @@ -43,26 +44,25 @@ /* Show help screen */ static int usage(void) { - com_printf("Usage: EMUMOUSE [option]\n"); - com_printf("Utility to control the internal mousedriver of DOSEMU\n\n"); - com_printf("Options:\n"); - com_printf(" r - Reset IRET.\n"); - com_printf(" i - Inquire current configuration.\n"); - com_printf(" 2 - Select 2 button mouse mode (Microsoft).\n"); - com_printf(" 3 - Select 3 button mouse mode (e.g. Mousesystems, PS2).\n"); - com_printf(" x value - Set horizontal speed.\n"); - com_printf(" y value - Set vertical speed.\n"); - com_printf(" s 1|0 - Ignore VESA modes (1 - ignore, 0 - accept).\n"); - com_printf(" c 1|0 - Enable/disable host's cursor.\n"); - com_printf(" l 1|0 - Lock/unlock host's cursor visibility.\n"); - com_printf(" u 1|0 - Enable/disable ungrab mode tweak.\n"); - com_printf(" h - Display this screen.\n"); - com_printf(" Mx val - Set minimum internal horizontal resolution.\n"); - com_printf(" My val - Set minimum internal vertical resolution.\n\n"); - com_printf("Valid range for \"value\" is from 1 (fastest) to 255 (slowest).\n\n"); - com_printf("Example: EMUMOUSE r a x 10 i\n"); - com_printf("reset, fixed speed setting, set horizontal speed to 10 and show current\n"); - com_printf(" configuration of the mouse\n\n"); + printf("Usage: EMUMOUSE [option]\n"); + printf("Utility to control the internal mousedriver of DOSEMU\n\n"); + printf("Options:\n"); + printf(" r - Reset IRET.\n"); + printf(" i - Inquire current configuration.\n"); + printf(" 2 - Select 2 button mouse mode (Microsoft).\n"); + printf(" 3 - Select 3 button mouse mode (e.g. Mousesystems, PS2).\n"); + printf(" x value - Set horizontal speed.\n"); + printf(" y value - Set vertical speed.\n"); + printf(" s 1|0 - Ignore VESA modes (1 - ignore, 0 - accept).\n"); + printf(" c 1|0 - Enable/disable host's cursor.\n"); + printf(" l 1|0 - Lock/unlock host's cursor visibility.\n"); + printf(" h - Display this screen.\n"); + printf(" Mx val - Set minimum internal horizontal resolution.\n"); + printf(" My val - Set minimum internal vertical resolution.\n\n"); + printf("Valid range for \"value\" is from 1 (fastest) to 255 (slowest).\n\n"); + printf("Example: EMUMOUSE r a x 10 i\n"); + printf("reset, fixed speed setting, set horizontal speed to 10 and show current\n"); + printf(" configuraton of the mouse\n\n"); return 0; } @@ -72,8 +72,8 @@ static int usage(void) static int detectInternalMouse(void) { if (!config.mouse.intdrv) { - com_printf("ERROR! Internal driver option not set, enable internal driver\n"); - com_printf(" in dosemu.conf ($_mouse_internal option).\n"); + printf("ERROR! Internal driver option not set, enable internal driver\n"); + printf(" in dosemu.conf ($_mouse_internal option).\n"); return 0; } return 1; @@ -112,76 +112,59 @@ int emumouse_main(int argc, char *argv[]) int val; i++; if (i == argc) { - com_printf("ERROR! No value for \"s\" found.\n"); + printf("ERROR! No value for \"s\" found.\n"); return(1); } val = argv[i][0] - '0'; - com_printf("Ignore VESA modes: %i\n", val); + printf("Ignore VESA modes: %i\n", val); SETLO_BYTE(regs.ecx, val); SETWORD(regs.ebx, 0x0006); mouse_helper(®s); break; } - case 'U': - case 'u': { - int val; - i++; - if (i == argc) { - com_printf("ERROR! No value for \"u\" found.\n"); - return(1); - } - val = argv[i][0] - '0'; - com_printf("Ungrabbed tweak: %i\n", val); - SETLO_BYTE(regs.ecx, val); - SETWORD(regs.ebx, 0x000b); - mouse_helper(®s); - break; - } - case 'R': case 'r': mouse_client_reset(); - com_printf("Resetting iret.\n"); + printf("Resetting iret.\n"); SETWORD(regs.ebx, 0x0000); mouse_helper(®s); break; case 'I': case 'i': - com_printf("\nCurrent mouse setting:\n"); + printf("\nCurrent mouse setting:\n"); SETWORD(regs.ebx, 0x0003); mouse_helper(®s); if (HI_BYTE_d(regs.ebx) == 0x10) - com_printf(" 2 button mouse mode (Microsoft)\n"); + printf(" 2 button mouse mode (Microsoft)\n"); else - com_printf(" 3 button mouse mode (e.g. Mousesystems, PS2)\n"); - com_printf (" Horizontal Speed (X) - %d\n", LO_BYTE_d(regs.ecx)); - com_printf (" Vertical Speed (Y) - %d\n", HI_BYTE_d(regs.ecx)); - com_printf (" Ignore VESA modes - %s\n", (LO_BYTE_d(regs.edx) & 1) ? "yes" : "no"); - com_printf (" Ungrab tweak - %s\n\n", (LO_BYTE_d(regs.edx) & 2) ? "yes" : "no"); + printf(" 3 button mouse mode (e.g. Mousesystems, PS2)\n"); + printf (" Horizontal Speed (X) - %d\n", LO_BYTE_d(regs.ecx)); + printf (" Vertical Speed (Y) - %d\n", HI_BYTE_d(regs.ecx)); + printf (" Ignore VESA modes - %s\n\n", LO_BYTE_d(regs.edx) ? "yes" : "no"); SETWORD(regs.ebx, 0x0007); mouse_helper(®s); if (LO_WORD(regs.eax) == 0) { - com_printf (" Minimum Internal Horizontal Resolution - %d\n", LO_WORD(regs.ecx)); - com_printf (" Minimum Internal Vertical Resolution - %d\n", LO_WORD(regs.edx)); + printf (" Minimum Internal Horizontal Resolution - %d\n", LO_WORD(regs.ecx)); + printf (" Minimum Internal Vertical Resolution - %d\n", LO_WORD(regs.edx)); } break; case '3': - com_printf("Selecting 3 button mouse mode (e.g. Mousesystems, PS2).\n"); + printf("Selecting 3 button mouse mode (e.g. Mousesystems, PS2).\n"); SETWORD(regs.ebx, 0x0002); mouse_helper(®s); if (LO_BYTE_d(regs.eax) == 0xff) { - com_printf("ERROR! Cannot select 3 button mouse mode, \"emulate3buttons\" not set\n"); - com_printf(" in /etc/dosemu.conf, try e.g.\n"); - com_printf(" 'mouse { ps2 device /dev/mouse internaldriver emulate3buttons }'\n"); + printf("ERROR! Cannot select 3 button mouse mode, \"emulate3buttons\" not set\n"); + printf(" in /etc/dosemu.conf, try e.g.\n"); + printf(" 'mouse { ps2 device /dev/mouse internaldriver emulate3buttons }'\n"); return (1); } break; case '2': - com_printf("Selecting 2 button mouse mode (Microsoft).\n"); + printf("Selecting 2 button mouse mode (Microsoft).\n"); SETWORD(regs.ebx, 0x0001); mouse_helper(®s); break; @@ -190,18 +173,16 @@ int emumouse_main(int argc, char *argv[]) case 'y': i++; if (i == argc) { - SETWORD(regs.ebx, 0x0003); - mouse_helper(®s); - com_printf(" Vertical Speed (Y) - %d\n", HI_BYTE_d(regs.ecx)); - break; + printf("ERROR! No value for \"y\" found.\n"); + return(1); } value = atoi(argv[i]); - com_printf("Selecting vertical speed to %d.\n", value); + printf("Selecting vertical speed to %d.\n", value); SETWORD(regs.ebx, 0x0004); SETLO_BYTE(regs.ecx, value); mouse_helper(®s); if (LO_WORD(regs.eax) == 1) { - com_printf("ERROR! Selected speed is out of range. Unable to set speed.\n"); + printf("ERROR! Selected speed is out of range. Unable to set speed.\n"); return(1); } break; @@ -210,18 +191,16 @@ int emumouse_main(int argc, char *argv[]) case 'x': i++; if (i == argc) { - SETWORD(regs.ebx, 0x0003); - mouse_helper(®s); - com_printf(" Horizontal Speed (X) - %d\n", LO_BYTE_d(regs.ecx)); - break; + printf("ERROR! No value for \"x\" found.\n"); + return(1); } value = atoi(argv[i]); - com_printf("Selecting horizontal speed to %d.\n", value); + printf("Selecting horizontal speed to %d.\n", value); SETWORD(regs.ebx, 0x0005); SETLO_BYTE(regs.ecx, value); mouse_helper(®s); if (LO_WORD(regs.eax) == 1) { - com_printf("ERROR! Selected speed is out of range. Unable to set speed.\n"); + printf("ERROR! Selected speed is out of range. Unable to set speed.\n"); return(1); } break; @@ -233,22 +212,22 @@ int emumouse_main(int argc, char *argv[]) case 'x': i++; if (i == argc) { - com_printf("ERROR! No value for \"Mx\" found.\n"); + printf("ERROR! No value for \"Mx\" found.\n"); return(1); } value = atoi(argv[i]); - com_printf("Selecting minimum horizontal resolution to %d.\n", value); + printf("Selecting minimum horizontal resolution to %d.\n", value); SETWORD(regs.ebx, 0x0007); mouse_helper(®s); if (LO_WORD(regs.eax) == 1) { - com_printf("ERROR! Setting minimum horizontal resolution not supported.\n"); + printf("ERROR! Setting minimum horizontal resolution not supported.\n"); break; } SETWORD(regs.ebx, 0x0008); SETWORD(regs.ecx, value); mouse_helper(®s); if (LO_WORD(regs.eax) == 1) { - com_printf("ERROR! Setting minimum horizontal resolution not supported.\n"); + printf("ERROR! Setting minimum horizontal resolution not supported.\n"); break; } break; @@ -257,28 +236,28 @@ int emumouse_main(int argc, char *argv[]) case 'y': i++; if (i == argc) { - com_printf("ERROR! No value for \"My\" found.\n"); + printf("ERROR! No value for \"My\" found.\n"); return(1); } value = atoi(argv[i]); - com_printf("Selecting minimum vertical resolution to %d.\n", value); + printf("Selecting minimum vertical resolution to %d.\n", value); SETWORD(regs.ebx, 0x0007); mouse_helper(®s); if (LO_WORD(regs.eax) == 1) { - com_printf("ERROR! Setting minimum vertical resolution not supported.\n"); + printf("ERROR! Setting minimum vertical resolution not supported.\n"); break; } SETWORD(regs.ebx, 0x0008); SETWORD(regs.edx, value); mouse_helper(®s); if (LO_WORD(regs.eax) == 1) { - com_printf("ERROR! Setting minimum vertical resolution not supported.\n"); + printf("ERROR! Setting minimum vertical resolution not supported.\n"); break; } break; default: - com_printf("ERROR! Unknown option \"%s\".\n\n", argv[i]); + printf("ERROR! Unknown option \"%s\".\n\n", argv[i]); return usage(); /* never reached */ break; @@ -289,7 +268,7 @@ int emumouse_main(int argc, char *argv[]) case 'c': i++; if (i == argc) { - com_printf("ERROR! No value found.\n"); + printf("ERROR! No value found.\n"); return(1); } value = atoi(argv[i]); @@ -302,7 +281,7 @@ int emumouse_main(int argc, char *argv[]) case 'l': i++; if (i == argc) { - com_printf("ERROR! No value found.\n"); + printf("ERROR! No value found.\n"); return(1); } value = atoi(argv[i]); @@ -312,7 +291,7 @@ int emumouse_main(int argc, char *argv[]) break; default: - com_printf("ERROR! Unknown option \"%s\".\n\n", argv[i]); + printf("ERROR! Unknown option \"%s\".\n\n", argv[i]); return usage(); /* never reached */ break; diff --git a/src/dosext/builtins/fossil.c b/src/dosext/builtins/fossil.c deleted file mode 100644 index f3df6d9..0000000 --- a/src/dosext/builtins/fossil.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". - * - * for details see file COPYING in the DOSEMU distribution - */ - -#include - -#include "builtins.h" -#include "doshelpers.h" -#include "fossil.h" - -int fossil_main(int argc, char **argv) -{ - struct REGPACK r = REGPACK_INIT; - - // get old interrupt vector to pass to Dosemu - r.r_ax = 0x3514; - com_intr(0x21, &r); // ES:BX now has old ISR addr - - // Check if we are good to load - r.r_ax = (DOS_HELPER_SERIAL_HELPER | (DOS_SUBHELPER_SERIAL_FOSSIL_INIT << 8)) & 0xffff; - // ES:BX still set - r.r_cx = DOS_VERSION_SERIAL_FOSSIL; - com_intr(DOS_HELPER_INT, &r); // DS:DX set by helper - - // set new interrupt vector (helper returned the ISR address in DS:DX) - if (!(r.r_flags & 1)) { // carry clear - r.r_ax = 0x2514; - // DS:DX still set - com_intr(0x21, &r); - - com_fprintf(com_stderr, "dosemu FOSSIL emulator: installed.\n"); - return 0; - } - - switch (r.r_bx) { - case DOS_ERROR_SERIAL_ALREADY_INSTALLED: - com_fprintf(com_stderr, "dosemu FOSSIL emulator: already installed.\n"); - return 1; - - case DOS_ERROR_SERIAL_CONFIG_DISABLED: - com_fprintf(com_stderr, "dosemu FOSSIL emulator: disabled in config.\n"); - return 2; - - case DOS_ERROR_SERIAL_FOSSIL_VERSION: - com_fprintf(com_stderr, "dosemu FOSSIL emulator: version mismatch, update FOSSIL.COM.\n"); - return 2; - - default: - com_fprintf(com_stderr, "dosemu FOSSIL emulator: unknown error.\n"); - return 2; - } -} diff --git a/src/dosext/builtins/fossil.h b/src/dosext/builtins/fossil.h deleted file mode 100644 index 4105f46..0000000 --- a/src/dosext/builtins/fossil.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * All modifications in this file to the original code are - * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". - * - * for details see file COPYING in the DOSEMU distribution - */ - -int fossil_main(int argc, char **argv); diff --git a/src/dosext/builtins/lredir.c b/src/dosext/builtins/lredir.c index 1751068..b10a0c9 100644 --- a/src/dosext/builtins/lredir.c +++ b/src/dosext/builtins/lredir.c @@ -340,7 +340,7 @@ struct lredir_opts { static int lredir_parse_opts(int argc, char *argv[], const char *getopt_string, struct lredir_opts *opts) { - int c; + char c; int need_args = 2; memset(opts, 0, sizeof(*opts)); @@ -351,7 +351,7 @@ static int lredir_parse_opts(int argc, char *argv[], return 0; } - GETOPT_RESET(); // glibc wants this to reser parser state + optind = 0; // glibc wants this to reser parser state while ((c = getopt(argc, argv, getopt_string)) != EOF) { switch (c) { case 'h': @@ -695,7 +695,7 @@ int lredir_main(int argc, char **argv) resourceStr[0] = '\0'; /* accept old unslashed notation */ - if (strncasecmp(get_arg2(argc, argv, &opts), &LINUX_RESOURCE[2], + if (strncasecmp(get_arg2(argc, argv, &opts), LINUX_RESOURCE + 2, strlen(LINUX_RESOURCE) - 2) == 0) { strcpy(resourceStr, "\\\\"); strcat(resourceStr, get_arg2(argc, argv, &opts)); diff --git a/src/dosext/builtins/msetenv.c b/src/dosext/builtins/msetenv.c index a3261f7..724834b 100644 --- a/src/dosext/builtins/msetenv.c +++ b/src/dosext/builtins/msetenv.c @@ -42,7 +42,7 @@ static char *envptr(int *size, int parent_p) /* msetenv - place an environment variable in command.com's copy of - the environment. + the envrionment. */ static int com_msetenv(const char *variable, const char *value, int parent_p) @@ -84,7 +84,7 @@ static int com_msetenv(const char *variable, const char *value, int parent_p) tail_sz += strlen(cp + 2) + 1; /* - If the variable fits, shovel it in at the end of the environment. + If the variable fits, shovel it in at the end of the envrionment. */ if (size - (env2 - env1) - tail_sz >= len) { memmove(env2 + len, env2, tail_sz); @@ -136,7 +136,7 @@ int mresize_env(int size_plus) else error("no env frame\n"); if (err) - error("can't free env frame\n"); + error("cant free env frame\n"); psp->envir_frame = new_env; return 0; } diff --git a/src/dosext/builtins/system.c b/src/dosext/builtins/system.c index 548ce30..908ff6a 100644 --- a/src/dosext/builtins/system.c +++ b/src/dosext/builtins/system.c @@ -53,17 +53,11 @@ static void do_parse_vars(const char *str, char drv, int parent); static char e_drv; static int vars_parsed; -static uint8_t drive; - -void system_com_reset(void) -{ - e_drv = 0; - vars_parsed = 0; -} +static int *drv_num_p; int system_main(int argc, char **argv) { - int c; + char c; int is_e = 0, is_p = 0; const char *getopt_string = "ercsp"; @@ -72,15 +66,14 @@ int system_main(int argc, char **argv) return usage(); } - GETOPT_RESET(); // glibc wants this to reser parser state + optind = 0; // glibc wants this to reser parser state while ((c = getopt(argc, argv, getopt_string)) != EOF) { /* Got a switch */ switch (c) { case 'e': /* Execute the DOS command given in dosemu command line with -E or -K */ is_e = 1; - if (config.tty_stderr == 1) - config.tty_stderr = 0; // output of -E goes to stdout + config.tty_stderr = 0; // output of -E goes to stdout break; case 'r': /* Execute the DOS command given in the Linux environment variable */ @@ -131,6 +124,7 @@ static int usage(void) static int setupDOSCommand(const char *dos_path, char *r_drv) { + int drive = *drv_num_p; char drvStr[2]; if (drive < 0) { @@ -147,24 +141,11 @@ static int setupDOSCommand(const char *dos_path, char *r_drv) return (0); } -static void setupDOSCommand2(const char *dos_path, char *r_drv) +static int do_system(const char *cmd, int terminate) { - if (dos_path[1] == ':') { - char drvStr[2]; - drvStr[0] = dos_path[0]; - drvStr[1] = '\0'; - msetenv("DOSEMU_SYS_DRV", drvStr); - if (r_drv) - *r_drv = drvStr[0]; - dos_path += 3; - } - if (dos_path[0]) - msetenv("DOSEMU_SYS_DIR", dos_path); -} - -static int do_system(const char *cmd) -{ - dbug_printf ("About to Execute: %s\n", cmd); +// com_printf ("About to Execute : %s\n", cmd); + if (terminate) + msetenv("DOSEMU_EXIT", "1"); msetenv("DOSEMU_SYS_CMD", cmd); return (0); } @@ -178,7 +159,7 @@ static int do_execute_dos(int argc, char **argv) cmd = getenv(argv[0]); if (!cmd) return (1); - return do_system(cmd); + return do_system(cmd, 0); } static void _do_parse_vars(char *str, char drv, int parent) @@ -268,17 +249,10 @@ static int do_execute_cmdline(int parent) char *vars, drv = e_drv; int ret = 0, first = 0; - /* Multiple invocations are possible due to freecom bug. - * First in a command.com's context and second in a separate process. - * If e_drv is not set then this is a first invocation. */ - if (!e_drv) { - if (config.unix_path) { - int err = setupDOSCommand(config.dos_path, &drv); - if (err) - return err; - } else if (config.dos_path) { - setupDOSCommand2(config.dos_path, &drv); - } + if (!e_drv && config.unix_path) { + int err = setupDOSCommand(config.dos_path, &drv); + if (err) + return err; e_drv = drv; // store for later -p first = 1; } @@ -301,7 +275,7 @@ static int do_execute_cmdline(int parent) } } if (config.dos_cmd) - ret = do_system(config.dos_cmd); + ret = do_system(config.dos_cmd, config.exit_on_cmd); return ret; } @@ -341,8 +315,6 @@ static void system_scrub(void) /* hack to support full path in -K */ if (!exists_file(config.unix_path)) goto err; - error("@Warning: -K deprecated.\n" - "\t should now be passed directly, so remove -K\n"); p = strrchr(config.unix_path, '/'); if (!p) goto err; @@ -350,7 +322,9 @@ static void system_scrub(void) *p = 0; } } - add_syscom_drive(config.unix_path, &drive); + drv_num_p = add_syscom_drive(config.unix_path); + if (!drv_num_p) + goto err; return; err: diff --git a/src/dosext/builtins/system.h b/src/dosext/builtins/system.h index 9f0e2e4..260328f 100644 --- a/src/dosext/builtins/system.h +++ b/src/dosext/builtins/system.h @@ -6,4 +6,4 @@ */ int system_main(int argc, char **argv); -void system_com_reset(void); + diff --git a/src/dosext/builtins/unix.c b/src/dosext/builtins/unix.c index 8485879..78c15f5 100644 --- a/src/dosext/builtins/unix.c +++ b/src/dosext/builtins/unix.c @@ -20,7 +20,6 @@ #include #include #include "dos2linux.h" -#include "utilities.h" #include "system.h" #include "unix.h" @@ -29,22 +28,19 @@ static int usage(void); int unix_main(int argc, char **argv) { char s[256]; - int c; - int secure = 0, bg = 0; - const char *getopt_string = "+bercsd:w"; + char c; + int secure = 0; + const char *getopt_string = "+ercsd:w"; if (argc == 1 || (argc == 2 && !strcmp (argv[1], "/?"))) { return usage(); } - GETOPT_RESET(); // glibc wants this to reser parser state + optind = 0; // glibc wants this to reser parser state while ((c = getopt(argc, argv, getopt_string)) != EOF) { /* Got a switch */ switch (c) { - case 'b': - bg++; - break; case 's': secure++; break; @@ -73,10 +69,7 @@ int unix_main(int argc, char **argv) } return run_unix_secure(argv[optind]); } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wincompatible-pointer-types" - return run_unix_command(argc - optind, argv + optind, bg); -#pragma GCC diagnostic pop + return run_unix_command(argc - optind, argv + optind); } return 0; @@ -90,9 +83,8 @@ static int usage(void) com_printf (" Set unix work dir to \"dir\".\n\n"); com_printf ("UNIX -w\n"); com_printf (" Get current unix work dir.\n\n"); - com_printf ("UNIX [-b] command [arg1 ...]\n"); - com_printf (" Execute the Linux command with the arguments given.\n"); - com_printf (" -b means run in background.\n\n"); + com_printf ("UNIX command [arg1 ...]\n"); + com_printf (" Execute the Linux command with the arguments given.\n\n"); com_printf ("UNIX\n"); com_printf ("UNIX /?\n"); com_printf (" show this help screen\n"); diff --git a/src/dosext/builtins/xmode.c b/src/dosext/builtins/xmode.c index a5d2aa3..19371eb 100644 --- a/src/dosext/builtins/xmode.c +++ b/src/dosext/builtins/xmode.c @@ -15,6 +15,12 @@ #include "xmode.h" +#define printf com_printf +#define fprintf com_fprintf +#undef stderr +#define stderr com_stderr +#define intr com_intr + static int X_change_config(unsigned, void *); int xmode_main(int argc, char **argv) @@ -25,7 +31,7 @@ int xmode_main(int argc, char **argv) argv++; if(!--argc) { - com_fprintf(com_stderr, + fprintf(stderr, "usage: xmode \n" " -mode activate graphics/text mode\n" " -title set name of emulator (in window title)\n" @@ -37,7 +43,6 @@ int xmode_main(int argc, char **argv) " -winsize set initial graphics window size\n" " -bpause on|off pause DOSEMU if the window loses focus\n" " -fullscreen on|off fullscreen mode\n" - " -mouse-ungrab-tweak on|off fix coords problems in ungrabbed mode\n" ); return 0; } @@ -72,7 +77,7 @@ int xmode_main(int argc, char **argv) else if(!strcmp(*argv, "-map") && argc >= 2) { l = strtol(argv[1], &p, 0); if(argv[1] == p) { - com_fprintf(com_stderr, "invalid mode number \"%s\"\n", argv[1]); + fprintf(stderr, "invalid mode number \"%s\"\n", argv[1]); return 2; } X_change_config(CHG_MAP, &l); @@ -81,7 +86,7 @@ int xmode_main(int argc, char **argv) else if(!strcmp(*argv, "-unmap") && argc >= 2) { l = strtol(argv[1], &p, 0); if(argv[1] == p) { - com_fprintf(com_stderr, "invalid mode number \"%s\"\n", argv[1]); + fprintf(stderr, "invalid mode number \"%s\"\n", argv[1]); return 2; } X_change_config(CHG_UNMAP, &l); @@ -90,12 +95,12 @@ int xmode_main(int argc, char **argv) else if(!strcmp(*argv, "-winsize") && argc >= 3) { ll[0] = strtol(argv[1], &p, 0); if(argv[1] == p) { - com_fprintf(com_stderr, "invalid width \"%s\"\n", argv[1]); + fprintf(stderr, "invalid width \"%s\"\n", argv[1]); return 2; } ll[1] = strtol(argv[2], &p, 0); if(argv[2] == p) { - com_fprintf(com_stderr, "invalid height \"%s\"\n", argv[2]); + fprintf(stderr, "invalid height \"%s\"\n", argv[2]); return 2; } X_change_config(CHG_WINSIZE, ll); @@ -104,7 +109,7 @@ int xmode_main(int argc, char **argv) else if(!strcmp(*argv, "-mode") && argc >= 2) { l = strtol(argv[1], &p, 0); if(argv[1] == p) { - com_fprintf(com_stderr, "invalid mode number \"%s\"\n", argv[1]); + fprintf(stderr, "invalid mode number \"%s\"\n", argv[1]); return 2; } if(l & ~0xff) { @@ -112,13 +117,13 @@ int xmode_main(int argc, char **argv) r.r_bx = l & 0xffff; r.r_ax = 0x4f02; - com_intr(0x10, &r); + intr(0x10, &r); } else { struct REGPACK r = REGPACK_INIT; r.r_ax = l & 0xff; - com_intr(0x10, &r); + intr(0x10, &r); } argc -= 2; argv += 2; } @@ -140,17 +145,8 @@ int xmode_main(int argc, char **argv) X_change_config(CHG_FULLSCREEN, &l); argc -= 2; argv += 2; } - else if (!strcmp(*argv, "-mouse-ungrab-tweak") && argc >= 2) { - if (strequalDOS (argv [1], "OFF") || strequalDOS (argv [1], "0")) - l = 0; - else - l = 1; - - config.mouse.ignore_speed = l; - argc -= 2; argv += 2; - } else { - com_fprintf(com_stderr, "Don't know what to do with argument \"%s\"; aborting here.\n", *argv); + fprintf(stderr, "Don't know what to do with argument \"%s\"; aborting here.\n", *argv); return 2; } } diff --git a/src/dosext/dpmi/Makefile b/src/dosext/dpmi/Makefile index ca49bbd..c202404 100644 --- a/src/dosext/dpmi/Makefile +++ b/src/dosext/dpmi/Makefile @@ -1,11 +1,12 @@ top_builddir=../../.. include $(top_builddir)/Makefile.conf -CFILES = dpmi.c memory.c emu-ldt.c msdoshlp.c vxd.c coopth_pm.c dpmi_api.c +CFILES = dpmi.c dnative.c memory.c emu-ldt.c msdoshlp.c vxd.c coopth_pm.c \ + dpmi_api.c SFILES = dpmisel.S ALL_CPPFLAGS += -I$(REALTOPDIR)/src/dosext/dpmi/msdos \ -DDOSEMU -all: lib +all: lib include $(REALTOPDIR)/src/Makefile.common diff --git a/src/dosext/dpmi/coopth_pm.c b/src/dosext/dpmi/coopth_pm.c index eb86156..2b57b7c 100644 --- a/src/dosext/dpmi/coopth_pm.c +++ b/src/dosext/dpmi/coopth_pm.c @@ -35,8 +35,8 @@ struct co_pm { Bit16u hlt_off; unsigned offs; - void (*post)(cpuctx_t *); - unsigned int leader:1; + void (*post)(sigcontext_t *); + int leader:1; }; #define INVALID_HLT 0xffffffff @@ -50,11 +50,11 @@ static struct co_pm_pth coopthpm_pth[COOPTH_POOL_SIZE]; static int is_active(int tid, int idx) { - cpuctx_t *scp = dpmi_get_scp(); + sigcontext_t *scp = dpmi_get_scp(); return (_cs == dpmi_sel() && _eip == coopthpm_pth[idx].hlt_off); } -static int to_sleep(int tid) +static int to_sleep(void) { if (!dpmi_isset_IF()) { dosemu_error("sleep with interrupts disabled\n"); @@ -90,7 +90,7 @@ static const struct coopth_be_ops ops = { .id = COOPTH_BE_PM, }; -static int do_start_custom(int tid, cpuctx_t *scp) +static int do_start_custom(int tid, sigcontext_t *scp) { int idx = coopth_start_custom_internal(tid, scp); if (idx == -1) @@ -102,7 +102,7 @@ static int do_start_custom(int tid, cpuctx_t *scp) static void coopth_auto_hlt_pm(Bit16u offs, void *sc, void *arg) { - cpuctx_t *scp = sc; + sigcontext_t *scp = sc; struct co_pm *thr = arg; int tid = (thr - coopthpm) + (offs >> 1); @@ -138,7 +138,7 @@ static int register_handler(void *hlt_state, const char *name, } int coopth_create_pm(const char *name, coopth_func_t func, - void (*post)(cpuctx_t *), void *hlt_state, unsigned offs, + void (*post)(sigcontext_t *), void *hlt_state, unsigned offs, unsigned int *hlt_off) { int num; @@ -159,7 +159,7 @@ int coopth_create_pm(const char *name, coopth_func_t func, } int coopth_create_pm_multi(const char *name, coopth_func_t func, - void (*post)(cpuctx_t *), void *hlt_state, unsigned offs, + void (*post)(sigcontext_t *), void *hlt_state, unsigned offs, int len, unsigned int *hlt_off, int r_offs[]) { int num; @@ -183,11 +183,3 @@ int coopth_create_pm_multi(const char *name, coopth_func_t func, *hlt_off = ret + offs; return num; } - -void coopth_leave_pm(cpuctx_t *scp) -{ - struct co_pm *thr = &coopthpm[coopth_get_tid()]; - coopth_leave_internal(); - assert(thr->post); - thr->post(scp); -} diff --git a/src/dosext/dpmi/coopth_pm.h b/src/dosext/dpmi/coopth_pm.h index 968331a..04243c5 100644 --- a/src/dosext/dpmi/coopth_pm.h +++ b/src/dosext/dpmi/coopth_pm.h @@ -2,13 +2,11 @@ #define COOPTH_PM int coopth_create_pm(const char *name, coopth_func_t func, - void (*post)(cpuctx_t *), void *hlt_state, unsigned offs, + void (*post)(sigcontext_t *), void *hlt_state, unsigned offs, unsigned int *hlt_off); int coopth_create_pm_multi(const char *name, coopth_func_t func, - void (*post)(cpuctx_t *), void *hlt_state, unsigned offs, + void (*post)(sigcontext_t *), void *hlt_state, unsigned offs, int len, unsigned int *hlt_off, int r_offs[]); -void coopth_leave_pm(cpuctx_t *scp); - #endif diff --git a/src/dosext/dpmi/djdpmi.h b/src/dosext/dpmi/djdpmi.h deleted file mode 100644 index cd66533..0000000 --- a/src/dosext/dpmi/djdpmi.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef DJDPMI_H -#define DJDPMI_H -/* ripped from djgpp's dpmi.h */ - -#include -#define LONG int32_t -#define ULONG uint32_t - -typedef struct { - unsigned short offset16; - unsigned short segment; -} __dpmi_raddr; - -typedef struct { - ULONG offset32; - unsigned short selector; -} __dpmi_paddr; - -typedef struct { - ULONG handle; /* 0, 2 */ - ULONG size; /* or count */ /* 4, 6 */ - ULONG address; /* 8, 10 */ -} __dpmi_meminfo; - -typedef union { - struct { - ULONG edi; - ULONG esi; - ULONG ebp; - ULONG res; - ULONG ebx; - ULONG edx; - ULONG ecx; - ULONG eax; - } d; - struct { - unsigned short di, di_hi; - unsigned short si, si_hi; - unsigned short bp, bp_hi; - unsigned short res, res_hi; - unsigned short bx, bx_hi; - unsigned short dx, dx_hi; - unsigned short cx, cx_hi; - unsigned short ax, ax_hi; - unsigned short flags; - unsigned short es; - unsigned short ds; - unsigned short fs; - unsigned short gs; - unsigned short ip; - unsigned short cs; - unsigned short sp; - unsigned short ss; - } x; - struct { - unsigned char edi[4]; - unsigned char esi[4]; - unsigned char ebp[4]; - unsigned char res[4]; - unsigned char bl, bh, ebx_b2, ebx_b3; - unsigned char dl, dh, edx_b2, edx_b3; - unsigned char cl, ch, ecx_b2, ecx_b3; - unsigned char al, ah, eax_b2, eax_b3; - } h; -} __attribute__((packed)) __dpmi_regs; - -typedef struct { - unsigned char major; - unsigned char minor; - unsigned short flags; - unsigned char cpu; - unsigned char master_pic; - unsigned char slave_pic; -} __dpmi_version_ret; - -typedef struct { - ULONG largest_available_free_block_in_bytes; - ULONG maximum_unlocked_page_allocation_in_pages; - ULONG maximum_locked_page_allocation_in_pages; - ULONG linear_address_space_size_in_pages; - ULONG total_number_of_unlocked_pages; - ULONG total_number_of_free_pages; - ULONG total_number_of_physical_pages; - ULONG free_linear_address_space_in_pages; - ULONG size_of_paging_file_partition_in_pages; - ULONG reserved[3]; -} __dpmi_free_mem_info; - -typedef struct { - ULONG total_allocated_bytes_of_physical_memory_host; - ULONG total_allocated_bytes_of_virtual_memory_host; - ULONG total_available_bytes_of_virtual_memory_host; - ULONG total_allocated_bytes_of_virtual_memory_vcpu; - ULONG total_available_bytes_of_virtual_memory_vcpu; - ULONG total_allocated_bytes_of_virtual_memory_client; - ULONG total_available_bytes_of_virtual_memory_client; - ULONG total_locked_bytes_of_memory_client; - ULONG max_locked_bytes_of_memory_client; - ULONG highest_linear_address_available_to_client; - ULONG size_in_bytes_of_largest_free_memory_block; - ULONG size_of_minimum_allocation_unit_in_bytes; - ULONG size_of_allocation_alignment_unit_in_bytes; - ULONG reserved[19]; -} __dpmi_memory_info; - -typedef struct { - ULONG data16[2]; - ULONG code16[2]; - unsigned short ip; - unsigned short reserved; - ULONG data32[2]; - ULONG code32[2]; - ULONG eip; -} __dpmi_callback_info; - -typedef struct { - ULONG size_requested; - ULONG size; - ULONG handle; - ULONG address; - ULONG name_offset; - unsigned short name_selector; - unsigned short reserved1; - ULONG reserved2; -} __dpmi_shminfo; - -#endif diff --git a/src/dosext/dpmi/dmemory.h b/src/dosext/dpmi/dmemory.h index f17cde3..be15024 100644 --- a/src/dosext/dpmi/dmemory.h +++ b/src/dosext/dpmi/dmemory.h @@ -13,20 +13,11 @@ typedef struct dpmi_pm_block_stuct { unsigned int size; dosaddr_t base; u_short *attrs; - unsigned int linear:1; - unsigned int hwram:1; - unsigned int shm:1; + int linear:1; + int hwram:1; + unsigned int shmsize; char *shmname; char *rshmname; - char *shm_dir; - void *shlock; - void *dlock; - void *shm_lock; - uint32_t lock_flags; - int mapped; -#define PMBF_DJ64 1 - uint32_t flags; - int opaque; } dpmi_pm_block; typedef struct dpmi_pm_block_root_struc { @@ -38,6 +29,7 @@ dpmi_pm_block *lookup_pm_block_by_addr(dpmi_pm_block_root *root, dosaddr_t addr); dpmi_pm_block *lookup_pm_block_by_shmname(dpmi_pm_block_root *root, const char *shmname); +int count_shm_blocks(dpmi_pm_block_root *root, const char *sname); int dpmi_alloc_pool(void); void dpmi_free_pool(void); dpmi_pm_block *DPMI_malloc(dpmi_pm_block_root *root, unsigned int size); @@ -46,15 +38,9 @@ int DPMI_free(dpmi_pm_block_root *root, unsigned int handle); dpmi_pm_block *DPMI_realloc(dpmi_pm_block_root *root, unsigned int handle, unsigned int newsize); dpmi_pm_block *DPMI_reallocLinear(dpmi_pm_block_root *root, unsigned long handle, unsigned long newsize, int committed); dpmi_pm_block *DPMI_mallocShared(dpmi_pm_block_root *root, - const char *name, unsigned int size, int flags); -dpmi_pm_block *DPMI_mallocSharedNewNS(dpmi_pm_block_root *root, - const char *name, unsigned int size, int flags); -dpmi_pm_block *DPMI_mallocSharedNS(dpmi_pm_block_root *root, - const char *dname, const char *name, unsigned int size, int flags); -int DPMI_freeShared(dpmi_pm_block_root *root, uint32_t handle); -int DPMI_freeSharedNS(dpmi_pm_block_root *root, uint32_t handle); -int DPMI_freeShPartial(dpmi_pm_block_root *root, uint32_t handle); -void DPMI_freeAll(dpmi_pm_block_root *root, dpmi_pm_block *p); + char *name, unsigned int size, unsigned int shmsize, int flags); +int DPMI_freeShared(dpmi_pm_block_root *root, uint32_t handle, int unlnk); +void DPMI_freeAll(dpmi_pm_block_root *root); int DPMI_MapConventionalMemory(dpmi_pm_block_root *root, unsigned long handle, unsigned long offset, unsigned long low_addr, unsigned long cnt); dpmi_pm_block * DPMI_mapHWRam(dpmi_pm_block_root *root, @@ -63,10 +49,8 @@ int DPMI_unmapHWRam(dpmi_pm_block_root *root, dosaddr_t vbase); int DPMI_SetPageAttributes(dpmi_pm_block_root *root, unsigned long handle, int offs, u_short attrs[], int count); int DPMI_GetPageAttributes(dpmi_pm_block_root *root, unsigned long handle, int offs, u_short attrs[], int count); int dpmi_lin_mem_rsv(void); -int dpmi_lin_mem_size(void); int dpmi_lin_mem_free(void); int dpmi_free_memory(void); -int dpmi_alloced_memory(void); -int dpmi_largest_memory_block(void); +void dpmi_set_map_flags(int cap); #endif diff --git a/src/dosext/dpmi/dnative.c b/src/dosext/dpmi/dnative.c new file mode 100644 index 0000000..c6c8eb1 --- /dev/null +++ b/src/dosext/dpmi/dnative.c @@ -0,0 +1,245 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * native DPMI backend + * + * Author: Stas Sergeev + */ +#include +#include +#include "libpcl/pcl.h" +#include "sig.h" +#include "cpu.h" +#include "dosemu_debug.h" +#include "utilities.h" +#include "emu.h" +#include "mapping.h" +#include "emudpmi.h" +#include "dpmisel.h" +#include "dnative.h" + +static coroutine_t dpmi_tid; +static cohandle_t co_handle; +static int dpmi_ret_val; +static sigcontext_t emu_stack_frame; +static struct sigaction emu_tmp_act; +#define DPMI_TMP_SIG SIGUSR1 +static int in_dpmi_thr; +static int dpmi_thr_running; + +#ifdef __x86_64__ +static unsigned int *iret_frame; + +static void iret_frame_setup(sigcontext_t * scp) +{ + /* set up a frame to get back to DPMI via iret. The kernel does not save + %ss, and the SYSCALL instruction in sigreturn() destroys it. + + IRET pops off everything in 64-bit mode even if the privilege + does not change which is nice, but clobbers the high 48 bits + of rsp if the DPMI client uses a 16-bit stack which is not so + nice (see EMUfailure.txt). Setting %rsp to 0x100000000 so that + bits 16-31 are zero works around this problem, as DPMI code + can't see bits 32-63 anyway. + */ + + iret_frame[0] = _eip; + iret_frame[1] = _cs; + iret_frame[2] = _eflags; + iret_frame[3] = _esp; + iret_frame[4] = _ss; + _rsp = (unsigned long) iret_frame; +} + +void dpmi_iret_setup(sigcontext_t * scp) +{ + iret_frame_setup(scp); + _eflags &= ~TF; + _rip = (unsigned long) DPMI_iret; + _cs = getsegment(cs); +} + +void dpmi_iret_unwind(sigcontext_t * scp) +{ + if (_rip != (unsigned long) DPMI_iret) + return; + _eip = iret_frame[0]; + _cs = iret_frame[1]; + _eflags = iret_frame[2]; + _esp = iret_frame[3]; + _ss = iret_frame[4]; +} +#endif + + +static void dpmi_thr(void *arg); + +/* ======================================================================== */ +/* + * DANG_BEGIN_FUNCTION native_dpmi_control + * + * This function is similar to the vm86() syscall in the kernel and + * switches to dpmi code. + * + * DANG_END_FUNCTION + */ + +int native_dpmi_control(sigcontext_t *scp) +{ + unsigned saved_IF = (_eflags & IF); + + _eflags = get_EFLAGS(_eflags); + if (in_dpmi_thr) + signal_switch_to_dpmi(); + else + dpmi_tid = + co_create(co_handle, dpmi_thr, NULL, NULL, SIGSTACK_SIZE); + dpmi_thr_running++; + co_call(dpmi_tid); + dpmi_thr_running--; + if (in_dpmi_thr) + signal_switch_to_dosemu(); + assert(_eflags & IF); + if (!saved_IF) + _eflags &= ~IF; + _eflags &= ~VIF; + /* we may return here with sighandler's signal mask. + * This is done for speed-up. dpmi_control() restores the mask. */ + return dpmi_ret_val; +} + +int native_dpmi_exit(sigcontext_t * scp) +{ + int ret; + if (!in_dpmi_thr) + return DPMI_RET_DOSEMU; + D_printf("DPMI: leaving\n"); + dpmi_ret_val = DPMI_RET_EXIT; + ret = native_dpmi_control(scp); + if (in_dpmi_thr) + error("DPMI thread have not terminated properly\n"); + return ret; +} + +void dpmi_return(sigcontext_t * scp, int retcode) +{ + /* only used for CPUVM_NATIVE (from sigsegv.c: dosemu_fault1()) */ + if (!DPMIValidSelector(_cs)) { + dosemu_error("Return to dosemu requested within dosemu context\n"); + return; + } + copy_to_emu(dpmi_get_scp(), scp); + dpmi_ret_val = retcode; + signal_return_to_dosemu(); + co_resume(co_handle); + signal_return_to_dpmi(); + if (dpmi_ret_val == DPMI_RET_EXIT) + *scp = emu_stack_frame; + else + copy_to_dpmi(scp, dpmi_get_scp()); +} + +static void dpmi_switch_sa(int sig, siginfo_t * inf, void *uc) +{ + ucontext_t *uct = uc; + sigcontext_t *scp = &uct->uc_mcontext; +#ifdef __linux__ + emu_stack_frame.fpregs = aligned_alloc(16, sizeof(*__fpstate)); +#endif + copy_context(&emu_stack_frame, scp); + copy_to_dpmi(scp, dpmi_get_scp()); + sigaction(DPMI_TMP_SIG, &emu_tmp_act, NULL); + deinit_handler(scp, &uct->uc_flags); +} + +static void indirect_dpmi_transfer(void) +{ + struct sigaction act; + + act.sa_flags = SA_SIGINFO; + sigfillset(&act.sa_mask); + sigdelset(&act.sa_mask, SIGSEGV); + act.sa_sigaction = dpmi_switch_sa; + sigaction(DPMI_TMP_SIG, &act, &emu_tmp_act); + signal_set_altstack(1); + /* for some absolutely unclear reason neither pthread_self() nor + * pthread_kill() are the memory barriers. */ + asm volatile ("":::"memory"); + pthread_kill(pthread_self(), DPMI_TMP_SIG); + /* and we are back */ + signal_set_altstack(0); +#ifdef __linux__ + free(emu_stack_frame.fpregs); +#endif +} + +static void dpmi_thr(void *arg) +{ + in_dpmi_thr++; + indirect_dpmi_transfer(); + in_dpmi_thr--; +} + +void native_dpmi_setup(void) +{ + co_handle = co_thread_init(PCL_C_MC); + +#ifdef __x86_64__ + { + unsigned int i, j; + void *addr; + /* search for page with bits 16-31 clear within first 47 bits + of address space */ + for (i = 1; i < 0x8000; i++) { + for (j = 0; j < 0x10000; j += PAGE_SIZE) { + addr = (void *) (i * 0x100000000UL + j); + iret_frame = + mmap_mapping_ux(MAPPING_SCRATCH | MAPPING_NOOVERLAP, + addr, PAGE_SIZE, + PROT_READ | PROT_WRITE); + if (iret_frame != MAP_FAILED) + goto out; + } + } + out: + if (iret_frame != addr) { + error("Can't find DPMI iret page, leaving\n"); + leavedos(0x24); + } + } +#endif +} + +void native_dpmi_done(void) +{ + if (in_dpmi_thr && !dpmi_thr_running) + co_delete(dpmi_tid); + co_thread_cleanup(co_handle); +} + +void native_dpmi_enter(void) +{ + /* if we are going directly to a sighandler, mask async signals. */ + if (in_dpmi_thr) + signal_restore_async_sigs(); +} + +void native_dpmi_leave(void) +{ + /* for speed-up, DPMI switching corrupts signal mask. Fix it here. */ + signal_unblock_async_sigs(); +} diff --git a/src/dosext/dpmi/dnative.h b/src/dosext/dpmi/dnative.h new file mode 100644 index 0000000..60f6fb0 --- /dev/null +++ b/src/dosext/dpmi/dnative.h @@ -0,0 +1,11 @@ +#ifndef DNATIVE_H +#define DNATIVE_H + +void native_dpmi_setup(void); +void native_dpmi_done(void); +int native_dpmi_control(sigcontext_t *scp); +int native_dpmi_exit(sigcontext_t *scp); +void native_dpmi_enter(void); +void native_dpmi_leave(void); + +#endif diff --git a/src/dosext/dpmi/dnative/Makefile b/src/dosext/dpmi/dnative/Makefile deleted file mode 100644 index 37b1a77..0000000 --- a/src/dosext/dpmi/dnative/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -top_builddir=../../../.. -include $(top_builddir)/Makefile.conf - -CFILES = dnative.c sigsegv.c - -ALL_CPPFLAGS += -I$(REALTOPDIR)/src/dosext/dpmi \ - -I$(REALTOPDIR)/src/base/lib/mcontext - -all: lib - -include $(REALTOPDIR)/src/Makefile.common diff --git a/src/dosext/dpmi/dnative/dnative.c b/src/dosext/dpmi/dnative/dnative.c deleted file mode 100644 index 7cd8c49..0000000 --- a/src/dosext/dpmi/dnative/dnative.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * native DPMI backend - * - * Author: Stas Sergeev - */ -#include -#include -#include "libpcl/pcl.h" -#include "sig.h" -#include "cpu.h" -#include "dosemu_debug.h" -#include "utilities.h" -#include "emu.h" -#include "vgaemu.h" -#include "cpu-emu.h" -#include "mapping.h" -#include "emudpmi.h" -#include "dpmisel.h" -#include "dnative.h" - -#define EMU_X86_FXSR_MAGIC 0x0000 -static coroutine_t dpmi_tid; -static cohandle_t co_handle; -static int dpmi_ret_val; -static sigcontext_t emu_stack_frame; -static int in_dpmi_thr; -static int dpmi_thr_running; - -static void copy_context(sigcontext_t *d, sigcontext_t *s) -{ -#ifdef __linux__ - /* keep pointer to FPU state the same */ - fpregset_t fptr = d->fpregs; -#endif - *d = *s; -#ifdef __linux__ - d->fpregs = fptr; -#endif -} - -#ifdef __i386__ -/* On i386 only, if SSE is available (i.e. since the Pentium III), - the kernel will use FXSAVE to save FPU state, then put the following - on the signal stack: - * FXSAVE format converted to FSAVE format (108 bytes) - * status and magic field where magic == X86_FXSR_MAGIC (4 bytes) - * FXSAVE format (512 bytes), which can be used directly by our loadfpstate - However, when restoring FPU state it will only use the mxcsr and xmm - fields from the FXSAVE format, and take everything else from the FSAVE - format, so we must "undo" the kernel logic and put those fields into the - FSAVE region. - see also arch/x86/kernel/fpu/regset.c in Linux kernel */ -static void convert_from_fxsr(fpregset_t fptr, - const struct emu_fpxstate *fxsave) -{ - static_assert(sizeof(*fptr) == sizeof(struct emu_fsave), - "size mismatch"); - fxsave_to_fsave(fxsave, (struct emu_fsave *)fptr); -} -#endif - -static void copy_to_dpmi(sigcontext_t *scp, cpuctx_t *s) -{ -#ifdef __x86_64__ - /* needs to clear high part of RIP and RSP because AMD CPUs - * check whole 64bit regs against 32bit CS and SS limits on iret */ - _scp_rip = 0; - _scp_rsp = 0; -#endif -#define _C(x) _scp_##x = get_##x(s) - _C(es); - _C(ds); - _C(ss); - _C(cs); - _C(fs); - _C(gs); - _C(eax); - _C(ebx); - _C(ecx); - _C(edx); - _C(esi); - _C(edi); - _C(ebp); - _C(esp); - _C(eip); - _C(eflags); - _C(trapno); - _C(err); - _scp_cr2 = (uintptr_t)MEM_BASE32(get_cr2(s)); - - if (scp->fpregs) { - void *fpregs = scp->fpregs; -#ifdef __x86_64__ - static_assert(sizeof(*scp->fpregs) == sizeof(vm86_fpu_state), - "size mismatch"); -#else - /* i386: convert fxsave state to fsave state */ - convert_from_fxsr(scp->fpregs, &vm86_fpu_state); - if ((scp->fpregs->status >> 16) != EMU_X86_FXSR_MAGIC) - return; - fpregs = &scp->fpregs->status + 1; -#endif - memcpy(fpregs, &vm86_fpu_state, sizeof(vm86_fpu_state)); - } -} - -static void copy_to_emu(cpuctx_t *d, sigcontext_t *scp) -{ -#define _D(x) get_##x(d) = _scp_##x - _D(es); - _D(ds); - _D(ss); - _D(cs); - _D(fs); - _D(gs); - _D(eax); - _D(ebx); - _D(ecx); - _D(edx); - _D(esi); - _D(edi); - _D(ebp); - _D(esp); - _D(eip); - _D(eflags); - _D(trapno); - _D(err); - get_cr2(d) = DOSADDR_REL(LINP(_scp_cr2)); - if (scp->fpregs) { - void *fpregs = scp->fpregs; -#ifdef __x86_64__ - static_assert(sizeof(*scp->fpregs) == sizeof(vm86_fpu_state), - "size mismatch"); -#else - if ((scp->fpregs->status >> 16) == EMU_X86_FXSR_MAGIC) - fpregs = &scp->fpregs->status + 1; - else { - fsave_to_fxsave(fpregs, &vm86_fpu_state); - return; - } -#endif - memcpy(&vm86_fpu_state, fpregs, sizeof(vm86_fpu_state)); - } -} - -static void dpmi_thr(void *arg); - -static int handle_pf(cpuctx_t *scp) -{ - int rc; - dosaddr_t cr2 = _cr2; -#ifdef X86_EMULATOR -#ifdef HOST_ARCH_X86 - /* DPMI code touches cpuemu prot */ - if (IS_EMU_JIT() && e_invalidate_page_full(cr2)) - return DPMI_RET_CLIENT; -#endif -#endif - signal_unblock_async_sigs(); - rc = vga_emu_fault(cr2, _err, scp); - /* going for dpmi_fault() or deinit_handler(), - * careful with async signals and sas_wa */ - signal_restore_async_sigs(); - if (rc == True) - return DPMI_RET_CLIENT; - return DPMI_RET_FAULT; -} - -/* ======================================================================== */ -/* - * DANG_BEGIN_FUNCTION native_dpmi_control - * - * This function is similar to the vm86() syscall in the kernel and - * switches to dpmi code. - * - * DANG_END_FUNCTION - */ - -int native_dpmi_control(cpuctx_t *scp) -{ - unsigned saved_IF = (_eflags & IF); - - _eflags = get_EFLAGS(_eflags); - if (in_dpmi_thr) - signal_switch_to_dpmi(); - else - dpmi_tid = - co_create(co_handle, dpmi_thr, NULL, NULL, SIGSTACK_SIZE); - dpmi_thr_running++; - co_call(dpmi_tid); - dpmi_thr_running--; - if (in_dpmi_thr) - signal_switch_to_dosemu(); - assert(_eflags & IF); - if (!saved_IF) - _eflags &= ~IF; - _eflags &= ~VIF; - if (dpmi_ret_val == DPMI_RET_FAULT && _trapno == 0x0e) - dpmi_ret_val = handle_pf(scp); - /* we may return here with sighandler's signal mask. - * This is done for speed-up. dpmi_control() restores the mask. */ - return dpmi_ret_val; -} - -int native_dpmi_exit(cpuctx_t *scp) -{ - int ret; - if (!in_dpmi_thr) - return DPMI_RET_DOSEMU; - D_printf("DPMI: leaving\n"); - dpmi_ret_val = DPMI_RET_EXIT; - ret = native_dpmi_control(scp); - if (in_dpmi_thr) - error("DPMI thread have not terminated properly\n"); - return ret; -} - -void dpmi_return(sigcontext_t *scp, int retcode) -{ - /* only used for CPUVM_NATIVE (from sigsegv.c: dosemu_fault1()) */ - if (!DPMIValidSelector(_scp_cs)) { - dosemu_error("Return to dosemu requested within dosemu context\n"); - return; - } - dpmi_ret_val = retcode; - if (retcode == DPMI_RET_EXIT) { - copy_context(scp, &emu_stack_frame); - return; - } - copy_to_emu(dpmi_get_scp(), scp); - /* signal handlers start with clean FPU state, but we unmask - overflow/division by zero in main code */ - fesetenv(&dosemu_fenv); - signal_return_to_dosemu(); - co_resume(co_handle); - signal_return_to_dpmi(); - if (dpmi_ret_val == DPMI_RET_EXIT) - copy_context(scp, &emu_stack_frame); - else - copy_to_dpmi(scp, dpmi_get_scp()); -} - -void dpmi_switch_sa(int sig, siginfo_t * inf, void *uc) -{ - ucontext_t *uct = uc; - sigcontext_t *scp = &uct->uc_mcontext; - copy_context(&emu_stack_frame, scp); - copy_to_dpmi(scp, dpmi_get_scp()); - unsetsig(DPMI_TMP_SIG); - deinit_handler(scp, &uct->uc_flags); -} - -static void indirect_dpmi_transfer(void) -{ - signative_start(); - signal_set_altstack(1); - /* for some absolutely unclear reason neither pthread_self() nor - * pthread_kill() are the memory barriers. */ - asm volatile ("":::"memory"); - pthread_kill(pthread_self(), DPMI_TMP_SIG); - /* and we are back */ - signal_set_altstack(0); - signative_stop(); - /* we inherited FPU state from DPMI, so put back to DOSEMU state */ - fesetenv(&dosemu_fenv); -} - -static void dpmi_thr(void *arg) -{ - in_dpmi_thr++; - indirect_dpmi_transfer(); - in_dpmi_thr--; -} - -int native_dpmi_setup(void) -{ - co_handle = co_thread_init(PCL_C_MC); - return 0; -} - -void native_dpmi_done(void) -{ - if (in_dpmi_thr && !dpmi_thr_running) - co_delete(dpmi_tid); - co_thread_cleanup(co_handle); -} - -void native_dpmi_enter(void) -{ - /* if we are going directly to a sighandler, mask async signals. */ - if (in_dpmi_thr) - signal_restore_async_sigs(); -} - -void native_dpmi_leave(void) -{ - /* for speed-up, DPMI switching corrupts signal mask. Fix it here. */ - signal_unblock_async_sigs(); -} diff --git a/src/dosext/dpmi/dnative/dnative.h b/src/dosext/dpmi/dnative/dnative.h deleted file mode 100644 index f28f0fb..0000000 --- a/src/dosext/dpmi/dnative/dnative.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef DNATIVE_H -#define DNATIVE_H - -#ifdef DNATIVE - -int native_dpmi_setup(void); -void native_dpmi_done(void); -int native_dpmi_control(cpuctx_t *scp); -int native_dpmi_exit(cpuctx_t *scp); -void native_dpmi_enter(void); -void native_dpmi_leave(void); -void dpmi_return(sigcontext_t *scp, int retcode); -void dpmi_switch_sa(int sig, siginfo_t * inf, void *uc); - -#define DPMI_TMP_SIG SIGUSR1 - -#else - -static inline int native_dpmi_setup(void) -{ - error("Native DPMI not compiled in\n"); - return -1; -} - -static inline void native_dpmi_done(void) -{ -} - -static inline int native_dpmi_control(cpuctx_t *scp) -{ - return 0; -} - -static inline int native_dpmi_exit(cpuctx_t *scp) -{ - return 0; -} - -static inline void native_dpmi_enter(void) -{ -} - -static inline void native_dpmi_leave(void) -{ -} - -static inline void dpmi_return(sigcontext_t *scp, int retcode) -{ -} - -#endif - -#endif diff --git a/src/dosext/dpmi/dnative/sigsegv.c b/src/dosext/dpmi/dnative/sigsegv.c deleted file mode 100644 index 90779b7..0000000 --- a/src/dosext/dpmi/dnative/sigsegv.c +++ /dev/null @@ -1,1179 +0,0 @@ -#include "mapping.h" -#include "debug.h" - -/* Define if we want graphics in X (of course we want :-) (root@zaphod) */ -/* WARNING: This may not work in BSD, because it was written for Linux! */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __linux__ -#include -#endif - -#include "emu.h" -#include "utilities.h" -#include "int.h" - -#include "video.h" -#include "vgaemu.h" /* root@zaphod */ - -#include "emudpmi.h" -#include "dnative.h" -#include "cpu-emu.h" -#include "dosemu_config.h" -#include "sig.h" - -/* sigaltstack work-around */ -#ifdef HAVE_LINUX_SIGNAL_H -#include -#endif -#if defined(DNATIVE) && defined(MCONTEXT) -#define SIGALTSTACK_WA_DEFAULT 1 -#else -#define SIGALTSTACK_WA_DEFAULT 0 -#endif -#if SIGALTSTACK_WA_DEFAULT - #ifdef DISABLE_SYSTEM_WA - #ifdef SS_AUTODISARM - #define SIGALTSTACK_WA 0 - #else - #ifdef WARN_UNDISABLED_WA - #warning Not disabling SIGALTSTACK_WA, update your kernel - #endif - #define SIGALTSTACK_WA 1 - #endif - #else - /* work-around sigaltstack badness - disable when kernel is fixed */ - #define SIGALTSTACK_WA 1 - #endif - #if defined(WARN_OUTDATED_WA) && defined(SS_AUTODISARM) - #warning SIGALTSTACK_WA is outdated - #endif -#else - #define SIGALTSTACK_WA 0 -#endif -#if SIGALTSTACK_WA -#include "mcontext.h" -#include "mapping.h" -#endif -/* SS_AUTODISARM is a dosemu-specific sigaltstack extension supported - * by some kernels */ -#ifndef SS_AUTODISARM -#define SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ -#endif - -/* sigreturn work-around */ -#ifdef HAVE_ASM_UCONTEXT_H -#include -#endif -#ifdef __x86_64__ - #define SIGRETURN_WA_DEFAULT DNATIVE -#else - #define SIGRETURN_WA_DEFAULT 0 -#endif -#if SIGRETURN_WA_DEFAULT - #ifdef DISABLE_SYSTEM_WA - #ifdef UC_SIGCONTEXT_SS - #define SIGRETURN_WA 0 - #else - #ifdef WARN_UNDISABLED_WA - #warning Not disabling SIGRETURN_WA, update your kernel - #endif - #define SIGRETURN_WA 1 - #endif - #else - /* work-around sigreturn badness - disable when kernel is fixed */ - #define SIGRETURN_WA 1 - #endif - #if defined(WARN_OUTDATED_WA) && defined(UC_SIGCONTEXT_SS) - #warning SIGRETURN_WA is outdated - #endif -#else - #define SIGRETURN_WA 0 -#endif - -#define loadflags(value) asm volatile("push %0 ; popf"::"g" (value): "cc" ) - -#define loadregister(reg, value) \ - asm volatile("mov %0, %%" #reg ::"rm" (value)) - -#define getsegment(reg) \ - ({ \ - Bit16u __value; \ - asm volatile("mov %%" #reg ",%0":"=rm" (__value)); \ - __value; \ - }) - -static struct eflags_fs_gs { - unsigned long eflags; - unsigned short fs, gs; -#ifdef __x86_64__ - unsigned char *fsbase, *gsbase; - unsigned short ds, es, ss; -#endif -} eflags_fs_gs; -static void *cstack; -static struct sigaction sacts[SIGMAX]; -static int block_all_sigs; -#if SIGALTSTACK_WA -static void *backup_stack; -static int need_sas_wa; -#endif -#if SIGRETURN_WA -static int need_sr_wa; -#endif - -#if SIGRETURN_WA -static unsigned int *iret_frame; - -asm("\n\ - .globl DPMI_iret\n\ - .type DPMI_iret,@function\n\ -DPMI_iret:\n\ - iretl\n\ -"); -extern void DPMI_iret(void); - -static void iret_frame_alloc(void) -{ - unsigned int i, j; - void *addr; - /* search for page with bits 16-31 clear within first 47 bits - of address space */ - for (i = 1; i < 0x8000; i++) { - for (j = 0; j < 0x10000; j += PAGE_SIZE) { - addr = (void *) (i * 0x100000000UL + j); - iret_frame = - mmap_mapping(MAPPING_SCRATCH | MAPPING_NOOVERLAP, - addr, PAGE_SIZE, PROT_READ | PROT_WRITE); - if (iret_frame != MAP_FAILED) - goto out; - } - } -out: - if (iret_frame != addr) { - error("Can't find DPMI iret page, leaving\n"); - config.exitearly = 1; - } -} - -static void iret_frame_setup(sigcontext_t * scp) -{ - /* set up a frame to get back to DPMI via iret. The kernel does not save - %ss, and the SYSCALL instruction in sigreturn() destroys it. - - IRET pops off everything in 64-bit mode even if the privilege - does not change which is nice, but clobbers the high 48 bits - of rsp if the DPMI client uses a 16-bit stack which is not so - nice (see EMUfailure.txt). Setting %rsp to 0x100000000 so that - bits 16-31 are zero works around this problem, as DPMI code - can't see bits 32-63 anyway. - */ - - iret_frame[0] = _scp_eip; - iret_frame[1] = _scp_cs; - iret_frame[2] = _scp_eflags; - iret_frame[3] = _scp_esp; - iret_frame[4] = _scp_ss; - _scp_rsp = (unsigned long) iret_frame; -} - -static void dpmi_iret_setup(sigcontext_t * scp) -{ - iret_frame_setup(scp); - _scp_eflags &= ~TF; - _scp_rip = (unsigned long) DPMI_iret; - _scp_cs = getsegment(cs); -} - -static void dpmi_iret_unwind(sigcontext_t * scp) -{ - if (_scp_rip != (unsigned long) DPMI_iret) - return; - _scp_eip = iret_frame[0]; - _scp_cs = iret_frame[1]; - _scp_eflags = iret_frame[2]; - _scp_esp = iret_frame[3]; - _scp_ss = iret_frame[4]; -} -#endif - -#ifdef __x86_64__ -#ifndef UC_SIGCONTEXT_SS -/* - * UC_SIGCONTEXT_SS will be set when delivering 64-bit or x32 signals on - * kernels that save SS in the sigcontext. Kernels that set UC_SIGCONTEXT_SS - * allow signal handlers to set UC_STRICT_RESTORE_SS; - * if UC_STRICT_RESTORE_SS is set, then sigreturn will restore SS. - * - * For compatibility with old programs, the kernel will *not* set - * UC_STRICT_RESTORE_SS when delivering signals from 32bit code. - */ -#define UC_SIGCONTEXT_SS 0x2 -#define UC_STRICT_RESTORE_SS 0x4 -#endif -#endif - -static void init_handler(sigcontext_t *scp, unsigned long uc_flags); -static void print_exception_info(sigcontext_t *scp); - -static int dpmi_fault(sigcontext_t *scp) -{ - /* If this is an exception 0x11, we have to ignore it. The reason is that - * under real DOS the AM bit of CR0 is not set. - * Also clear the AC flag to prevent it from re-occuring. - */ - if (_scp_trapno == 0x11) { - g_printf("Exception 0x11 occurred, clearing AC\n"); - _scp_eflags &= ~AC; - return DPMI_RET_CLIENT; - } - - return DPMI_RET_FAULT; // process the rest in dosemu context -} - -/* - * DANG_BEGIN_FUNCTION dosemu_fault(int, sigcontext_t); - * - * All CPU exceptions (except 13=general_protection from V86 mode, - * which is directly scanned by the kernel) are handled here. - * - * We have 4 main cases: - * 1. VM86 faults from vm86() (i386 only) - * 2. DPMI faults with LDT _cs (native DPMI only) - * 3. Faults (PF/DE) generated from cpuemu. In this case _cs is the Linux - * userspace _cs - * 4. DOSEMU itself crashes (bad!) - * - * DANG_END_FUNCTION - */ -static void dosemu_fault1(int signum, sigcontext_t *scp, const siginfo_t *si) -{ - if (fault_cnt > 1) { - error("Fault handler re-entered! signal=%i _trapno=0x%x\n", - signum, _scp_trapno); - if (!in_vm86 && !DPMIValidSelector(_scp_cs)) { - siginfo_debug(si); - _exit(43); - } else { - error("BUG: Fault handler re-entered not within dosemu code! in_vm86=%i\n", - in_vm86); - } - goto bad; - } -#ifdef __x86_64__ - if (_scp_trapno == 0x0e && _scp_cr2 > 0xffffffff) - { -#ifdef X86_EMULATOR - if (IS_EMU_JIT() && e_in_compiled_code()) { - int i; - /* dosemu_error() will SIGSEGV in backtrace(). */ - error("JIT fault accessing invalid address 0x%08"PRI_RG", " - "RIP=0x%08"PRI_RG"\n", _scp_cr2, _scp_rip); - if (mapping_find_hole(_scp_rip, _scp_rip + 64, 1) == MAP_FAILED) { - error("@Generated code dump:\n"); - for (i = 0; i < 64; i++) { - error("@ %02x", *(unsigned char *)(_scp_rip + i)); - if ((i & 15) == 15) - error("@\n"); - } - } - goto bad; - } -#endif - dosemu_error("Accessing invalid address 0x%08"PRI_RG"\n", _scp_cr2); - goto bad; - } -#endif - - -#ifdef __i386__ - /* case 1: note that _scp_cr2 must be 0-based */ - if (in_vm86 && config.cpu_vm == CPUVM_VM86) { - true_vm86_fault(scp); - return; - } -#endif - - /* case 2: At first let's find out where we came from */ - if (DPMIValidSelector(_scp_cs)) { - int ret = DPMI_RET_FAULT; - assert(config.cpu_vm_dpmi == CPUVM_NATIVE); - if (_scp_trapno == 0x10) { - dbug_printf("coprocessor exception, calling IRQ13\n"); - print_exception_info(scp); - raise_fpu_irq(); - dpmi_return(scp, DPMI_RET_DOSEMU); - return; - } - - /* Not in dosemu code: dpmi_fault() will handle that */ - if (ret == DPMI_RET_FAULT) - ret = dpmi_fault(scp); - if (signal_pending() || ret != DPMI_RET_CLIENT) - dpmi_return(scp, ret); - return; - } - -#ifdef X86_EMULATOR - /* case 3 */ - if (IS_EMU_JIT() && e_emu_fault(scp, in_vm86)) - return; -#endif - - /* case 4 */ - error("Fault in dosemu code, in_dpmi=%i\n", dpmi_active()); - /* TODO - we can start gdb here */ - /* start_gdb() */ - /* Going to die from here */ - -bad: -/* All recovery attempts failed, going to die :( */ - - { - siginfo_debug(si); - - if (DPMIValidSelector(_scp_cs)) - print_exception_info(scp); - if (in_vm86) - show_regs(); - fatalerr = 4; - _leavedos_main(0, signum); /* shouldn't return */ - } -} - -/* noinline is to prevent gcc from moving TLS access around init_handler() */ -__attribute__((noinline)) -static void dosemu_fault0(int signum, sigcontext_t *scp, const siginfo_t *si) -{ - pthread_t tid; - - if (fault_cnt > 2) { - /* - * At this point we already tried leavedos(). Now try _exit() - * and NOT exit(3), because glibc is probably malfunctions if - * we are here. - */ - _exit(255); - } - - tid = pthread_self(); - if (!pthread_equal(tid, dosemu_pthread_self)) { -#ifdef __GLIBC__ - char name[128]; -#endif - /* disable cancellation to prevent main thread from terminating - * this one due to SIGSEGV elsewhere while we are doing backtrace */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); -#if defined(HAVE_PTHREAD_GETNAME_NP) && defined(__GLIBC__) - pthread_getname_np(tid, name, sizeof(name)); - dosemu_error("thread %s got signal %i, cr2=%llx\n", name, signum, - (unsigned long long)_scp_cr2); -#else - dosemu_error("thread got signal %i, cr2=%llx\n", signum, - (unsigned long long)_scp_cr2); -#endif - signal(signum, SIG_DFL); - pthread_kill(tid, signum); // dump core - _exit(23); - return; - } - -#ifdef __linux__ - if (kernel_version_code < KERNEL_VERSION(2, 6, 14)) { - sigset_t set; - - /* this emulates SA_NODEFER, so that we can double fault. - SA_NODEFER only works as documented in Linux kernels >= 2.6.14. - */ - sigemptyset(&set); - sigaddset(&set, signum); - sigprocmask(SIG_UNBLOCK, &set, NULL); - } -#endif - - if (debug_level('g')>7) - g_printf("Entering fault handler, signal=%i _trapno=0x%x\n", - signum, _scp_trapno); - - dosemu_fault1(signum, scp, si); - - if (debug_level('g')>8) - g_printf("Returning from the fault handler\n"); -} - -SIG_PROTO_PFX -static void dosemu_fault(int signum, siginfo_t *si, void *uc) -{ - ucontext_t *uct = uc; - sigcontext_t *scp = &uct->uc_mcontext; - /* need to call init_handler() before any syscall. - * Additionally, TLS access should be done in a separate no-inline - * function, so that gcc not to move the TLS access around init_handler(). */ - init_handler(scp, uct->uc_flags); -#if defined(__FreeBSD__) - /* freebsd does not provide cr2 */ - _scp_cr2 = (uintptr_t)si->si_addr; -#endif - fault_cnt++; - dosemu_fault0(signum, scp, si); - fault_cnt--; - deinit_handler(scp, &uct->uc_flags); -} - -/* - * DANG_BEGIN_FUNCTION print_exception_info - * - * Prints information about an exception: exception number, error code, - * address, reason, etc. - * - * DANG_END_FUNCTION - * - */ -static void print_exception_info(sigcontext_t *scp) -{ - int i; - - switch(_scp_trapno) - { - case 0: - error("@Division by zero\n"); - break; - - - case 1: - error("@Debug exception\n"); - break; - - - case 3: - error("@Breakpoint exception (caused by INT 3 instruction)\n"); - break; - - - case 4: - error("@Overflow exception (caused by INTO instruction)\n"); - break; - - - case 5: - error("@Bound exception (caused by BOUND instruction)\n"); - break; - - - case 6: { - unsigned char *csp; - int ps = getpagesize(); - unsigned pa = _scp_rip & (ps - 1); - int sub = _min(pa, 10); - int sup = _min(ps - pa, 10); - error("@Invalid opcode\n"); - error("@Opcodes: "); - csp = (unsigned char *) _scp_rip - sub; - for (i = 0; i < 10 - sub; i++) - error("@XX "); - for (i = 0; i < sub; i++) - error("@%02x ", *csp++); - error("@-> "); - for (i = 0; i < sup; i++) - error("@%02x ", *csp++); - for (i = 0; i < 10 - sup; i++) - error("@XX "); - error("@\n"); - break; - } - - case 7: - error("@Coprocessor exception (coprocessor not available)\n"); - /* I'd like to print some info on the EM, MP, and TS flags in CR0, - * but I don't know where I can get that information :-( - * Anyway, this exception should not happen... (Erik Mouw) - */ - break; - - - case 8: - error("@Double fault\n"); - break; - - - case 9: - error("@Coprocessor segment overflow\n"); - break; - - - case 0xa: - error("@Invalid TSS\n"); - if(_scp_err & 0x02) - error("@IDT"); - else if(_scp_err & 0x04) - error("@LDT"); - else - error("@GDT"); - - error("@ selector: 0x%04x\n", (unsigned)((_scp_err >> 3) & 0x1fff )); - - if(_scp_err & 0x01) - error("@Exception was not caused by DOSEMU\n"); - else - error("@Exception was caused by DOSEMU\n"); - break; - - - case 0xb: - error("@Segment not available\n"); - /* This is the same code as case 0x0a; the compiler merges these - * blocks, so I don't have to edit some dirty constructions to - * generate one block of code. (Erik Mouw) - */ - if(_scp_err & 0x02) - error("@IDT"); - else if(_scp_err & 0x04) - error("@LDT"); - else - error("@GDT"); - - error("@ selector: 0x%04x\n", (unsigned)((_scp_err >> 3) & 0x1fff )); - - if(_scp_err & 0x01) - error("@Exception was not caused by DOSEMU\n"); - else - error("@Exception was caused by DOSEMU\n"); - break; - - - case 0xc: - error("@Stack exception\n"); - break; - - - case 0xd: - error("@General protection exception\n"); - /* This is the same code as case 0x0a; the compiler merges these - * blocks, so I don't have to edit some dirty constructions to - * generate one block of code. (Erik Mouw) - */ - if(_scp_err & 0x02) - error("@IDT"); - else if(_scp_err & 0x04) - error("@LDT"); - else - error("@GDT"); - - error("@ selector: 0x%04x\n", (unsigned)((_scp_err >> 3) & 0x1fff )); - - if(_scp_err & 0x01) - error("@Exception was not caused by DOSEMU\n"); - else - error("@Exception was caused by DOSEMU\n"); - break; - - - case 0xe: - error("@Page fault: "); - if(_scp_err & 0x02) - error("@write"); - else - error("@read"); - - error("@ instruction to linear address: 0x%08"PRI_RG"\n", _scp_cr2); - - error("@CPU was in "); - if(_scp_err & 0x04) - error("@user mode\n"); - else - error("@supervisor mode\n"); - - error("@Exception was caused by "); - if(_scp_err & 0x01) - error("@insufficient privilege\n"); - else - error("@non-available page\n"); - break; - - case 0x10: { - int i, n; - unsigned short sw; - fpregset_t p = _scp_fpstate; - error ("@Coprocessor Error:\n"); -#ifdef __x86_64__ - error ("@cwd=%04x swd=%04x ftw=%04x\n", p->cwd, p->swd, p->ftw); - error ("@cs:rip=%04x:%08lx ds:data=%04x:%08lx\n", _scp_cs,p->rip,_scp_ds,p->rdp); - sw = p->swd; -#else - error ("@cw=%04x sw=%04x tag=%04x\n", - ((unsigned short)(p->cw)),((unsigned short)(p->sw)), - ((unsigned short)(p->tag))); - error ("@cs:eip=%04x:%08x ds:data=%04x:%08x\n", - ((unsigned short)(p->cssel)),(unsigned)p->ipoff, - ((unsigned short)(p->datasel)),(unsigned)p->dataoff); - sw = p->sw; -#endif - if ((sw&0x80)==0) error("@No error summary bit,why?\n"); - else { - if (sw&0x20) error("@Precision\n"); - if (sw&0x10) error("@Underflow\n"); - if (sw&0x08) error("@Overflow\n"); - if (sw&0x04) error("@Divide by 0\n"); - if (sw&0x02) error("@Denormalized\n"); - if ((sw&0x41)==0x01) error("@Invalid op\n"); - else if ((sw&0x41)==0x41) error("@Stack fault\n"); - } - n = (sw >> 11) & 7; - for (i=0; i<8; i++) { - unsigned short *r = p->_st[i].significand; - unsigned short e = p->_st[i].exponent; - error ("@fpr[%d] = %04x:%04x%04x%04x%04x\n",n,e,r[3],r[2],r[1],r[0]); - n = (n+1) & 7; - } - } break; - - case 0x13: { -#ifdef __x86_64__ - int i; - unsigned mxcsr; - fpregset_t p = _scp_fpstate; - error ("@SIMD Floating-Point Exception:\n"); - mxcsr = p->mxcsr; - error ("@mxcsr=%08x, mxcr_mask=%08x\n",mxcsr,(unsigned)(p->mxcr_mask)); - if (mxcsr&0x40) error("@Denormals are zero\n"); - if (mxcsr&0x20) error("@Precision\n"); - if (mxcsr&0x10) error("@Underflow\n"); - if (mxcsr&0x08) error("@Overflow\n"); - if (mxcsr&0x04) error("@Divide by 0\n"); - if (mxcsr&0x02) error("@Denormalized\n"); - if (mxcsr&0x01) error("@Invalid op\n"); - for (i=0; i_xmm)/sizeof(p->_xmm[0]); i++) - { - error ("@xmm[%d] = %08x:%08x:%08x:%08x\n",i, - (unsigned)p->_xmm[i].element[0], (unsigned)p->_xmm[i].element[1], - (unsigned)p->_xmm[i].element[2], (unsigned)p->_xmm[i].element[3]); - } -#else - error ("@SIMD Floating-Point Exception\n"); -#endif - break; - } - - default: - error("@Unknown exception\n"); - break; - } -} - -static void sigstack_init(void) -{ - /* sigaltstack_wa is optional. See if we need it. */ - /* .ss_flags is signed int and SS_AUTODISARM is a sign bit :( */ - stack_t dummy2; - stack_t dummy = { .ss_flags = (int)(SS_DISABLE | SS_AUTODISARM) }; - int err = sigaltstack(&dummy, &dummy2); - int errno_save = errno; - - /* needs to drop SS_AUTODISARM or asan will fail. See - * https://github.com/dosemu2/dosemu2/issues/1576 */ - sigaltstack(&dummy2, NULL); -#if SIGALTSTACK_WA - if ((err && errno_save == EINVAL) -#ifdef __i386__ -#ifdef __linux__ - /* kernels before 4.11 had the needed functionality only for 64bits */ - || kernel_version_code < KERNEL_VERSION(4, 11, 0) -#endif -#endif - ) - { - need_sas_wa = 1; - warn("Enabling sigaltstack() work-around\n"); - /* for SAS WA block all signals. If we don't, there is a - * race that the signal can come after we switched to backup stack - * but before we disabled sigaltstack. We unblock the fatal signals - * later, only right before switching back to dosemu. */ - block_all_sigs = 1; - } else if (err) { - goto unk_err; - } - - if (need_sas_wa) { - cstack = alloc_mapping(MAPPING_SHARED, SIGSTACK_SIZE); - if (cstack == MAP_FAILED) { - error("Unable to allocate stack\n"); - config.exitearly = 1; - return; - } - backup_stack = alias_mapping_ux(MAPPING_OTHER, SIGSTACK_SIZE, - PROT_READ | PROT_WRITE, cstack); - if (backup_stack == MAP_FAILED) { - error("Unable to allocate stack\n"); - config.exitearly = 1; - return; - } - } else { - cstack = mmap(NULL, SIGSTACK_SIZE, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (cstack == MAP_FAILED) { - error("Unable to allocate stack\n"); - config.exitearly = 1; - return; - } - } -#else - if ((err && errno_save == EINVAL) -#ifdef __i386__ -#ifdef __linux__ - || kernel_version_code < KERNEL_VERSION(4, 11, 0) -#endif -#endif - ) - { - error("Your kernel does not support SS_AUTODISARM and the " - "work-around in dosemu is not enabled.\n"); - config.exitearly = 1; - return; - } else if (err) { - goto unk_err; - } - cstack = mmap(NULL, SIGSTACK_SIZE, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); - if (cstack == MAP_FAILED) { - error("Unable to allocate stack\n"); - config.exitearly = 1; - return; - } -#endif - - return; - -unk_err: - if (err) { - error("sigaltstack() returned %i, %s\n", errno_save, - strerror(errno_save)); - config.exitearly = 1; - } -} - -void signative_init(void) -{ - sigstack_init(); -#if SIGRETURN_WA - /* 4.6+ are able to correctly restore SS */ -#ifdef __linux__ - if (kernel_version_code < KERNEL_VERSION(4, 6, 0)) { - need_sr_wa = 1; - warn("Enabling sigreturn() work-around for old kernel\n"); - /* block all sigs for SR WA. If we don't, the signal can come before - * SS is saved, but we can't restore SS on signal exit. */ - block_all_sigs = 1; - } -#endif -#endif -} - -void signal_set_altstack(int on) -{ - stack_t stk = { 0 }; - int err; - - if (!on) { - stk.ss_flags = SS_DISABLE; - err = sigaltstack(&stk, NULL); - } else { - stk.ss_sp = cstack; - stk.ss_size = SIGSTACK_SIZE; -#if SIGALTSTACK_WA - stk.ss_flags = SS_ONSTACK | (need_sas_wa ? 0 : SS_AUTODISARM); -#else - stk.ss_flags = SS_ONSTACK | SS_AUTODISARM; -#endif - err = sigaltstack(&stk, NULL); - } - if (err) { - error("sigaltstack(0x%x) returned %i, %s\n", - stk.ss_flags, err, strerror(errno)); - leavedos(err); - } -} - -#if SIGALTSTACK_WA -static void signal_sas_wa(void) -{ - int err; - stack_t ss = {}; - m_ucontext_t hack; - unsigned char *sp; - unsigned char *top = cstack + SIGSTACK_SIZE; - unsigned char *btop = backup_stack + SIGSTACK_SIZE; - ptrdiff_t delta; - - if (getmcontext(&hack) == 0) { - sp = alloca(sizeof(void *)); - delta = top - sp; - /* switch stack to its mirror (same phys addr) to cheat sigaltstack() */ - asm volatile( -#ifdef __x86_64__ - "mov %0, %%rsp\n" -#else - "mov %0, %%esp\n" -#endif - :: "r"(btop - delta)); - } else { - signal_unblock_fatal_sigs(); - return; - } - - ss.ss_flags = SS_DISABLE; - /* sas will re-enable itself when returning from sighandler */ - err = sigaltstack(&ss, NULL); - if (err) - perror("sigaltstack"); - - setmcontext(&hack); -} -#endif - -void signative_pre_init(void) -{ - /* initialize user data & code selector values (used by DPMI code) */ - /* And save %fs, %gs for NPTL */ - eflags_fs_gs.fs = getsegment(fs); - eflags_fs_gs.gs = getsegment(gs); - eflags_fs_gs.eflags = getflags(); - dbug_printf("initial register values: fs: 0x%04x gs: 0x%04x eflags: 0x%04lx\n", - eflags_fs_gs.fs, eflags_fs_gs.gs, eflags_fs_gs.eflags); -#ifdef __x86_64__ - eflags_fs_gs.ds = getsegment(ds); - eflags_fs_gs.es = getsegment(es); - eflags_fs_gs.ss = getsegment(ss); - /* get long fs and gs bases. If they are in the first 32 bits - normal 386-style fs/gs switching can happen so we can ignore - fsbase/gsbase */ - dosemu_arch_prctl(ARCH_GET_FS, &eflags_fs_gs.fsbase); - if (((unsigned long)eflags_fs_gs.fsbase <= 0xffffffff) && eflags_fs_gs.fs) - eflags_fs_gs.fsbase = 0; - dosemu_arch_prctl(ARCH_GET_GS, &eflags_fs_gs.gsbase); - if (((unsigned long)eflags_fs_gs.gsbase <= 0xffffffff) && eflags_fs_gs.gs) - eflags_fs_gs.gsbase = 0; - dbug_printf("initial segment bases: fs: %p gs: %p\n", - eflags_fs_gs.fsbase, eflags_fs_gs.gsbase); -#endif - -#if SIGRETURN_WA - iret_frame_alloc(); -#endif -} - -SIG_PROTO_PFX -static void signative_enter(sigcontext_t *scp) -{ -#if SIGRETURN_WA - if (need_sr_wa && !DPMIValidSelector(_scp_cs)) - dpmi_iret_unwind(scp); -#endif - -#if 0 - /* for async signals need to restore fs/gs even if dosemu code - * was interrupted, because it can be interrupted in a switching - * routine when fs or gs are already switched but cs is not */ - if (!DPMIValidSelector(_scp_cs) && !async) - return; -#else - /* as DIRECT_DPMI_SWITCH support is now removed, the above comment - * applies only to DPMI_iret, which is now unwound. - * We don't need to restore segregs for async signals any more. */ - if (!DPMIValidSelector(_scp_cs)) - return; -#endif - - /* restore %fs and %gs for compatibility with NPTL. */ - if (getsegment(fs) != eflags_fs_gs.fs) - loadregister(fs, eflags_fs_gs.fs); - if (getsegment(gs) != eflags_fs_gs.gs) - loadregister(gs, eflags_fs_gs.gs); -#ifdef __x86_64__ - loadregister(ds, eflags_fs_gs.ds); - loadregister(es, eflags_fs_gs.es); - /* kernel has the following rule: non-zero selector means 32bit base - * in GDT. Zero selector means 64bit base, set via msr. - * So if we set selector to 0, need to use also prctl(ARCH_SET_xS). - * Also, if the bases are not used they are 0 so no need to restore, - * which saves a syscall */ - if (!eflags_fs_gs.fs && eflags_fs_gs.fsbase) - dosemu_arch_prctl(ARCH_SET_FS, eflags_fs_gs.fsbase); - if (!eflags_fs_gs.gs && eflags_fs_gs.gsbase) - dosemu_arch_prctl(ARCH_SET_GS, eflags_fs_gs.gsbase); -#endif -} - -/* init_handler puts the handler in a sane state that glibc - expects. That means restoring fs, gs and eflags for DPMI. */ -SIG_PROTO_PFX -static void __init_handler(sigcontext_t *scp, unsigned long uc_flags) -{ - /* - * FIRST thing to do in signal handlers - to avoid being trapped into int0x11 - * forever, we must restore the eflags. - */ - loadflags(eflags_fs_gs.eflags); - -#ifdef __x86_64__ - /* ds,es, and ss are ignored in 64-bit mode and not present or - saved in the sigcontext, so we need to do it ourselves - (using the 3 high words of the trapno field). - fs and gs are set to 0 in the sigcontext, so we also need - to save those ourselves */ - _scp_ds = getsegment(ds); - _scp_es = getsegment(es); - if (!(uc_flags & UC_SIGCONTEXT_SS)) - _scp_ss = getsegment(ss); - _scp_fs = getsegment(fs); - _scp_gs = getsegment(gs); - if (_scp_cs == 0) { - if (config.dpmi -#ifdef X86_EMULATOR - && !EMU_DPMI() -#endif - ) { - fprintf(stderr, "Cannot run DPMI code natively "); -#ifdef __linux__ - if (kernel_version_code < KERNEL_VERSION(2, 6, 15)) - fprintf(stderr, "because your Linux kernel is older than version 2.6.15.\n"); - else - fprintf(stderr, "for unknown reasons.\nPlease contact linux-msdos@vger.kernel.org.\n"); -#endif -#ifdef X86_EMULATOR - fprintf(stderr, "Set $_cpu_emu=\"full\" or \"fullsim\" to avoid this message.\n"); -#endif - } -#ifdef X86_EMULATOR - config.cpu_vm = CPUVM_EMU; - _scp_cs = getsegment(cs); -#else - leavedos_sig(45); -#endif - } -#endif - - signative_enter(scp); - assert(config.cpu_vm_dpmi == CPUVM_NATIVE); -} - -SIG_PROTO_PFX -static void init_handler(sigcontext_t *scp, unsigned long uc_flags) -{ - /* Async signals are initially blocked. - * If we don't block them, nested sighandler will clobber SS - * before we manage to save it. - * Even if the nested sighandler tries hard, it can't properly - * restore SS, at least until the proper sigreturn() support is in. - * For kernels that have the proper SS support, only nonfatal - * async signals are initially blocked. They need to be blocked - * because of sas wa and because they should not interrupt - * deinit_handler() after it changed %fs. In this case, however, - * we can block them later at the right places, but this will - * cost a syscall per every signal. - * Note: in 64bit mode some segment registers are neither saved nor - * restored by the signal dispatching code in kernel, so we have - * to restore them by hands. - * Note: most async signals are left blocked, we unblock only few. - * Sync signals like SIGSEGV are never blocked. - */ - __init_handler(scp, uc_flags); - if (!block_all_sigs) - return; -#if SIGALTSTACK_WA - /* for SAS WA we unblock the fatal signals even later if we came - * from DPMI, as then we'll be switching stacks which is racy when - * async signals enabled. */ - if (need_sas_wa && DPMIValidSelector(_scp_cs)) - return; -#endif - /* either came from dosemu/vm86 or having SS_AUTODISARM - - * then we can unblock any signals we want. This is because - * dosemu DOES NOT USE signal stack by itself. We switch to - * dosemu via a direct context switch (including a stack switch), - * before which we make sure either SS_AUTODISARM or sas_wa worked. - * So we are here either on dosemu stack, or on autodisarmed SAS. - * For now leave nonfatal signals blocked as they are rarely needed - * inside sighandlers (needed only for instremu, see - * https://github.com/stsp/dosemu2/issues/477 - * ) */ - signal_unblock_fatal_sigs(); -} - -void signative_sigbreak(void *uc) -{ - ucontext_t *uct = uc; - sigcontext_t *scp = &uct->uc_mcontext; - if (DPMIValidSelector(_scp_cs)) - dpmi_return(scp, DPMI_RET_DOSEMU); -} - -SIG_PROTO_PFX -void deinit_handler(sigcontext_t *scp, unsigned long *uc_flags) -{ - if (!DPMIValidSelector(_scp_cs)) - return; - -#ifdef __x86_64__ - if (*uc_flags & UC_SIGCONTEXT_SS) { - /* - * On Linux 4.4 (possibly) and up, the kernel can fully restore - * SS and ESP, so we don't need any special tricks. To avoid confusion, - * force strict restore. (Some 4.1 versions support this as well but - * without the uc_flags bits. It's not trying to detect those kernels.) - */ - *uc_flags |= UC_STRICT_RESTORE_SS; - } else { -#if SIGRETURN_WA - if (!need_sr_wa) { - need_sr_wa = 1; - warn("Enabling sigreturn() work-around\n"); - } - dpmi_iret_setup(scp); -#else - error("Your kernel does not support UC_STRICT_RESTORE_SS and the " - "work-around in dosemu is not enabled.\n"); - dpmi_return(scp, DPMI_RET_EXIT); - leavedos_sig(-1); -#endif - } - - if (_scp_fs != getsegment(fs)) - loadregister(fs, _scp_fs); - if (_scp_gs != getsegment(gs)) - loadregister(gs, _scp_gs); - - loadregister(ds, _scp_ds); - loadregister(es, _scp_es); -#endif -} - -/* noinline is needed to prevent gcc from caching tls vars before - * calling to init_handler() */ -__attribute__((noinline)) -static void fixup_handler0(int sig, siginfo_t *si, void *uc) -{ - struct sigaction *sa = &sacts[sig]; - if (sa->sa_flags & SA_SIGINFO) { - sa->sa_sigaction(sig, si, uc); - } else { - typedef void (*hdlr_t)(int, siginfo_t *, ucontext_t *); - hdlr_t hdlr = (hdlr_t)sa->sa_handler; - hdlr(sig, si, uc); - } -} - -SIG_PROTO_PFX -static void fixup_handler(int sig, siginfo_t *si, void *uc) -{ - ucontext_t *uct = uc; - sigcontext_t *scp = &uct->uc_mcontext; - init_handler(scp, uct->uc_flags); - fixup_handler0(sig, si, uc); - deinit_handler(scp, &uct->uc_flags); -} - -static void fixupsig(int sig) -{ - struct sigaction sa; - sigaction(sig, NULL, &sa); - sacts[sig] = sa; - if (sa.sa_handler == SIG_DFL || sa.sa_handler == SIG_IGN) - return; - sa.sa_flags |= SA_ONSTACK | SA_SIGINFO; - if (block_all_sigs) - /* initially block all async signals. */ - sa.sa_mask = q_mask; - /* otherwise no additional blocking needed */ - sa.sa_sigaction = fixup_handler; - sigaction(sig, &sa, NULL); -} - -void unsetsig(int sig) -{ - sigaction(sig, &sacts[sig], NULL); -} - -static void newsetsig(int sig, void (*fun)(int sig, siginfo_t *si, void *uc)) -{ - struct sigaction sa; - - sa.sa_flags = SA_RESTART | SA_ONSTACK | SA_SIGINFO; -#ifdef __linux__ - if (kernel_version_code >= KERNEL_VERSION(2, 6, 14)) -#endif - sa.sa_flags |= SA_NODEFER; - if (block_all_sigs) - { - /* initially block all async signals. */ - sa.sa_mask = q_mask; - } - else - { - /* block all non-fatal async signals */ - sa.sa_mask = nonfatal_q_mask; - } - sa.sa_sigaction = fun; - sigaction(sig, &sa, &sacts[sig]); -} - -static int saved_fc; - -void signal_switch_to_dosemu(void) -{ - saved_fc = fault_cnt; - fault_cnt = 0; -} - -void signal_switch_to_dpmi(void) -{ - fault_cnt = saved_fc; -} - -void signal_return_to_dosemu(void) -{ -#if SIGALTSTACK_WA - if (need_sas_wa) - signal_sas_wa(); -#endif -} - -void signal_return_to_dpmi(void) -{ -} - -void signative_start(void) -{ - int sig; - - for (sig = 0; sig < SIGMAX; sig++) - if (sigismember(&q_mask, sig)) - fixupsig(sig); - /* call that after all non-fatal sigs set up */ - newsetsig(SIGILL, dosemu_fault); - newsetsig(SIGFPE, dosemu_fault); - newsetsig(SIGTRAP, dosemu_fault); - newsetsig(SIGBUS, dosemu_fault); - newsetsig(SIGSEGV, dosemu_fault); - newsetsig(DPMI_TMP_SIG, dpmi_switch_sa); // dont unset this on stop -} - -void signative_stop(void) -{ - int sig; - - for (sig = 0; sig < SIGMAX; sig++) - if (sigismember(&q_mask, sig)) - unsetsig(sig); - unsetsig(SIGILL); - unsetsig(SIGFPE); - unsetsig(SIGTRAP); - unsetsig(SIGBUS); - unsetsig(SIGSEGV); -} diff --git a/src/dosext/dpmi/doslib/Makefile b/src/dosext/dpmi/doslib/Makefile deleted file mode 100644 index b56736d..0000000 --- a/src/dosext/dpmi/doslib/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -top_builddir=../../../.. -include $(top_builddir)/Makefile.conf - -CFILES = dos.c - -include $(REALTOPDIR)/src/Makefile.common diff --git a/src/dosext/dpmi/doslib/dos.c b/src/dosext/dpmi/doslib/dos.c deleted file mode 100644 index c05e6a5..0000000 --- a/src/dosext/dpmi/doslib/dos.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2024 stsp - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "../emudpmi.h" -#include "../dpmisel.h" -#include "../dpmi_api.h" -#include "coopth.h" -#include "dos.h" - -static void call_msdos(cpuctx_t *scp) -{ - struct pmaddr_s pma = { - .offset = DPMI_SEL_OFF(DPMI_msdos), - .selector = dpmi_sel(), - }; - unsigned int *ssp = SEL_ADR(_ss, _esp); - *--ssp = _cs; - *--ssp = _eip; - _esp -= 8; - - _cs = pma.selector; - _eip = pma.offset; - coopth_sched(); -} - -unsigned _dos_open(const char *pathname, unsigned mode, int *handle) -{ - cpuctx_t *scp = dpmi_get_scp(); - cpuctx_t saved_scp = *scp; - int len = strlen(pathname) + 1; - __dpmi_paddr nm = dapi_alloc(len); - unsigned ret = 0; - - _eax = 0x3d00 | (mode & 0xff); - _ecx = 0; - _ds = nm.selector; - _edx = nm.offset32; - memcpy(SEL_ADR(_ds, _edx), pathname, len); - call_msdos(scp); - if (_eflags & CF) - ret = _eax; - else - *handle = _eax; - - dapi_free(nm); - *scp = saved_scp; - return ret; -} - -unsigned _dos_read(int handle, void *buffer, unsigned count, unsigned *numread) -{ - cpuctx_t *scp = dpmi_get_scp(); - cpuctx_t saved_scp = *scp; - __dpmi_paddr buf = dapi_alloc(count); - unsigned ret = 0; - - _eax = 0x3f00; - _ebx = handle; - _ecx = count; - _ds = buf.selector; - _edx = buf.offset32; - call_msdos(scp); - if (_eflags & CF) - ret = _eax; - else { - *numread = _eax; - memcpy(buffer, SEL_ADR(_ds, _edx), count); - } - - dapi_free(buf); - *scp = saved_scp; - return ret; -} - -unsigned _dos_write(int handle, const void *buffer, unsigned count, unsigned *numwrt) -{ - cpuctx_t *scp = dpmi_get_scp(); - cpuctx_t saved_scp = *scp; - __dpmi_paddr buf = dapi_alloc(count); - unsigned ret = 0; - - _eax = 0x4000; - _ebx = handle; - _ecx = count; - _ds = buf.selector; - _edx = buf.offset32; - memcpy(SEL_ADR(_ds, _edx), buffer, count); - call_msdos(scp); - if (_eflags & CF) - ret = _eax; - else - *numwrt = _eax; - - dapi_free(buf); - *scp = saved_scp; - return ret; -} - -unsigned long _dos_seek(int handle, unsigned long offset, int origin) -{ - cpuctx_t *scp = dpmi_get_scp(); - cpuctx_t saved_scp = *scp; - unsigned ret = 0; - - _eax = 0x4200 | (origin & 3); - _ebx = handle; - _ecx = offset >> 16; - _edx = offset & 0xffff; - call_msdos(scp); - if (_eflags & CF) - ret = -1; - else - ret = (_edx << 16) | (_eax & 0xffff); - - *scp = saved_scp; - return ret; -} - -int _dos_close(int handle) -{ - cpuctx_t *scp = dpmi_get_scp(); - cpuctx_t saved_scp = *scp; - unsigned ret = 0; - - _eax = 0x3e00; - _ebx = handle; - call_msdos(scp); - if (_eflags & CF) - ret = _eax; - - *scp = saved_scp; - return ret; -} - -int _dos_link_umb(int on) -{ - cpuctx_t *scp = dpmi_get_scp(); - cpuctx_t saved_scp = *scp; - unsigned ret = 0; - - _eax = 0x5803; - _ebx = on; - call_msdos(scp); - if (_eflags & CF) { - ret = _eax; - goto done; - } - _eax = 0x5801; - _ebx = on ? 0x80 : 0; - call_msdos(scp); - if (_eflags & CF) { - ret = _eax; - goto done; - } - -done: - *scp = saved_scp; - return ret; -} diff --git a/src/dosext/dpmi/doslib/dos.h b/src/dosext/dpmi/doslib/dos.h deleted file mode 100644 index 1f45221..0000000 --- a/src/dosext/dpmi/doslib/dos.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef DOS_H -#define DOS_H - -unsigned _dos_open(const char *pathname, unsigned mode, int *handle); -unsigned _dos_read(int handle, void *buffer, unsigned count, unsigned *numread); -unsigned _dos_write(int handle, const void *buffer, unsigned count, unsigned *numwrt); -unsigned long _dos_seek(int handle, unsigned long offset, int origin); -int _dos_close(int handle); - -int _dos_link_umb(int on); - -#endif diff --git a/src/dosext/dpmi/doslib/dpmi.h b/src/dosext/dpmi/doslib/dpmi.h deleted file mode 100644 index 37d0953..0000000 --- a/src/dosext/dpmi/doslib/dpmi.h +++ /dev/null @@ -1,149 +0,0 @@ -#include "../emudpmi.h" -#include "../djdpmi.h" -#include "../dpmi_api.h" - -#define DD(r, n, a, ...) \ -static inline r __##n a { \ - return _##n(dpmi_get_scp(), dpmi_is_32(), __VA_ARGS__); \ -} -#define DDv(r, n) \ -static inline r __##n(void) { \ - return _##n(dpmi_get_scp(), dpmi_is_32()); \ -} -#define vDD(n, a, ...) \ -static inline void __##n a { \ - _##n(dpmi_get_scp(), dpmi_is_32(), __VA_ARGS__); \ -} -#define vDDv(n) \ -static inline void __##n(void) { \ - _##n(dpmi_get_scp(), dpmi_is_32()); \ -} - -vDDv(dpmi_yield) - -DD(int, dpmi_allocate_ldt_descriptors, (int _count), _count); -DD(int, dpmi_free_ldt_descriptor, (int _descriptor), _descriptor); -DD(int, dpmi_segment_to_descriptor, (int _segment), _segment); -DDv(int, dpmi_get_selector_increment_value); -DD(int, dpmi_get_segment_base_address, (int _selector, ULONG *_addr), _selector, _addr); -DD(int, dpmi_set_segment_base_address, (int _selector, ULONG _address), _selector, _address); -DD(ULONG, dpmi_get_segment_limit, (int _selector), _selector); -DD(int, dpmi_set_segment_limit, (int _selector, ULONG _limit), _selector, _limit); -DD(int, dpmi_get_descriptor_access_rights, (int _selector), _selector); -DD(int, dpmi_set_descriptor_access_rights, (int _selector, int _rights), _selector, _rights); -DD(int, dpmi_create_alias_descriptor, (int _selector), _selector); -DD(int, dpmi_get_descriptor, (int _selector, void *_buffer), _selector, _buffer); -DD(int, dpmi_set_descriptor, (int _selector, void *_buffer), _selector, _buffer); -DD(int, dpmi_allocate_specific_ldt_descriptor, (int _selector), _selector); - -DD(int, dpmi_get_multiple_descriptors, (int _count, void *_buffer), _count, _buffer); /* DPMI 1.0 AX=000e */ -DD(int, dpmi_set_multiple_descriptors, (int _count, void *_buffer), _count, _buffer); - -DD(int, dpmi_allocate_dos_memory, (int _paragraphs, int *_ret_selector_or_max), - _paragraphs, _ret_selector_or_max); -DD(int, dpmi_free_dos_memory, (int _selector), _selector); -DD(int, dpmi_resize_dos_memory, (int _selector, int _newpara, int *_ret_max), - _selector, _newpara, _ret_max); - -DD(int, dpmi_get_real_mode_interrupt_vector, (int _vector, __dpmi_raddr *_address), - _vector, _address); -DD(int, dpmi_set_real_mode_interrupt_vector, (int _vector, __dpmi_raddr *_address), - _vector, _address); -DD(int, dpmi_get_processor_exception_handler_vector, (int _vector, __dpmi_paddr *_address), - _vector, _address); -DD(int, dpmi_set_processor_exception_handler_vector, (int _vector, __dpmi_paddr *_address), - _vector, _address); -DD(int, dpmi_get_protected_mode_interrupt_vector, (int _vector, __dpmi_paddr *_address), - _vector, _address); -DD(int, dpmi_set_protected_mode_interrupt_vector, (int _vector, __dpmi_paddr *_address), - _vector, _address); - -DD(int, dpmi_get_extended_exception_handler_vector_pm, (int _vector, __dpmi_paddr *_address), - _vector, _address); -DD(int, dpmi_get_extended_exception_handler_vector_rm, (int _vector, __dpmi_paddr *_address), - _vector, _address); -DD(int, dpmi_set_extended_exception_handler_vector_pm, (int _vector, __dpmi_paddr *_address), - _vector, _address); -DD(int, dpmi_set_extended_exception_handler_vector_rm, (int _vector, __dpmi_paddr *_address), - _vector, _address); - -DD(int, dpmi_simulate_real_mode_interrupt, (int _vector, __dpmi_regs *__regs), - _vector, __regs); -DD(int, dpmi_int, (int _vector, __dpmi_regs *__regs), - _vector, __regs); - -DD(int, dpmi_simulate_real_mode_procedure_retf, (__dpmi_regs *__regs), __regs); -DD(int, dpmi_simulate_real_mode_procedure_retf_stack, (__dpmi_regs *__regs, int stack_words_to_copy, const void *stack_data), - __regs, stack_words_to_copy, stack_data); -DD(int, dpmi_simulate_real_mode_procedure_iret, (__dpmi_regs *__regs), __regs); -DD(int, dpmi_allocate_real_mode_callback, (void (*_handler)(void), __dpmi_regs *__regs, __dpmi_raddr *_ret), - _handler, __regs, _ret); -DD(int, dpmi_free_real_mode_callback, (__dpmi_raddr *_addr), _addr); -DD(int, dpmi_get_state_save_restore_addr, (__dpmi_raddr *_rm, __dpmi_paddr *_pm), _rm, _pm); -DD(int, dpmi_get_raw_mode_switch_addr, (__dpmi_raddr *_rm, __dpmi_paddr *_pm), _rm, _pm); - -DD(int, dpmi_get_version, (__dpmi_version_ret *_ret), _ret); - -DD(int, dpmi_get_capabilities, (int *_flags, char *vendor_info), - _flags, vendor_info); - -DD(int, dpmi_get_free_memory_information, (__dpmi_free_mem_info *_info), _info); -DD(int, dpmi_allocate_memory, (__dpmi_meminfo *_info), _info); -DD(int, dpmi_free_memory, (ULONG _handle), _handle); -DD(int, dpmi_resize_memory, (__dpmi_meminfo *_info), _info); - -DD(int, dpmi_allocate_linear_memory, (__dpmi_meminfo *_info, int _commit), - _info, _commit); -DD(int, dpmi_resize_linear_memory, (__dpmi_meminfo *_info, int _commit), - _info, _commit); -DD(int, dpmi_get_page_attributes, (__dpmi_meminfo *_info, short *_buffer), - _info, _buffer); -DD(int, dpmi_set_page_attributes, (__dpmi_meminfo *_info, short *_buffer), - _info, _buffer); -DD(int, dpmi_map_device_in_memory_block, (__dpmi_meminfo *_info, ULONG _physaddr), - _info, _physaddr); -DD(int, dpmi_map_conventional_memory_in_memory_block, (__dpmi_meminfo *_info, ULONG _physaddr), - _info, _physaddr); -DD(int, dpmi_get_memory_block_size_and_base, (__dpmi_meminfo *_info), _info); -DD(int, dpmi_get_memory_information, (__dpmi_memory_info *_buffer), _buffer); - -DD(int, dpmi_lock_linear_region, (__dpmi_meminfo *_info), _info); -DD(int, dpmi_unlock_linear_region, (__dpmi_meminfo *_info), _info); -DD(int, dpmi_mark_real_mode_region_as_pageable, (__dpmi_meminfo *_info), _info); -DD(int, dpmi_relock_real_mode_region, (__dpmi_meminfo *_info), _info); -DD(int, dpmi_get_page_size, (ULONG *_size), _size); - -DD(int, dpmi_mark_page_as_demand_paging_candidate, (__dpmi_meminfo *_info), _info); -DD(int, dpmi_discard_page_contents, (__dpmi_meminfo *_info), _info); - -DD(int, dpmi_physical_address_mapping, (__dpmi_meminfo *_info), _info); -DD(int, dpmi_free_physical_address_mapping, (__dpmi_meminfo *_info), _info); - -DDv(int, dpmi_get_and_disable_virtual_interrupt_state); -DDv(int, dpmi_get_and_enable_virtual_interrupt_state); -DD(int, dpmi_get_and_set_virtual_interrupt_state, (int _old_state), _old_state); -DDv(int, dpmi_get_virtual_interrupt_state); - -DD(int, dpmi_get_vendor_specific_api_entry_point, (char *_id, __dpmi_paddr *_api), - _id, _api); - -DD(int, dpmi_set_debug_watchpoint, (__dpmi_meminfo *_info, int _type), _info, _type); -DD(int, dpmi_clear_debug_watchpoint, (ULONG _handle), _handle); -DD(int, dpmi_get_state_of_debug_watchpoint, (ULONG _handle, int *_status), - _handle, _status); -DD(int, dpmi_reset_debug_watchpoint, (ULONG _handle), _handle); - -DD(int, dpmi_install_resident_service_provider_callback, (__dpmi_callback_info *_info), - _info); -DD(int, dpmi_terminate_and_stay_resident, (int return_code, int paragraphs_to_keep), - return_code, paragraphs_to_keep); - -DD(int, dpmi_allocate_shared_memory, (__dpmi_shminfo *_info), _info); -DD(int, dpmi_free_shared_memory, (LONG _handle), _handle); -DD(int, dpmi_serialize_on_shared_memory, (ULONG _handle, int _flags), - _handle, _flags); -DD(int, dpmi_free_serialization_on_shared_memory, (ULONG _handle, int _flags), - _handle, _flags); - -DDv(int, dpmi_get_coprocessor_status); -DD(int, dpmi_set_coprocessor_emulation, (int _flags), _flags); diff --git a/src/dosext/dpmi/dpmi.c b/src/dosext/dpmi/dpmi.c index dfde4b6..028426d 100644 --- a/src/dosext/dpmi/dpmi.c +++ b/src/dosext/dpmi/dpmi.c @@ -13,15 +13,6 @@ * DPMI-1.0 and extensions by stsp. */ -/* -Currently missing DPMI-1.0 functions: - - 0x508 Map device, 1.0, OPTIONAL. Maps phys ram to existing linear region. - But we do not "move"/unmap hwram currently, as all phys ram - is initially mapped into a 4Gb space, so 85434678 should be - reverted. The extra complication is that this allows to map - devices at 1Mb, like video memory and roms. -*/ - #include #include #include @@ -40,6 +31,7 @@ extern long int __sysconf (int); /* for Debian eglibc 2.13-3 */ #include #include #include + #include "version.h" #include "emu.h" #include "dosemu_config.h" @@ -60,19 +52,13 @@ extern long int __sysconf (int); /* for Debian eglibc 2.13-3 */ #include "int.h" #include "port.h" #include "utilities.h" -#include "shlock.h" #include "mapping.h" +#include "vgaemu.h" #include "cpu-emu.h" #include "emu-ldt.h" -#include "instremu.h" #include "kvm.h" -#include "coopth.h" -#include "vtmr.h" -#include "dnative/dnative.h" +#include "dnative.h" #include "dpmi_api.h" -#ifdef USE_DJDEV64 -#include -#endif #define SHOWREGS 1 @@ -82,12 +68,7 @@ static int current_client; #define DPMI_CLIENT (DPMIclient[current_client]) #define PREV_DPMI_CLIENT (DPMIclient[current_client-1]) -#define DEFAULT_INT(i) (!DPMI_CLIENT.Interrupt_Table[i].selector || \ - (DPMI_CLIENT.Interrupt_Table[i].selector == dpmi_sel() && \ - DPMI_CLIENT.Interrupt_Table[i].offset < DPMI_SEL_OFF(DPMI_sel_end))) - #define _isset_IF() (!!(_eflags & IF)) -#define _isset_TF() (!!(_eflags & TF)) #define dpmi_cli() (_eflags &= ~IF) #define dpmi_sti() (_eflags |= IF) @@ -100,14 +81,7 @@ static int current_client; /* we trust that client doesn't hack us so we do not force IOPL/IF in ring0 */ #define dpmi_flags_from_stack_r0(flags) (flags) -static struct { - int user; - unsigned int cstd:1; -} seg_meta[MAX_SELECTORS]; -#define segment_get(x, f) seg_meta[x].f -#define segment_set(x, y, f) (seg_meta[x].f = (y)) -#define segment_user(x) segment_get(x, user) -#define segment_set_user(x, y) segment_set(x, y, user) +static SEGDESC Segments[MAX_SELECTORS]; static int in_dpmi;/* Set to 1 when running under DPMI */ static int dpmi_pm; static int in_dpmi_irq; @@ -118,19 +92,20 @@ static int dpmi_is_cli; static unsigned char *cli_blacklist[CLI_BLACKLIST_LEN]; static unsigned char *current_cli; static int cli_blacklisted = 0; +static int return_requested = 0; static int find_cli_in_blacklist(unsigned char *addr); static void add_cli_to_blacklist(unsigned char *addr); #ifdef USE_MHPDBG -static int dpmi_mhp_intxx_check(cpuctx_t *scp, int intno); +static int dpmi_mhp_intxx_check(sigcontext_t *scp, int intno); #endif -static int dpmi_fault1(cpuctx_t *scp); -static void do_dpmi_retf(cpuctx_t *scp, void * const sp); -static int prn_tid; +static int dpmi_fault1(sigcontext_t *scp); +static far_t s_i1c, s_i23, s_i24; + static struct RealModeCallStructure DPMI_rm_stack[DPMI_max_rec_rm_func]; static int DPMI_rm_procedure_running = 0; struct DPMIclient_struct { - cpuctx_t stack_frame; + sigcontext_t stack_frame; int is_32; dpmi_pm_block_root pm_block_root; unsigned short private_data_segment; @@ -150,33 +125,29 @@ struct DPMIclient_struct { unsigned short RSP_cs[DPMI_MAX_CLIENTS], RSP_ds[DPMI_MAX_CLIENTS]; int RSP_state, RSP_installed; int win3x_mode; - Bit8u imr[2]; - Bit8u orig_imr; + Bit8u imr; #define DF_PHARLAP 1 Bit32u feature_flags; uint16_t initial_psp; - uint16_t psp_sel; uint16_t int23_psp; - uint16_t envp; - - DPMI_INTDESC vtmr_prev; - DPMI_INTDESC vrtc_prev; - - int RSP_num; - - emu_fpstate saved_fpu_state; - Bit8u saved_ldt[0x10 * LDT_ENTRY_SIZE]; - far_t s_i1c, s_i23, s_i24; }; +struct RSPcall_s { + unsigned char data16[8]; + unsigned char code16[8]; + unsigned short ip; + unsigned short reserved; + unsigned char data32[8]; + unsigned char code32[8]; + unsigned int eip; +}; struct RSP_s { struct RSPcall_s call; dpmi_pm_block_root pm_block_root; - unsigned short lm_para_off; }; #define DPMI_max_rec_pm_func 16 -static cpuctx_t DPMI_pm_stack[DPMI_max_rec_pm_func]; +static sigcontext_t DPMI_pm_stack[DPMI_max_rec_pm_func]; static int DPMI_pm_procedure_running = 0; static struct DPMIclient_struct DPMIclient[DPMI_MAX_CLIENTS]; @@ -186,28 +157,21 @@ static dpmi_pm_block_root host_pm_block_root; static uint8_t _ldt_buffer[LDT_ENTRIES * LDT_ENTRY_SIZE]; uint8_t *ldt_buffer = _ldt_buffer; static unsigned short _dpmi_sel16, _dpmi_sel32; -unsigned short dpmi_sel(void) +unsigned short dpmi_sel() { return DPMI_CLIENT.is_32 ? _dpmi_sel32 : _dpmi_sel16; } -unsigned short dpmi_sel16(void) { return _dpmi_sel16; } -unsigned short dpmi_sel32(void) { return _dpmi_sel32; } +unsigned short dpmi_sel16() { return _dpmi_sel16; } +unsigned short dpmi_sel32() { return _dpmi_sel32; } static int RSP_num = 0; static struct RSP_s RSP_callbacks[DPMI_MAX_CLIENTS]; static int ext__thunk_16_32; // thunk extension -#ifdef USE_DJDEV64 -static const struct djdev64_ops *djdev64; -#endif -static void make_retf_frame(cpuctx_t *scp, void *sp, +static void make_retf_frame(sigcontext_t *scp, void *sp, uint32_t cs, uint32_t eip); -static void make_xretf_frame(cpuctx_t *scp, void *sp, +static void make_xretf_frame(sigcontext_t *scp, void *sp, uint32_t cs, uint32_t eip); -static void do_pm_int(cpuctx_t *scp, int i); -static void msdos_set_client(cpuctx_t *scp, int num); -static int rsp_get_para(void); - static uint32_t ldt_bitmap[LDT_ENTRIES / 32]; static int ldt_bitmap_cnt; typedef struct { @@ -216,19 +180,19 @@ typedef struct { } ldt_calldesc; static ldt_calldesc ldt_call16, ldt_call32; static int ldt_mon_on; -static void ldt_bitmap_update(unsigned short ldt_entry, int num) +static void ldt_bitmap_update(unsigned short selector, int num) { int i; if (!ldt_mon_on) return; for (i = 0; i < num; i++) { - int ent = ldt_entry + i; + int ent = (selector >> 3) + i; ldt_bitmap[ent >> 5] |= 1ULL << (ent & 0x1f); } ldt_bitmap_cnt += num; } -static void dpmi_ldt_call(cpuctx_t *scp); +static void dpmi_ldt_call(sigcontext_t *scp); static int dpmi_not_supported; @@ -248,10 +212,10 @@ static int dpmi_not_supported; } \ } -static void quit_dpmi(cpuctx_t *scp, unsigned short errcode, +static void quit_dpmi(sigcontext_t *scp, unsigned short errcode, int tsr, unsigned short tsr_para, int dos_exit); -#ifdef DNATIVE +#ifdef __linux__ #define modify_ldt dosemu_modify_ldt static inline int modify_ldt(int func, void *ptr, unsigned long bytecount) { @@ -259,89 +223,15 @@ static inline int modify_ldt(int func, void *ptr, unsigned long bytecount) } #endif -static void print_thr(void *arg) -{ - com_doswritecon(arg, strlen(arg)); -} - -FORMAT(printf, 1, 2) -static int p_direct_str(const char *fmt, ...) -{ - static char buf[1024]; - va_list args; - int i; - - va_start(args, fmt); - i = com_vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - if (in_dpmi_pm()) - fake_pm_int(); - coopth_start(prn_tid, buf); - return i; -} - -int p_direct_vstr(const char *fmt, va_list args) -{ - static char buf[1024]; - int i; - - i = com_vsnprintf(buf, sizeof(buf), fmt, args); - if (in_dpmi_pm()) - fake_pm_int(); - coopth_start(prn_tid, buf); - return i; -} - -int dpmi_is_32(void) -{ - return DPMI_CLIENT.is_32; -} - int dpmi_isset_IF(void) { assert(in_dpmi); return !!(get_eflags(&DPMI_CLIENT.stack_frame) & IF); } -static SEGDESC FillSegdesc(dosaddr_t base_addr, unsigned int limit, - unsigned char is_32, unsigned char type, unsigned char readonly, - unsigned char is_big, unsigned char seg_not_present, unsigned char useable) -{ - SEGDESC ret; - ret.base_addr = base_addr; - ret.limit = limit; - ret.type = type; - ret.is_32 = is_32; - ret.readonly = readonly; - ret.is_big = is_big; - ret.not_present = seg_not_present; - ret.useable = useable; - return ret; -} - -static SEGDESC Segments(unsigned short ldt_entry) -{ - unsigned int base_addr, limit; - int np, ro, type, ld; - unsigned int *lp = (unsigned int *)&ldt_buffer[ldt_entry * LDT_ENTRY_SIZE]; - - base_addr = (lp[1] & 0xFF000000) | ((lp[1] << 16) & 0x00FF0000) | - ((lp[0] >> 16) & 0x0000FFFF); - limit = (lp[1] & 0x000F0000) | (lp[0] & 0x0000FFFF); - type = (lp[1] >> 10) & 3; - ro = ((lp[1] >> 9) & 1) ^ 1; - np = ((lp[1] >> 15) & 1) ^ 1; - ld = (lp[1] >> 12) & 1; - if (!ld && !np) - D_printf("DPMI: invalid access type %x\n", lp[1] >> 8); - - return FillSegdesc(base_addr, limit, (lp[1] >> 22) & 1, type, ro, - (lp[1] >> 23) & 1, np, (lp[1] >> 20) & 1); -} - static void *SEL_ADR_LDT(unsigned short sel, unsigned int reg, int is_32) { - dosaddr_t p; + unsigned long p; if (is_32) p = GetSegmentBase(sel) + reg; else @@ -357,7 +247,7 @@ void *SEL_ADR(unsigned short sel, unsigned int reg) return (void *)(uintptr_t)reg; } /* LDT */ - return SEL_ADR_LDT(sel, reg, Segments(sel>>3).is_32); + return SEL_ADR_LDT(sel, reg, Segments[sel>>3].is_32); } void *SEL_ADR_CLNT(unsigned short sel, unsigned int reg, int is_32) @@ -370,58 +260,32 @@ void *SEL_ADR_CLNT(unsigned short sel, unsigned int reg, int is_32) return SEL_ADR_LDT(sel, reg, is_32); } -int get_ldt(void *buffer, int len) +int get_ldt(void *buffer) { -#ifdef DNATIVE +#ifdef __linux__ int i, ret; struct ldt_descriptor *dp; if (config.cpu_vm_dpmi != CPUVM_NATIVE) - return emu_modify_ldt(LDT_READ, buffer, len); - ret = modify_ldt(LDT_READ, buffer, len); + return emu_modify_ldt(0, buffer, LDT_ENTRIES * LDT_ENTRY_SIZE); + ret = modify_ldt(0, buffer, LDT_ENTRIES * LDT_ENTRY_SIZE); /* do emu_modify_ldt even if modify_ldt fails, so cpu_vm_dpmi fallbacks can still work */ - if (ret != len) - return emu_modify_ldt(LDT_READ, buffer, len); - for (i = 0, dp = buffer; i < len / LDT_ENTRY_SIZE; i++, dp++) { + if (ret != LDT_ENTRIES * LDT_ENTRY_SIZE) + return emu_modify_ldt(0, buffer, LDT_ENTRIES * LDT_ENTRY_SIZE); + for (i = 0, dp = buffer; i < LDT_ENTRIES; i++, dp++) { unsigned int base_addr = DT_BASE(dp); - if ((base_addr || DT_LIMIT(dp)) && (DT_FLAGS(dp) & 0x80/*P bit*/)) { + if (base_addr || DT_LIMIT(dp)) { base_addr -= (uintptr_t)mem_base; MKBASE(dp, base_addr); } } return ret; #else - return emu_modify_ldt(LDT_READ, buffer, len); + return emu_modify_ldt(0, buffer, LDT_ENTRIES * LDT_ENTRY_SIZE); #endif } -static int put_ldt(struct user_desc *ldt_info) -{ - int __retval; - -#ifdef DNATIVE - if (config.cpu_vm_dpmi == CPUVM_NATIVE) - { - /* NOTE: the real LDT in kernel space uses the real addresses, but - the LDT we emulate, and DOS applications work with, - has all base addresses with respect to mem_base */ - if (!ldt_info->seg_not_present) { - ldt_info->base_addr += (uintptr_t)mem_base; - __retval = modify_ldt(LDT_WRITE, ldt_info, sizeof(*ldt_info)); - ldt_info->base_addr -= (uintptr_t)mem_base; - } else { - __retval = modify_ldt(LDT_WRITE, ldt_info, sizeof(*ldt_info)); - } - if (__retval) - return __retval; - } -#endif - /* this also updates our ldt_buffer */ - __retval = emu_modify_ldt(LDT_WRITE, ldt_info, sizeof(*ldt_info)); - return __retval; -} - -static int set_ldt_entry(int entry, dosaddr_t base, unsigned int limit, +static int set_ldt_entry(int entry, unsigned long base, unsigned int limit, int seg_32bit_flag, int contents, int read_only_flag, int limit_in_pages_flag, int seg_not_present, int useable) { @@ -431,6 +295,7 @@ static int set_ldt_entry(int entry, dosaddr_t base, unsigned int limit, */ struct user_desc ldt_info = {}; + int __retval; ldt_info.entry_number = entry; ldt_info.base_addr = base; ldt_info.limit = limit; @@ -440,7 +305,26 @@ static int set_ldt_entry(int entry, dosaddr_t base, unsigned int limit, ldt_info.limit_in_pages = limit_in_pages_flag; ldt_info.seg_not_present = seg_not_present; ldt_info.useable = useable; - return put_ldt(&ldt_info); +#ifdef __linux__ + if (config.cpu_vm_dpmi == CPUVM_NATIVE) + { + /* NOTE: the real LDT in kernel space uses the real addresses, but + the LDT we emulate, and DOS applications work with, + has all base addresses with respect to mem_base */ + if (base || limit) { + ldt_info.base_addr += (uintptr_t)mem_base; + __retval = modify_ldt(LDT_WRITE, &ldt_info, sizeof(ldt_info)); + ldt_info.base_addr -= (uintptr_t)mem_base; + } else { + __retval = modify_ldt(LDT_WRITE, &ldt_info, sizeof(ldt_info)); + } + if (__retval) + return __retval; + } +#endif + + __retval = emu_modify_ldt(LDT_WRITE, &ldt_info, sizeof(ldt_info)); + return __retval; } static void _print_dt(char *buffer, int nsel, int isldt) /* stolen from WINE */ @@ -471,7 +355,7 @@ static void _print_dt(char *buffer, int nsel, int isldt) /* stolen from WINE */ base_addr |= (*lp & 0xFF000000) | ((*lp << 16) & 0x00FF0000); limit |= (*lp & 0x000F0000); type = (*lp >> 8) & 15; - if ((base_addr > 0) || (limit > 0 ) || segment_user(i)) { + if ((base_addr > 0) || (limit > 0 ) || Segments[i].used) { if (*lp & 0x1000) { D_printf("Entry 0x%04x: Base %08x, Limit %05x, Type %d (desc %#x)\n", i, base_addr, limit, (type&7), (i<<3)|(isldt?7:0)); @@ -509,7 +393,7 @@ static void _print_dt(char *buffer, int nsel, int isldt) /* stolen from WINE */ lp2 = (unsigned int *) &ldt_buffer[i*LDT_ENTRY_SIZE]; D_printf(" cache: %08x %08x\n", *(lp2+1), *lp2); D_printf(" seg: Base %08x, Limit %05x, Type %d, Big %d\n", - Segments(i).base_addr, Segments(i).limit, Segments(i).type, Segments(i).is_big); + Segments[i].base_addr, Segments[i].limit, Segments[i].type, Segments[i].is_big); } } } @@ -519,24 +403,12 @@ static void print_ldt(void) { static char buffer[0x10000]; - if (get_ldt(buffer, LDT_ENTRIES * LDT_ENTRY_SIZE) < 0) + if (get_ldt(buffer) < 0) leavedos(0x544c); _print_dt(buffer, MAX_SELECTORS, 1); } -static void leave_backend(int be, int pm) -{ - if (be == CPUVM_KVM) - kvm_leave(pm); -} - -static void enter_backend(int be, int pm) -{ - if (be == CPUVM_KVM) - kvm_enter(pm); -} - static void dpmi_set_pm(int pm) { assert(pm <= 1); @@ -546,10 +418,6 @@ static void dpmi_set_pm(int pm) return; } dpmi_pm = pm; - if (config.cpu_vm != config.cpu_vm_dpmi) { - leave_backend(pm ? config.cpu_vm : config.cpu_vm_dpmi, !pm); - enter_backend(!pm ? config.cpu_vm : config.cpu_vm_dpmi, pm); - } } static dpmi_pm_block *lookup_pm_blocks_by_addr(dosaddr_t addr) @@ -587,7 +455,7 @@ int dpmi_is_valid_range(dosaddr_t addr, int len) return 0; for (i = (addr - blk->base) >> PAGE_SHIFT; i < (PAGE_ALIGN(addr + len - 1) - blk->base) >> PAGE_SHIFT; i++) - if ((blk->attrs[i] & 1) != 1) + if ((blk->attrs[i] & 7) != 1) return 0; return 1; } @@ -606,23 +474,17 @@ int dpmi_write_access(dosaddr_t addr) /* client_esp return the proper value of client\'s esp, if scp != 0, */ /* get esp from scp, otherwise get esp from dpmi_stack_frame */ -static uint32_t client_esp(cpuctx_t *scp) +static inline unsigned long client_esp(sigcontext_t *scp) { - if( Segments(_ss >> 3).is_32) + if (scp == NULL) + scp = &DPMI_CLIENT.stack_frame; + if( Segments[_ss >> 3].is_32) return _esp; else return (_esp)&0xffff; } -static uint32_t client_eip(cpuctx_t *scp) -{ - if( Segments(_cs >> 3).is_32) - return _eip; - else - return (_eip)&0xffff; -} - -static int do_dpmi_switch(cpuctx_t *scp) +static int do_dpmi_switch(sigcontext_t *scp) { int ret; @@ -649,42 +511,16 @@ static int do_dpmi_switch(cpuctx_t *scp) return ret; } -static void dpmi_pic_run(cpuctx_t *scp) -{ - int inum; - - if (!_isset_IF() || !pic_pending()) - return; - inum = pic_get_inum(); - do_pm_int(scp, inum); -} - static int _dpmi_control(void) { int ret; - cpuctx_t *scp = &DPMI_CLIENT.stack_frame; + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; do { -#ifdef USE_MHPDBG - if (mhpdbg.active) - mhp_debug(DBG_POLL, 0, 0); -#endif - dpmi_pic_run(scp); - if (!in_dpmi_pm()) { - ret = DPMI_RET_DOSEMU; - break; - } -#ifdef USE_MHPDBG - if (mhpdbg.active) - mhp_debug(DBG_PRE_VM86, 0, 0); -#endif ret = do_dpmi_switch(scp); - if (ret == DPMI_RET_EXIT) - break; if (ret == DPMI_RET_FAULT) { ret = dpmi_fault1(scp); - if (in_dpmi_pm()) - scp = &DPMI_CLIENT.stack_frame; // update, could change + scp = &DPMI_CLIENT.stack_frame; // update, could change } #if 0 /* allow dynamically switch from native to something else */ @@ -700,15 +536,16 @@ static int _dpmi_control(void) break; } #endif - - if (!in_dpmi_pm()) { - ret = DPMI_RET_DOSEMU; - } else if (ret == DPMI_RET_CLIENT) { + if (ret == DPMI_RET_CLIENT) { uncache_time(); hardware_run(); - handle_signals(); - if (!in_dpmi_pm()) - ret = DPMI_RET_DOSEMU; + } + + if (!in_dpmi_pm() || (ret == DPMI_RET_CLIENT && + ((_isset_IF() && pic_pending()) || return_requested))) { + return_requested = 0; + ret = DPMI_RET_DOSEMU; + break; } } while (ret == DPMI_RET_CLIENT); if (debug_level('M') >= 8) @@ -735,12 +572,12 @@ void dpmi_get_entry_point(void) D_printf("Request for DPMI entry\n"); if (dpmi_not_supported) { - com_printf("DPMI is not supported on your linux kernel!\n"); + p_dos_str("DPMI is not supported on your linux kernel!\n"); CARRY; return; } if (!config.dpmi) { - com_printf("DPMI disabled, please check the dosemu config and log\n"); + p_dos_str("DPMI disabled, please check the dosemu config and log\n"); CARRY; return; } @@ -753,14 +590,14 @@ void dpmi_get_entry_point(void) /* Version 0.9 */ HI(dx) = DPMI_VERSION; - LO(dx) = DPMI_MINOR_VERSION; + LO(dx) = DPMI_DRIVER_VERSION; /* Entry Address for DPMI */ SREG(es) = DPMI_SEG; REG(edi) = DPMI_OFF; /* private data */ - LWORD(esi) = DPMI_private_paragraphs + rsp_get_para(); + LWORD(esi) = DPMI_private_paragraphs + msdos_get_lowmem_size(); D_printf("DPMI entry returned, needs %#x lowmem paragraphs (%i)\n", LWORD(esi), LWORD(esi) << 4); @@ -771,18 +608,28 @@ int SetSelector(unsigned short selector, dosaddr_t base_addr, unsigned int limit unsigned char is_big, unsigned char seg_not_present, unsigned char useable) { int ldt_entry = selector >> 3; - if (!DPMIValidSelector(selector) || !segment_user(ldt_entry)) { + if (!DPMIValidSelector(selector)) { D_printf("ERROR: Invalid selector passed to SetSelector(): %#x\n", selector); return -1; } - if (set_ldt_entry(ldt_entry, base_addr, limit, is_32, type, readonly, is_big, + if (Segments[ldt_entry].used) { + if (set_ldt_entry(ldt_entry, base_addr, limit, is_32, type, readonly, is_big, seg_not_present, useable)) { - D_printf("DPMI: set_ldt_entry() failed\n"); - return -1; - } - D_printf("DPMI: SetSelector: 0x%04x base=0x%x " + D_printf("DPMI: set_ldt_entry() failed\n"); + return -1; + } + D_printf("DPMI: SetSelector: 0x%04x base=0x%x " "limit=0x%x big=%hhi type=%hhi np=%hhi\n", selector, base_addr, limit, is_big, type, seg_not_present); + } + Segments[ldt_entry].base_addr = base_addr; + Segments[ldt_entry].limit = limit; + Segments[ldt_entry].type = type; + Segments[ldt_entry].is_32 = is_32; + Segments[ldt_entry].readonly = readonly; + Segments[ldt_entry].is_big = is_big; + Segments[ldt_entry].not_present = seg_not_present; + Segments[ldt_entry].useable = useable; return 0; } @@ -791,7 +638,7 @@ static int SystemSelector(unsigned int selector) if ((selector >> 3) >= MAX_SELECTORS) return 0; /* 0xff refers to dpmi_sel16 & dpmi_sel32 */ - return !DPMIValidSelector(selector) || segment_user(selector >> 3) == 0xff; + return !DPMIValidSelector(selector) || Segments[selector >> 3].used == 0xff; } static unsigned short allocate_descriptors_at(unsigned short selector, @@ -805,17 +652,17 @@ static unsigned short allocate_descriptors_at(unsigned short selector, return 0; } for (i=0;i> 3; - segment_set(ldt_entry, 1, cstd); - ldt_bitmap_update(ldt_entry, 1); + Segments[ldt_entry].cstd = 1; + ldt_bitmap_update(selector, 1); return selector; } @@ -965,13 +807,12 @@ int ValidAndUsedSelector(unsigned int selector) { if ((selector >> 3) >= MAX_SELECTORS) return 0; - return DPMIValidSelector(selector) && segment_user(selector >> 3); + return DPMIValidSelector(selector) && Segments[selector >> 3].used; } static inline int check_verr(unsigned short selector) { - int ret = 0; -#ifdef DNATIVE + int ret; asm volatile( "verrw %%ax\n" "jz 1f\n" @@ -979,7 +820,6 @@ static inline int check_verr(unsigned short selector) "1:\n" : "=a"(ret) : "a"(selector)); -#endif return ret; } @@ -1005,7 +845,7 @@ THEN Clear descriptor valid bit; FI; */ -static inline int CheckDataSelector(cpuctx_t *scp, +static inline int CheckDataSelector(sigcontext_t *scp, unsigned short selector, char letter, int in_dosemu) { @@ -1013,11 +853,11 @@ static inline int CheckDataSelector(cpuctx_t *scp, apparently fs=3 and gs=3 show up sometimes when running in x86-64 */ if (selector > 3 && (!ValidAndUsedSelector(selector) - || Segments(selector >> 3).not_present)) { + || Segments[selector >> 3].not_present)) { if (in_dosemu) { error("%cS selector invalid: 0x%04X, type=%x np=%i\n", - letter, selector, Segments(selector >> 3).type, - Segments(selector >> 3).not_present); + letter, selector, Segments[selector >> 3].type, + Segments[selector >> 3].not_present); D_printf("%s", DPMI_show_state(scp)); #if 1 /* Some buggy programs load the arbitrary LDT or even GDT @@ -1033,7 +873,7 @@ static inline int CheckDataSelector(cpuctx_t *scp, return 1; } -int CheckSelectors(cpuctx_t *scp, int in_dosemu) +int CheckSelectors(sigcontext_t *scp, int in_dosemu) { #ifdef TRACE_DPMI if (debug_level('t') == 0 || _trapno!=1) @@ -1046,11 +886,11 @@ int CheckSelectors(cpuctx_t *scp, int in_dosemu) Segment must be present ELSE # NP(selector); Instruction pointer must be within code-segment limit ELSE #GP(0); */ - if (!ValidAndUsedSelector(_cs) || Segments(_cs >> 3).not_present || - Segments(_cs >> 3).type != MODIFY_LDT_CONTENTS_CODE) { + if (!ValidAndUsedSelector(_cs) || Segments[_cs >> 3].not_present || + Segments[_cs >> 3].type != MODIFY_LDT_CONTENTS_CODE) { if (in_dosemu) { error("CS selector invalid: 0x%04X, type=%x np=%i\n", - _cs, Segments(_cs >> 3).type, Segments(_cs >> 3).not_present); + _cs, Segments[_cs >> 3].type, Segments[_cs >> 3].not_present); D_printf("%s", DPMI_show_state(scp)); } return 0; @@ -1058,7 +898,7 @@ int CheckSelectors(cpuctx_t *scp, int in_dosemu) if (_eip > GetSegmentLimit(_cs)) { if (in_dosemu) { error("IP outside CS limit: ip=%#x, cs=%#x, lim=%#x, 32=%i\n", - _eip, _cs, GetSegmentLimit(_cs), Segments(_cs >> 3).is_32); + _eip, _cs, GetSegmentLimit(_cs), Segments[_cs >> 3].is_32); D_printf("%s", DPMI_show_state(scp)); } return 0; @@ -1080,12 +920,12 @@ AR byte must indicate a writable data segment else #GP(selector); FI; */ if (!ValidAndUsedSelector(_ss) || ((_ss & 3) != 3) || - Segments(_ss >> 3).readonly || Segments(_ss >> 3).not_present || - (Segments(_ss >> 3).type != MODIFY_LDT_CONTENTS_STACK && - Segments(_ss >> 3).type != MODIFY_LDT_CONTENTS_DATA)) { + Segments[_ss >> 3].readonly || Segments[_ss >> 3].not_present || + (Segments[_ss >> 3].type != MODIFY_LDT_CONTENTS_STACK && + Segments[_ss >> 3].type != MODIFY_LDT_CONTENTS_DATA)) { if (in_dosemu) { error("SS selector invalid: 0x%04X, type=%x np=%i\n", - _ss, Segments(_ss >> 3).type, Segments(_ss >> 3).not_present); + _ss, Segments[_ss >> 3].type, Segments[_ss >> 3].not_present); D_printf("%s", DPMI_show_state(scp)); } return 0; @@ -1102,7 +942,7 @@ unsigned int GetSegmentBase(unsigned short selector) { if (!ValidAndUsedSelector(selector)) return 0; - return Segments(selector >> 3).base_addr; + return Segments[selector >> 3].base_addr; } unsigned int GetSegmentLimit(unsigned short selector) @@ -1110,66 +950,57 @@ unsigned int GetSegmentLimit(unsigned short selector) unsigned int limit; if (!ValidAndUsedSelector(selector)) return 0; - limit = Segments(selector >> 3).limit; - if (Segments(selector >> 3).is_big) + limit = Segments[selector >> 3].limit; + if (Segments[selector >> 3].is_big) limit = (limit << 12) | 0xfff; return limit; } -unsigned int GetSegmentType(unsigned short selector) -{ - if (!ValidAndUsedSelector(selector)) - return 0; - return Segments(selector >> 3).type; -} - -int SetSegmentBaseAddress(unsigned short selector, dosaddr_t baseaddr) +int SetSegmentBaseAddress(unsigned short selector, unsigned long baseaddr) { unsigned short ldt_entry = selector >> 3; int ret; - D_printf("DPMI: SetSegmentBaseAddress[0x%04x;0x%04x] 0x%08x\n", ldt_entry, selector, baseaddr); + D_printf("DPMI: SetSegmentBaseAddress[0x%04x;0x%04x] 0x%08lx\n", ldt_entry, selector, baseaddr); if (!ValidAndUsedSelector((ldt_entry << 3) | 7)) return -1; - ret = set_ldt_entry(ldt_entry, baseaddr, - Segments(ldt_entry).limit, Segments(ldt_entry).is_32, - Segments(ldt_entry).type, Segments(ldt_entry).readonly, - Segments(ldt_entry).is_big, - Segments(ldt_entry).not_present, Segments(ldt_entry).useable); - ldt_bitmap_update(ldt_entry, 1); + Segments[ldt_entry].base_addr = baseaddr; + ret = set_ldt_entry(ldt_entry , Segments[ldt_entry].base_addr, + Segments[ldt_entry].limit, Segments[ldt_entry].is_32, + Segments[ldt_entry].type, Segments[ldt_entry].readonly, + Segments[ldt_entry].is_big, + Segments[ldt_entry].not_present, Segments[ldt_entry].useable); + ldt_bitmap_update(selector, 1); return ret; } int SetSegmentLimit(unsigned short selector, unsigned int limit) { unsigned short ldt_entry = selector >> 3; - unsigned lim; - int is_big, ret; + int ret; D_printf("DPMI: SetSegmentLimit[0x%04x;0x%04x] 0x%08x\n", ldt_entry, selector, limit); if (!ValidAndUsedSelector((ldt_entry << 3) | 7)) return -1; if (limit > 0x0fffff) { /* "Segment limits greater than 1M must have the low 12 bits set" */ if (~limit & 0xfff) return -1; - lim = (limit>>12) & 0xfffff; - is_big = 1; + Segments[ldt_entry].limit = (limit>>12) & 0xfffff; + Segments[ldt_entry].is_big = 1; } else { - lim = limit; - is_big = 0; + Segments[ldt_entry].limit = limit; + Segments[ldt_entry].is_big = 0; } - ret = set_ldt_entry(ldt_entry , Segments(ldt_entry).base_addr, - lim, Segments(ldt_entry).is_32, - Segments(ldt_entry).type, Segments(ldt_entry).readonly, - is_big, - Segments(ldt_entry).not_present, Segments(ldt_entry).useable); - ldt_bitmap_update(ldt_entry, 1); + ret = set_ldt_entry(ldt_entry , Segments[ldt_entry].base_addr, + Segments[ldt_entry].limit, Segments[ldt_entry].is_32, + Segments[ldt_entry].type, Segments[ldt_entry].readonly, + Segments[ldt_entry].is_big, + Segments[ldt_entry].not_present, Segments[ldt_entry].useable); + ldt_bitmap_update(selector, 1); return ret; } int SetDescriptorAccessRights(unsigned short selector, unsigned short acc_rights) { unsigned short ldt_entry = selector >> 3; - unsigned type; - int readonly, is_32, is_big, not_present, useable; int ret; D_printf("DPMI: SetDescriptorAccessRights[0x%04x;0x%04x] 0x%04x\n", ldt_entry, selector, acc_rights); if (!ValidAndUsedSelector((ldt_entry << 3) | 7)) @@ -1178,51 +1009,79 @@ int SetDescriptorAccessRights(unsigned short selector, unsigned short acc_rights if ((acc_rights & 0x70) != 0x70) return -2; /* invalid value 8021 */ - type = (acc_rights >> 2) & 3; - is_32 = (acc_rights >> 14) & 1; - is_big = (acc_rights >> 15) & 1; - readonly = ((acc_rights >> 1) & 1) ? 0 : 1; - not_present = ((acc_rights >> 7) & 1) ? 0 : 1; - useable = (acc_rights >> 12) & 1; - ret = set_ldt_entry(ldt_entry , Segments(ldt_entry).base_addr, Segments(ldt_entry).limit, - is_32, type, readonly, is_big, not_present, useable); - ldt_bitmap_update(ldt_entry, 1); + Segments[ldt_entry].type = (acc_rights >> 2) & 3; + Segments[ldt_entry].is_32 = (acc_rights >> 14) & 1; + Segments[ldt_entry].is_big = (acc_rights >> 15) & 1; + Segments[ldt_entry].readonly = ((acc_rights >> 1) & 1) ? 0 : 1; + Segments[ldt_entry].not_present = ((acc_rights >> 7) & 1) ? 0 : 1; + Segments[ldt_entry].useable = (acc_rights >> 12) & 1; + ret = set_ldt_entry(ldt_entry , Segments[ldt_entry].base_addr, Segments[ldt_entry].limit, + Segments[ldt_entry].is_32, Segments[ldt_entry].type, + Segments[ldt_entry].readonly, Segments[ldt_entry].is_big, + Segments[ldt_entry].not_present, Segments[ldt_entry].useable); + ldt_bitmap_update(selector, 1); return ret; } -static int GetDescriptorAccessRights(unsigned short selector, - unsigned short *acc_rights) -{ - unsigned short ldt_entry = selector >> 3; - if (!ValidAndUsedSelector(selector)) - return -1; /* invalid selector 8022 */ - get_ldt(ldt_buffer, (ldt_entry + 1) * LDT_ENTRY_SIZE); // update the buffer - memcpy(acc_rights, &ldt_buffer[(selector & 0xfff8) + 5], 2); - return 0; -} - unsigned short CreateAliasDescriptor(unsigned short selector) { - uint16_t ds_selector; - uint16_t cs_ldt= selector >> 3; + us ds_selector; + us cs_ldt= selector >> 3; ds_selector = AllocateDescriptors(1); - if (SetSelector(ds_selector, Segments(cs_ldt).base_addr, Segments(cs_ldt).limit, - Segments(cs_ldt).is_32, MODIFY_LDT_CONTENTS_DATA, - Segments(cs_ldt).readonly, Segments(cs_ldt).is_big, - Segments(cs_ldt).not_present, Segments(cs_ldt).useable)) + if (SetSelector(ds_selector, Segments[cs_ldt].base_addr, Segments[cs_ldt].limit, + Segments[cs_ldt].is_32, MODIFY_LDT_CONTENTS_DATA, + Segments[cs_ldt].readonly, Segments[cs_ldt].is_big, + Segments[cs_ldt].not_present, Segments[cs_ldt].useable)) return 0; - ldt_bitmap_update(ds_selector >> 3, 1); + ldt_bitmap_update(selector, 1); return ds_selector; } -int GetDescriptor(uint16_t selector, unsigned int *lp) +static inline int do_LAR(us selector) { - unsigned short ldt_entry = selector >> 3; + int ret; +#ifdef X86_EMULATOR + if (config.cpu_vm_dpmi != CPUVM_NATIVE) + return emu_do_LAR(selector); + else +#endif + asm volatile( + "larw %%ax,%%ax\n" + "jz 1f\n" + "xorl %%eax,%%eax\n" + "1: shrl $8,%%eax\n" + : "=a"(ret) + : "a"(selector) + ); + return ret; +} + +int GetDescriptor(us selector, unsigned int *lp) +{ + int typebyte; + unsigned char *type_ptr; if (!ValidAndUsedSelector(selector)) return -1; /* invalid value 8021 */ - get_ldt(ldt_buffer, (ldt_entry + 1) * LDT_ENTRY_SIZE); // update the buffer memcpy((unsigned char *)lp, &ldt_buffer[selector & 0xfff8], LDT_ENTRY_SIZE); + /* DANG_BEGIN_REMARK + * Hopefully the below LAR can serve as a replacement for the KERNEL_LDT, + * which we are abandoning now. Especially the 'accessed-bit' will get + * updated in the ldt-cache with the code below. + * Most DPMI-clients fortunately _are_ using LAR also to get this info, + * however, some do not. Some of those which do _not_, at least use the + * DPMI-GetDescriptor function, so this may solve the problem. + * (Hans Lermen, July 1996) + * DANG_END_REMARK + */ + if (!Segments[selector >> 3].not_present) { + typebyte = do_LAR(selector); + type_ptr = ((unsigned char *)lp) + 5; + if (typebyte != *type_ptr) { + D_printf("DPMI: change type only in local selector\n"); + *type_ptr=typebyte; + } + } D_printf("DPMI: GetDescriptor[0x%04x;0x%04x]: 0x%08x%08x\n", selector >> 3, selector, lp[1], lp[0]); return 0; @@ -1249,86 +1108,75 @@ int SetDescriptor(unsigned short selector, unsigned int *lp) ret = SetSelector(selector, base_addr, limit, (lp[1] >> 22) & 1, type, ro, (lp[1] >> 23) & 1, np, (lp[1] >> 20) & 1); - ldt_bitmap_update(selector >> 3, 1); + ldt_bitmap_update(selector, 1); return ret; } void GetFreeMemoryInformation(unsigned int *lp) { - // Largest available free block in bytes - /*00h*/ lp[0] = dpmi_largest_memory_block(); - // Maximum unlocked page allocation in pages + /*00h*/ lp[0] = dpmi_free_memory(); /*04h*/ lp[1] = dpmi_free_memory()/DPMI_page_size; - // Maximum locked page allocation in pages /*08h*/ lp[2] = dpmi_free_memory()/DPMI_page_size; - // Linear address space size in pages - /*0ch*/ lp[3] = dpmi_lin_mem_size()/DPMI_page_size; - // Total number of unlocked pages + /*0ch*/ lp[3] = dpmi_lin_mem_rsv()/DPMI_page_size; // not accurate /*10h*/ lp[4] = dpmi_total_memory/DPMI_page_size; - // Total number of free pages /*14h*/ lp[5] = dpmi_free_memory()/DPMI_page_size; - // Total number of physical pages /*18h*/ lp[6] = dpmi_total_memory/DPMI_page_size; - // Free linear address space in pages /*1ch*/ lp[7] = dpmi_lin_mem_free()/DPMI_page_size; #if 0 - // Size of paging file/partition in pages /*20h*/ lp[8] = dpmi_total_memory/DPMI_page_size; #else /* report no swap, or the locked/unlocked * amounts will have to be adjusted */ /*20h*/ lp[8] = 0; #endif - // Reserved, all 0xc bytes set to 0FFH - /*24h*/ memset(&lp[9], 0xff, 0xc); + /*24h*/ lp[9] = 0xffffffff; + /*28h*/ lp[0xa] = 0xffffffff; + /*2ch*/ lp[0xb] = 0xffffffff; } -static void GetFreeMemoryInformationExt(unsigned int *lp) +void copy_to_dpmi(sigcontext_t *d, sigcontext_t *s) { - // Total allocated bytes of physical memory controlled by DPMI host - /*00h*/ lp[0] = dpmi_alloced_memory(); - // Total allocated bytes of virtual memory controlled by DPMI host - /*04h*/ lp[1] = dpmi_alloced_memory(); - // Total available bytes of virtual memory controlled by DPMI host - /*08h*/ lp[2] = dpmi_free_memory(); - // Total allocated bytes of virtual memory for this virtual machine - /*0ch*/ lp[3] = dpmi_alloced_memory(); - // Total available bytes of virtual memory for this virtual machine - /*10h*/ lp[4] = dpmi_free_memory(); - // Total allocated bytes of virtual memory for this client - /*14h*/ lp[5] = dpmi_alloced_memory(); - // Total available bytes of virtual memory for this client - /*18h*/ lp[6] = dpmi_free_memory(); - // Total locked bytes of memory for this client - /*1ch*/ lp[7] = 0; - // Maximum locked bytes of memory for this client - /*20h*/ lp[8] = dpmi_total_memory; - // Highest linear address available to this client - /*24h*/ lp[9] = config.dpmi_base ? config.dpmi_base - 1 : 0; - // Size in bytes of largest available free memory block - /*28h*/ lp[0xa] = dpmi_largest_memory_block(); - // Size of minimum allocation unit in bytes - /*2ch*/ lp[0xb] = DPMI_page_size; - // Size of the allocation alignment unit in bytes - /*30h*/ lp[0xc] = DPMI_page_size; - // Reserved, currently zero (0x4c bytes) - /*34h*/ memset(&lp[0xd], 0, 0x4c); + *d = *s; } -static void save_context_nofpu(cpuctx_t *d, cpuctx_t *s) +void copy_context(sigcontext_t *d, sigcontext_t *s) { - memcpy(d, s, REGS_SIZE); +#ifdef __linux__ + fpregset_t fptr = d->fpregs; +#endif + *d = *s; +#ifdef __linux__ + if (fptr == s->fpregs) + dosemu_error("Copy FPU context between the same locations?\n"); + *fptr = *s->fpregs; + d->fpregs = fptr; +#endif } -static void restore_context_nofpu(cpuctx_t *d, cpuctx_t *s) +void copy_to_emu(sigcontext_t *d, sigcontext_t *s) { - memcpy(d, s, REGS_SIZE); // copy w/o fpstate + copy_context(d, s); } -static void *enter_lpms(cpuctx_t *scp) +static void save_context_nofpu(sigcontext_t *d, sigcontext_t *s) +{ + *d = *s; + assert(d->fpregs); + d->fpregs = NULL; +} + +static void restore_context_nofpu(sigcontext_t *d, sigcontext_t *s) +{ + fpregset_t fptr = d->fpregs; + assert(fptr && !s->fpregs); + *d = *s; + d->fpregs = fptr; +} + +static void *enter_lpms(sigcontext_t *scp) { unsigned short pmstack_sel; - uint32_t pmstack_esp; + unsigned long pmstack_esp; if (!DPMI_CLIENT.in_dpmi_pm_stack) { D_printf("DPMI: Switching to locked stack\n"); pmstack_sel = DPMI_CLIENT.PMSTACK_SEL; @@ -1360,7 +1208,7 @@ static void *enter_lpms(cpuctx_t *scp) return SEL_ADR_CLNT(pmstack_sel, pmstack_esp, DPMI_CLIENT.is_32); } -static void leave_lpms(cpuctx_t *scp) +static void leave_lpms(sigcontext_t *scp) { if (DPMI_CLIENT.in_dpmi_pm_stack) { DPMI_CLIENT.in_dpmi_pm_stack--; @@ -1379,7 +1227,7 @@ static void leave_lpms(cpuctx_t *scp) * register words in protected mode, and zero out high register * words in real mode. The preserving may be needed because some * realmode int handlers may trash the high register words. */ -static void pm_to_rm_regs(cpuctx_t *scp, unsigned mask) +static void pm_to_rm_regs(sigcontext_t *scp, unsigned int mask) { if (mask & (1 << eflags_INDEX)) REG(eflags) = flags_to_e_rm(_eflags); @@ -1399,7 +1247,7 @@ static void pm_to_rm_regs(cpuctx_t *scp, unsigned mask) REG(ebp) = D_16_32(_ebp); } -static void rm_to_pm_regs(cpuctx_t *scp, unsigned mask) +static void rm_to_pm_regs(sigcontext_t *scp, unsigned int mask) { /* NDN insists on full 32bit copy. It sets up its own * int handlers in real mode, using those not covered @@ -1430,39 +1278,27 @@ static void rm_to_pm_regs(cpuctx_t *scp, unsigned mask) /* the below are used by DPMI API realmode services, and should * be able to pass full 32bit register values. */ -static void DPMI_save_rm_regs(struct RealModeCallStructure *rmreg, - unsigned mask) +static void DPMI_save_rm_regs(struct RealModeCallStructure *rmreg) { -#define RMR(x) \ - if (mask & (1 << x##_INDEX)) \ - rmreg->x = REG(x); -#define SRMR(x) \ - if (mask & (1 << x##_INDEX)) \ - rmreg->x = SREG(x); - RMR(edi); - RMR(esi); - RMR(ebp); - RMR(ebx); - RMR(edx); - RMR(ecx); - RMR(eax); - if (mask & (1 << eflags_INDEX)) - rmreg->flags = get_FLAGS(REG(eflags)); - SRMR(es); - SRMR(ds); - SRMR(fs); - SRMR(gs); - if (mask & (1 << eip_INDEX)) - rmreg->ip = LWORD(eip); - SRMR(cs); - if (mask & (1 << esp_INDEX)) - rmreg->sp = LWORD(esp); - SRMR(ss); -#undef RMR -#undef SRMR + rmreg->edi = REG(edi); + rmreg->esi = REG(esi); + rmreg->ebp = REG(ebp); + rmreg->ebx = REG(ebx); + rmreg->edx = REG(edx); + rmreg->ecx = REG(ecx); + rmreg->eax = REG(eax); + rmreg->flags = get_FLAGS(REG(eflags)); + rmreg->es = SREG(es); + rmreg->ds = SREG(ds); + rmreg->fs = SREG(fs); + rmreg->gs = SREG(gs); + rmreg->cs = SREG(cs); + rmreg->ip = LWORD(eip); + rmreg->ss = SREG(ss); + rmreg->sp = LWORD(esp); } -static void DPMI_restore_rm_regs(struct RealModeCallStructure *rmreg, unsigned mask) +static void DPMI_restore_rm_regs(struct RealModeCallStructure *rmreg, int mask) { #define RMR(x) \ if (mask & (1 << x##_INDEX)) \ @@ -1489,8 +1325,6 @@ static void DPMI_restore_rm_regs(struct RealModeCallStructure *rmreg, unsigned m if (mask & (1 << esp_INDEX)) LWORD(esp) = rmreg->sp; SRMR(ss); -#undef RMR -#undef SRMR } static void save_rm_regs(void) @@ -1499,7 +1333,7 @@ static void save_rm_regs(void) error("DPMI: DPMI_rm_procedure_running = 0x%x\n",DPMI_rm_procedure_running); leavedos(25); } - DPMI_save_rm_regs(&DPMI_rm_stack[DPMI_rm_procedure_running], ~0); + DPMI_save_rm_regs(&DPMI_rm_stack[DPMI_rm_procedure_running]); DPMI_rm_procedure_running++; if (DPMI_CLIENT.in_dpmi_rm_stack++ < DPMI_rm_stacks) { D_printf("DPMI: switching to realmode stack, in_dpmi_rm_stack=%i\n", @@ -1530,7 +1364,7 @@ static void update_kvm_idt(void) int i; for (i = 0; i < 0x100; i++) { - if (DEFAULT_INT(i) || i < 0x20) + if (DPMI_CLIENT.Interrupt_Table[i].selector == dpmi_sel() || i < 0x20) kvm_set_idt_default(i); else kvm_set_idt(i, DPMI_CLIENT.Interrupt_Table[i].selector, @@ -1538,114 +1372,29 @@ static void update_kvm_idt(void) } } -static void finish_clnt_switch(void) +static void set_client_num(int num) { - assert(in_dpmi); + if (!in_dpmi) + return; + current_client = num; + msdos_set_client(num); if (config.cpu_vm_dpmi == CPUVM_KVM) update_kvm_idt(); - if (config.cpu_vm == CPUVM_KVM || config.cpu_vm_dpmi == CPUVM_KVM) - kvm_update_fpu(); } -static int do_ldt_write(unsigned short ldt_entry, unsigned int *lp) +static void post_rm_call(int old_client) { - unsigned int base_addr, limit; - int np, ro, type, ld, ret; - - base_addr = (lp[1] & 0xFF000000) | ((lp[1] << 16) & 0x00FF0000) | - ((lp[0] >> 16) & 0x0000FFFF); - limit = (lp[1] & 0x000F0000) | (lp[0] & 0x0000FFFF); - type = (lp[1] >> 10) & 3; - ro = ((lp[1] >> 9) & 1) ^ 1; - np = ((lp[1] >> 15) & 1) ^ 1; - ld = (lp[1] >> 12) & 1; - if (!ld && !np) - D_printf("DPMI: invalid access type %x\n", lp[1] >> 8); - - ret = set_ldt_entry(ldt_entry, base_addr, limit, (lp[1] >> 22) & 1, type, ro, - (lp[1] >> 23) & 1, np, (lp[1] >> 20) & 1); - if (ret == -1) - return -1; - return np; -} - -static int ldt_write_low(unsigned short ldt_entry, unsigned int *lp) -{ - int rc = do_ldt_write(ldt_entry, lp); - switch (rc) { - case -1: - return -1; - case 0: // present - segment_set_user(ldt_entry, current_client + 1); - ldt_bitmap_update(ldt_entry, 1); - break; - case 1: { // NP - int used = segment_user(ldt_entry); - /* update only used entries as win31 stores crap in unused ones, - * and that crap needs to be preserved */ - if (used) { - segment_set_user(ldt_entry, 0); - ldt_bitmap_update(ldt_entry, 1); - } - break; - } - } - return 0; -} - -static void save_prev_clnt_state(void) -{ - if (config.cpu_vm == CPUVM_KVM || config.cpu_vm_dpmi == CPUVM_KVM) - kvm_get_fpu(); - memcpy(&DPMI_CLIENT.saved_fpu_state, &vm86_fpu_state, - sizeof(vm86_fpu_state)); - /* ldt_buffer may be outdated on an "accessed" bits so read from ldt */ - get_ldt(DPMI_CLIENT.saved_ldt, sizeof(DPMI_CLIENT.saved_ldt)); -} - -static void clnt_switch(int new_clnt) -{ - int i; - - assert(in_dpmi); - assert(current_client != new_clnt); - D_printf("DPMI: client switch %i --> %i\n", current_client, new_clnt); - if (current_client >= 0 && current_client < in_dpmi) - save_prev_clnt_state(); - - current_client = new_clnt; - - memcpy(&vm86_fpu_state, &DPMI_CLIENT.saved_fpu_state, - sizeof(vm86_fpu_state)); - /* swap first 16 LDT entries as required by DPMI-1.0 */ - for (i = 0; i < 0x10; i++) { - if (segment_user(i) < 0xfe) { - int err = ldt_write_low(i, - (unsigned int *)&DPMI_CLIENT.saved_ldt[i * LDT_ENTRY_SIZE]); - assert(!err); - } - } - - finish_clnt_switch(); -} - -static int post_rm_call(int old_client) -{ - int ret = 0; - assert(old_client <= in_dpmi - 1); assert(DPMI_rm_procedure_running); if (old_client != current_client) { /* 32rtm returned w/o terminating (stayed resident). * We switch to the prev client here. */ - /* old_client is actually a new one, it was saved on rm call */ - clnt_switch(old_client); - ret = 1; + D_printf("DPMI: client switch %i --> %i\n", current_client, old_client); + set_client_num(old_client); } - return ret; } -static void save_pm_regs(cpuctx_t *scp) +static void save_pm_regs(sigcontext_t *scp) { if (DPMI_pm_procedure_running >= DPMI_max_rec_pm_func) { error("DPMI: DPMI_pm_procedure_running = 0x%x\n",DPMI_pm_procedure_running); @@ -1654,24 +1403,17 @@ static void save_pm_regs(cpuctx_t *scp) save_context_nofpu(&DPMI_pm_stack[DPMI_pm_procedure_running++], scp); } -static void restore_pm_regs(cpuctx_t *scp) +static void restore_pm_regs(sigcontext_t *scp) { -#ifdef USE_MHPDBG - int tf = _isset_TF(); -#endif if (DPMI_pm_procedure_running > DPMI_max_rec_pm_func || DPMI_pm_procedure_running < 1) { error("DPMI: DPMI_pm_procedure_running = 0x%x\n",DPMI_pm_procedure_running); leavedos(25); } restore_context_nofpu(scp, &DPMI_pm_stack[--DPMI_pm_procedure_running]); -#ifdef USE_MHPDBG - if (mhpdbg.active && tf && !_isset_TF()) - _eflags |= TF; -#endif } -static void __fake_pm_int(cpuctx_t *scp) +static void __fake_pm_int(sigcontext_t *scp) { D_printf("DPMI: fake_pm_int() called, dpmi_pm=0x%02x\n", in_dpmi_pm()); save_rm_regs(); @@ -1693,17 +1435,16 @@ void fake_pm_int(void) __fake_pm_int(&DPMI_CLIENT.stack_frame); } -static void get_ext_API(cpuctx_t *scp) +static void get_ext_API(sigcontext_t *scp) { char *ptr = SEL_ADR_CLNT(_ds, _esi, DPMI_CLIENT.is_32); D_printf("DPMI: GetVendorAPIEntryPoint: %s\n", ptr); - _eflags &= ~CF; if (!strcmp("VIRTUAL SUPPORT", ptr)) { _LO(ax) = 0; } else if (!strcmp("PHARLAP.HWINT_SUPPORT", ptr) || !strcmp("PHARLAP.CE_SUPPORT", ptr) || !strcmp("PHARLAP.16", ptr) || !strncmp("PHARLAP.", ptr, 8)) { -// p_direct_str("DPMI: pharlap extender unsupported (%s)\n", ptr); +// p_dos_str("DPMI: pharlap extender unsupported (%s)\n", ptr); D_printf("DPMI: pharlap extender unsupported (%s)\n", ptr); DPMI_CLIENT.feature_flags |= DF_PHARLAP; _LO(ax) = 0; @@ -1715,26 +1456,6 @@ static void get_ext_API(cpuctx_t *scp) _LO(ax) = 0; _es = dpmi_sel(); _edi = DPMI_SEL_OFF(DPMI_API_extension); - } else if (!strcmp("DPMI_REINIT", ptr)) { - _LO(ax) = 0; - _es = dpmi_sel(); - _edi = DPMI_SEL_OFF(DPMI_reinit); -#ifdef USE_DJDEV64 - } else if (!strcmp("DJ64", ptr)) { - _LO(ax) = 0; - _es = dpmi_sel(); - _edi = DPMI_SEL_OFF(DPMI_dj64); - } else if (!strcmp("DJ64STUB", ptr)) { - if (!djdev64) - load_plugin("dj64"); - if (!djdev64) { - _eflags |= CF; - } else { - _LO(ax) = 0; - _es = dpmi_sel(); - _edi = djdev64->stub(); - } -#endif } else { if (!(_LWORD(eax)==0x168a)) _eax = 0x8001; @@ -1742,7 +1463,7 @@ static void get_ext_API(cpuctx_t *scp) } } -static int ResizeDescriptorBlock(cpuctx_t *scp, +static int ResizeDescriptorBlock(sigcontext_t *scp, unsigned short begin_selector, unsigned long length) { unsigned short num_descs, old_num_descs; @@ -1821,7 +1542,7 @@ void dpmi_set_interrupt_vector(unsigned char num, DPMI_INTDESC desc) else #endif /* first 0x20 int handlers clash with exception handlers */ - if (DEFAULT_INT(num) || num < 0x20) + if (desc.selector == dpmi_sel() || num < 0x20) kvm_set_idt_default(num); else kvm_set_idt(num, desc.selector, desc.offset32, DPMI_CLIENT.is_32, @@ -1861,7 +1582,7 @@ dpmi_pm_block DPMImalloc(unsigned long size) return *ptr; return dummy; } -dpmi_pm_block DPMImallocLinear(dosaddr_t base, unsigned long size, int committed) +dpmi_pm_block DPMImallocLinear(unsigned long base, unsigned long size, int committed) { dpmi_pm_block dummy, *ptr; memset(&dummy, 0, sizeof(dummy)); @@ -1872,19 +1593,6 @@ dpmi_pm_block DPMImallocLinear(dosaddr_t base, unsigned long size, int committed } int DPMIfree(unsigned long handle) { - dpmi_pm_block *ptr; - - ptr = lookup_pm_block(&DPMI_CLIENT.pm_block_root, handle); - if (!ptr) - return -1; - /* Syndicate game uses 0x502 for freeing shmem blocks. - * Instead of completely ignoring, we can use that to unlink shm - * while keeping the rest untouched. */ - if (ptr->shmname) { - D_printf("DPMI: partial free shared region %s\n", - ptr->shmname); - return DPMI_freeShPartial(&DPMI_CLIENT.pm_block_root, handle); - } return DPMI_free(&DPMI_CLIENT.pm_block_root, handle); } dpmi_pm_block DPMIrealloc(unsigned long handle, unsigned long size) @@ -1907,37 +1615,29 @@ dpmi_pm_block DPMIreallocLinear(unsigned long handle, unsigned long size, return *ptr; return dummy; } - -static void DPMIfreeAll(dpmi_pm_block_root *root) +void DPMIfreeAll(void) { - dpmi_pm_block **p = &root->first_pm_block; - while (*p) { -#ifdef USE_DJDEV64 - if ((*p)->flags & PMBF_DJ64) - djdev64->close((*p)->opaque); -#endif - DPMI_freeAll(root, *p); - } + return DPMI_freeAll(&DPMI_CLIENT.pm_block_root); } int DPMIMapConventionalMemory(unsigned long handle, unsigned long offset, - dosaddr_t low_addr, unsigned long cnt) + unsigned long low_addr, unsigned long cnt) { return DPMI_MapConventionalMemory(&DPMI_CLIENT.pm_block_root, handle, offset, low_addr, cnt); } -int DPMISetPageAttributes(unsigned long handle, int offs, uint16_t attrs[], int count) +int DPMISetPageAttributes(unsigned long handle, int offs, us attrs[], int count) { return DPMI_SetPageAttributes(&DPMI_CLIENT.pm_block_root, handle, offs, attrs, count); } -int DPMIGetPageAttributes(unsigned long handle, int offs, uint16_t attrs[], int count) +int DPMIGetPageAttributes(unsigned long handle, int offs, us attrs[], int count) { return DPMI_GetPageAttributes(&DPMI_CLIENT.pm_block_root, handle, offs, attrs, count); } -#ifdef DNATIVE +#ifdef __linux__ static int get_dr(pid_t pid, int i, unsigned int *dri) { *dri = ptrace(PTRACE_PEEKUSER, pid, @@ -1955,9 +1655,9 @@ static int set_dr(pid_t pid, int i, unsigned long dri) } #endif -static int dpmi_debug_breakpoint(int op, cpuctx_t *scp) +static int dpmi_debug_breakpoint(int op, sigcontext_t *scp) { -#ifdef DNATIVE +#ifdef __linux__ pid_t pid, vpid; int err, r, status; @@ -2150,26 +1850,36 @@ far_t DPMI_get_real_mode_interrupt_vector(int vec) return get_int_vector(vec); } -int DPMIAllocateShared(struct SHM_desc *shm) +static int count_shms(const char *name) { - const char *name = SEL_ADR_CLNT(shm->name_selector, shm->name_offset32, - DPMI_CLIENT.is_32); + int i; + int cnt = 0; + for (i = 0; i < in_dpmi; i++) + cnt += count_shm_blocks(&DPMIclient[i].pm_block_root, name); + return cnt; +} + +static unsigned int get_shm_size(const char *name) +{ + int i; dpmi_pm_block *ptr = NULL; - D_printf("DPMI: allocate shared region %s\n", name); - if (shm->flags & SHM_NEW_NS) { - ptr = DPMI_mallocSharedNewNS(&DPMI_CLIENT.pm_block_root, name, - shm->req_len, shm->flags); - } else if (shm->flags & SHM_NS) { - dpmi_pm_block *ptr2 = lookup_pm_block(&DPMI_CLIENT.pm_block_root, - shm->opaque); - if (ptr2) - ptr = DPMI_mallocSharedNS(&DPMI_CLIENT.pm_block_root, - ptr2->shm_dir, name, shm->req_len, shm->flags); - } else { - ptr = DPMI_mallocShared(&DPMI_CLIENT.pm_block_root, name, - shm->req_len, shm->flags); + for (i = 0; i < in_dpmi; i++) { + if ((ptr = lookup_pm_block_by_shmname(&DPMIclient[i].pm_block_root, + name))) + break; } + if (!ptr) + return 0; + return ptr->shmsize; +} + +int DPMIAllocateShared(struct SHM_desc *shm) +{ + char *name = SEL_ADR_CLNT(shm->name_selector, shm->name_offset32, + DPMI_CLIENT.is_32); + dpmi_pm_block *ptr = DPMI_mallocShared(&DPMI_CLIENT.pm_block_root, name, + shm->req_len, get_shm_size(name), shm->flags); if (!ptr) return -1; shm->ret_len = ptr->size; @@ -2180,109 +1890,14 @@ int DPMIAllocateShared(struct SHM_desc *shm) int DPMIFreeShared(uint32_t handle) { + int cnt; dpmi_pm_block *ptr; ptr = lookup_pm_block(&DPMI_CLIENT.pm_block_root, handle); if (!ptr) return -1; - D_printf("DPMI: free shared region %s\n", ptr->shmname); -#ifdef USE_DJDEV64 - if (ptr->flags & PMBF_DJ64) { - error("DJ64: handle was not closed\n"); - djdev64->close(ptr->opaque); - } -#endif - if (ptr->shm_dir) - return DPMI_freeSharedNS(&DPMI_CLIENT.pm_block_root, handle); - return DPMI_freeShared(&DPMI_CLIENT.pm_block_root, handle); -} - -static int DPMILockShared(cpuctx_t *scp, uint32_t handle, uint16_t flags) -{ -#define LOCK_DIR "dosemu2_shm" - void *sp = SEL_ADR(_ss, _esp); - int block = ((flags & 1) == 0); - int excl = ((flags & 2) == 0); - dpmi_pm_block *ptr = lookup_pm_block(&DPMI_CLIENT.pm_block_root, handle); - if (!ptr) - return 0x8023; - ptr->lock_flags = flags; - if (!block) { - void *lk = shlock_open(LOCK_DIR, ptr->shmname, excl, 0); - if (!lk) - return (excl ? 0x8018 : 0x8019); - ptr->shm_lock = lk; - return 0; - } - - ptr->lock_flags |= (1 << 16); // in progress - make_retf_frame(scp, sp, _cs, _eip); - _cs = dpmi_sel(); - _eip = DPMI_SEL_OFF(DPMI_shlock); - _eflags &= ~CF; - _eflags &= ~ZF; - return 0; -} - -static void LockShared(cpuctx_t *scp, uint32_t handle, uint16_t flags) -{ - void *lk; - int excl = ((flags & 2) == 0); - dpmi_pm_block *ptr = lookup_pm_block(&DPMI_CLIENT.pm_block_root, handle); - if (!ptr) { - _eflags |= CF; - _eax = 0x8023; - return; - } - if (!(ptr->lock_flags & (1 << 16))) { - error("No lock in progress\n"); - _eflags |= CF; - _eax = 0x8023; - return; - } - if (ptr->lock_flags & (1 << 17)) { // cancel request - _eflags |= CF; - _eax = 0x8005; - ptr->lock_flags = 0; - return; - } - lk = shlock_open(LOCK_DIR, ptr->shmname, excl, 0); - if (lk) { - ptr->shm_lock = lk; - ptr->lock_flags &= 0xffff; // clear in-progress flag - _eflags |= ZF; - return; - } - _eflags &= ~ZF; -} - -static int DPMIUnlockShared(uint32_t handle, uint16_t flags) -{ - int excl = ((flags & 1) == 0); - int cancel = ((flags & 2) == 2); - dpmi_pm_block *ptr = lookup_pm_block(&DPMI_CLIENT.pm_block_root, handle); - if (!ptr) - return 0x8023; - if (excl != ((ptr->lock_flags & 2) == 0)) { - error("DPMI: unlock invalid lock type\n"); - return 0x8002; - } - if (cancel) { - if (!(ptr->lock_flags & (1 << 16))) { - error("Canceling unavailable lock request\n"); - return 0x8002; - } - ptr->lock_flags |= (1 << 17); - return 0; - } - if (!ptr->shm_lock) { - error("DPMI: unlocking missing lock\n"); - return 0x8002; - } - shlock_close(ptr->shm_lock); - ptr->shm_lock = NULL; - ptr->lock_flags = 0; - return 0; + cnt = count_shms(ptr->shmname); + return DPMI_freeShared(&DPMI_CLIENT.pm_block_root, handle, cnt == 1); } DPMI_INTDESC dpmi_get_pm_exc_addr(int num) @@ -2315,10 +1930,9 @@ void dpmi_ext_set_ldt_monitor32(DPMI_INTDESC call, uint16_t d32) void dpmi_ext_ldt_monitor_enable(int on) { ldt_mon_on = on; - ldt_bitmap_cnt = 0; } -static void _do_ldt_call(cpuctx_t *scp, ldt_calldesc call, int ent, +static void _do_ldt_call(sigcontext_t *scp, ldt_calldesc call, int ent, int num) { _ebx = (ent << 3) | 7; @@ -2331,7 +1945,7 @@ static void _do_ldt_call(cpuctx_t *scp, ldt_calldesc call, int ent, _gs = 0; } -static void do_ldt_call(cpuctx_t *scp, ldt_calldesc call, int ent, +static void do_ldt_call(sigcontext_t *scp, ldt_calldesc call, int ent, int num, int cnt) { void *sp; @@ -2345,7 +1959,7 @@ static void do_ldt_call(cpuctx_t *scp, ldt_calldesc call, int ent, cnt, _cs, _eip, _ebx, _ecx); } -static void do_ldt_call_b(cpuctx_t *scp, ldt_calldesc call, int ent, +static void do_ldt_call_b(sigcontext_t *scp, ldt_calldesc call, int ent, int num, int cnt) { void *sp; @@ -2366,7 +1980,7 @@ struct chunk_state { int cnt; }; -static void ldt_process_chunk(cpuctx_t *scp, ldt_calldesc call, +static void ldt_process_chunk(sigcontext_t *scp, ldt_calldesc call, int i, struct chunk_state *state) { int j; @@ -2398,7 +2012,7 @@ static void ldt_process_chunk(cpuctx_t *scp, ldt_calldesc call, } } -static void ldt_process_chunk_c(cpuctx_t *scp, ldt_calldesc call, +static void ldt_process_chunk_c(sigcontext_t *scp, ldt_calldesc call, int i, struct chunk_state *state) { int j; @@ -2430,7 +2044,7 @@ static void ldt_process_chunk_c(cpuctx_t *scp, ldt_calldesc call, } } -static void ldt_process_end(cpuctx_t *scp, ldt_calldesc call, +static void ldt_process_end(sigcontext_t *scp, ldt_calldesc call, struct chunk_state *state) { if (state->carry) { @@ -2442,7 +2056,7 @@ static void ldt_process_end(cpuctx_t *scp, ldt_calldesc call, } } -static void dpmi_ldt_call(cpuctx_t *scp) +static void dpmi_ldt_call(sigcontext_t *scp) { ldt_calldesc call = DPMI_CLIENT.is_32 ? ldt_call32 : ldt_call16; int i; @@ -2492,7 +2106,7 @@ static void ldt_process_chunk_b_c(int i, struct chunk_state *state) ldt_bitmap[i] = 0; } -static void ldt_process_end_b(cpuctx_t *scp, ldt_calldesc call, +static void ldt_process_end_b(sigcontext_t *scp, ldt_calldesc call, struct chunk_state *state) { assert(state->carry); @@ -2503,7 +2117,7 @@ static void ldt_process_end_b(cpuctx_t *scp, ldt_calldesc call, state->cnt++; } -static void dpmi_ldt_exitcall(cpuctx_t *scp) +static void dpmi_ldt_exitcall(sigcontext_t *scp) { ldt_calldesc call = DPMI_CLIENT.is_32 ? ldt_call32 : ldt_call16; int i; @@ -2527,47 +2141,14 @@ static void dpmi_ldt_exitcall(cpuctx_t *scp) ldt_process_end_b(scp, call, &state); } -static int do_install_rsp(struct RSPcall_s *callback) -{ - if (RSP_num >= DPMI_MAX_CLIENTS) - return -1; - RSP_callbacks[RSP_num].lm_para_off = rsp_get_para(); - RSP_callbacks[RSP_num].call = *callback; - return 0; -} - -int dpmi_install_rsp(struct RSPcall_s *callback) -{ - int err = do_install_rsp(callback); - if (err) - return err; - RSP_num++; - return 0; -} - -dosaddr_t DPMIMapHWRam(unsigned addr, unsigned size) -{ - dpmi_pm_block *blk = DPMI_mapHWRam(&DPMI_CLIENT.pm_block_root, addr, size); - D_printf("DPMI: Map Physical Memory, addr=%#08x size=%#x\n", addr, size); - if (!blk) - return -1; - return blk->base; -} - -int DPMIUnmapHWRam(dosaddr_t vbase) -{ - D_printf("DPMI: Unmap Physical Memory, vbase=%#08x\n", vbase); - return DPMI_unmapHWRam(&DPMI_CLIENT.pm_block_root, vbase); -} - -static void do_int31(cpuctx_t *scp) +static void do_int31(sigcontext_t *scp) { #if 0 /* old way to use DPMI API, as per specs */ #define API_32(s) DPMI_CLIENT.is_32 #else /* allow 16bit clients to access the 32bit API. dosemu's DPMI extension. */ -#define API_32(scp) (DPMI_CLIENT.is_32 || (Segments(_cs >> 3).is_32 && \ +#define API_32(scp) (DPMI_CLIENT.is_32 || (Segments[_cs >> 3].is_32 && \ ext__thunk_16_32)) #endif #define API_16_32(x) (API_32(scp) ? (x) : (x) & 0xffff) @@ -2617,20 +2198,20 @@ static void do_int31(cpuctx_t *scp) CHECK_SELECTOR(_LWORD(ebx)); { unsigned int baddress = GetSegmentBase(_LWORD(ebx)); - _LWORD(edx) = (uint16_t)(baddress & 0xffff); - _LWORD(ecx) = (uint16_t)(baddress >> 16); + _LWORD(edx) = (us)(baddress & 0xffff); + _LWORD(ecx) = (us)(baddress >> 16); } break; case 0x0007: CHECK_SELECTOR(_LWORD(ebx)); - if (SetSegmentBaseAddress(_LWORD(ebx), (_LWORD_(ecx) << 16) | _LWORD(edx))) { + if (SetSegmentBaseAddress(_LWORD(ebx), ((uint32_t)_LWORD(ecx))<<16 | (_LWORD(edx)))) { _eflags |= CF; _LWORD(eax) = 0x8025; } break; case 0x0008: CHECK_SELECTOR(_LWORD(ebx)); - if (SetSegmentLimit(_LWORD(ebx), (_LWORD_(ecx) << 16) | _LWORD(edx))) { + if (SetSegmentLimit(_LWORD(ebx), ((uint32_t)(_LWORD(ecx))<<16) | (_LWORD(edx)))) { _eflags |= CF; _LWORD(eax) = 0x8025; } @@ -2667,7 +2248,7 @@ static void do_int31(cpuctx_t *scp) break; } /* DPMI-1.0 requires us to reload segregs */ - if (Segments(_LWORD(ebx) >> 3).not_present) + if (Segments[_LWORD(ebx) >> 3].not_present) FreeSegRegs(scp, _LWORD(ebx)); break; case 0x000d: @@ -2842,7 +2423,7 @@ err: desc = dpmi_get_pm_exc_addr(_LO(bx)); _LWORD(ecx) = desc.selector; _edx = desc.offset32; - D_printf("DPMI: Getting Ext PM Excp %#x = %#x:%#x\n", _LO(bx),_LWORD(ecx),_edx); + D_printf("DPMI: Getting Ext Excp %#x = %#x:%#x\n", _LO(bx),_LWORD(ecx),_edx); break; } case 0x0211: /* Get Ext Processor Exception Handler Vector - RM */ @@ -2853,7 +2434,7 @@ err: } _LWORD(ecx) = DPMI_CLIENT.Exception_Table_RM[_LO(bx)].selector; _edx = DPMI_CLIENT.Exception_Table_RM[_LO(bx)].offset; - D_printf("DPMI: Getting Ext RM Excp %#x = %#x:%#x\n", _LO(bx),_LWORD(ecx),_edx); + D_printf("DPMI: Getting RM Excp %#x = %#x:%#x\n", _LO(bx),_LWORD(ecx),_edx); break; case 0x0212: { /* Set Ext Processor Exception Handler Vector - PM */ DPMI_INTDESC desc; @@ -2862,7 +2443,7 @@ err: _eax = 0x8021; break; } - D_printf("DPMI: Setting Ext PM Excp %#x = %#x:%#x\n", _LO(bx),_LWORD(ecx),_edx); + D_printf("DPMI: Setting Ext Excp %#x = %#x:%#x\n", _LO(bx),_LWORD(ecx),_edx); desc.selector = _LWORD(ecx); desc.offset32 = API_16_32(_edx); dpmi_set_pm_exc_addr(_LO(bx), desc); @@ -2874,7 +2455,7 @@ err: _eax = 0x8021; break; } - D_printf("DPMI: Setting Ext RM Excp %#x = %#x:%#x\n", _LO(bx),_LWORD(ecx),_edx); + D_printf("DPMI: Setting Ext Excp %#x = %#x:%#x\n", _LO(bx),_LWORD(ecx),_edx); DPMI_CLIENT.Exception_Table_RM[_LO(bx)].selector = _LWORD(ecx); DPMI_CLIENT.Exception_Table_RM[_LO(bx)].offset = API_16_32(_edx); break; @@ -2885,22 +2466,17 @@ err: save_rm_regs(); { struct RealModeCallStructure *rmreg = SEL_ADR_X(_es, _edi); - uint16_t *ssp; + us *ssp; unsigned int rm_ssp, rm_sp; int rmask = ~((1 << cs_INDEX) | (1 << eip_INDEX)); int i; D_printf("DPMI: RealModeCallStructure at %p\n", rmreg); - if (rmreg->ss == SREG(ss)) { - error("DPMI: ERROR: bad rm stack requested, %x:%x\n", - rmreg->ss, rmreg->sp); - rmreg->ss = rmreg->sp = 0; - } if (rmreg->ss == 0 && rmreg->sp == 0) rmask &= ~((1 << esp_INDEX) | (1 << ss_INDEX)); DPMI_restore_rm_regs(rmreg, rmask); - ssp = (uint16_t *) SEL_ADR(_ss, _esp); + ssp = (us *) SEL_ADR(_ss, _esp); rm_ssp = SEGOFF2LINEAR(SREG(ss), 0); rm_sp = LWORD(esp); for (i = 0; i < _LWORD(ecx); i++) @@ -2927,11 +2503,8 @@ err: break; } /* 32rtm work-around */ - if (current_client != in_dpmi - 1) { - clnt_switch(in_dpmi - 1); - scp = &DPMI_CLIENT.stack_frame; // refresh after switch - msdos_set_client(scp, current_client); - } + if (current_client != in_dpmi - 1) + set_client_num(in_dpmi - 1); /* --------------------------------------------------- 0x300: RM | FC90C | @@ -2964,7 +2537,7 @@ err: _eflags |= CF; } break; - case 0x0305: { /* Get State Save/Restore Addresses */ + case 0x0305: { /* Get State Save/Restore Adresses */ far_t raddr; struct pmaddr_s paddr; _LWORD(eax) = DPMI_get_save_restore_address(&raddr, &paddr); @@ -2974,15 +2547,15 @@ err: _edi = paddr.offset; break; } - case 0x0306: /* Get Raw Mode Switch Addresses */ + case 0x0306: /* Get Raw Mode Switch Adresses */ _LWORD(ebx) = DPMI_SEG; _LWORD(ecx) = DPMI_OFF + HLT_OFF(DPMI_raw_mode_switch_rm); _LWORD(esi) = dpmi_sel(); _edi = DPMI_SEL_OFF(DPMI_raw_mode_switch_pm); break; case 0x0400: /* Get Version */ - _LWORD(eax) = (DPMI_VERSION << 8) | DPMI_MINOR_VERSION; - _LO(bx) = 5; // 32bit, V86, virtual memory + _LWORD(eax) = DPMI_VERSION << 8 | DPMI_DRIVER_VERSION; + _LO(bx) = 5; _LO(cx) = vm86s.cpu_type; _LWORD(edx) = 0x0870; /* PIC base imaster/slave interrupt */ break; @@ -2994,13 +2567,14 @@ err: * conventional memory mapping, * demand zero fill, * write-protect client, + * write-protect host. */ - _LWORD(eax) = 0x38; + _LWORD(eax) = 0x78; _LWORD(ecx) = 0; _LWORD(edx) = 0; *buf = DPMI_VERSION; - *(buf+1) = DPMI_MINOR_VERSION; - snprintf(buf+2, 126, "DOSEMU2 Version %d.%d", VERSION_NUM, SUBLEVEL); + *(buf+1) = DPMI_DRIVER_VERSION; + snprintf(buf+2, 126, "DOSEMU Version %d.%d", VERSION_NUM, SUBLEVEL); } break; @@ -3014,7 +2588,7 @@ err: case 0x0501: /* Allocate Memory Block */ { dpmi_pm_block block; - unsigned int mem_required = (_LWORD(ebx) << 16) | _LWORD(ecx); + unsigned int mem_required = (_LWORD(ebx))<<16 | (_LWORD(ecx)); block = DPMImalloc(mem_required); if (!block.size) { @@ -3022,7 +2596,7 @@ err: _eflags |= CF; break; } - D_printf("DPMI: malloc attempt for siz 0x%08x\n", (_LWORD(ebx) << 16) | _LWORD(ecx)); + D_printf("DPMI: malloc attempt for siz 0x%08x\n", (_LWORD(ebx))<<16 | (_LWORD(ecx))); D_printf(" malloc returns address %#x\n", block.base); D_printf(" using handle 0x%08x\n",block.handle); _LWORD(edi) = (block.handle)&0xffff; @@ -3033,9 +2607,9 @@ err: break; case 0x0502: /* Free Memory Block */ { - D_printf(" DPMI: Free Mem Blk. for handle %08x\n", (_LWORD(esi) << 16) | _LWORD(edi)); + D_printf(" DPMI: Free Mem Blk. for handle %08x\n",(_LWORD(esi))<<16 | (_LWORD(edi))); - if (DPMIfree((_LWORD(esi) << 16) | _LWORD(edi))) { + if(DPMIfree((_LWORD(esi))<<16 | (_LWORD(edi)))) { D_printf("DPMI: client attempt to free a non exist handle\n"); _eflags |= CF; break; @@ -3046,8 +2620,8 @@ err: { unsigned newsize, handle; dpmi_pm_block block; - handle = (_LWORD(esi) << 16) | _LWORD(edi); - newsize = (_LWORD(ebx) << 16) | _LWORD(ecx); + handle = (_LWORD(esi))<<16 | (_LWORD(edi)); + newsize = (_LWORD(ebx)<<16 | _LWORD(ecx)); D_printf("DPMI: Realloc to size %x\n", (_LWORD(ebx)<<16 | _LWORD(ecx))); D_printf("DPMI: For Mem Blk. for handle 0x%08x\n", handle); @@ -3059,8 +2633,8 @@ err: } D_printf("DPMI: realloc attempt for siz 0x%08x\n", newsize); D_printf(" realloc returns address %#x\n", block.base); - _LWORD(ecx) = (dosaddr_t)(block.base) & 0xffff; - _LWORD(ebx) = ((dosaddr_t)(block.base) >> 16) & 0xffff; + _LWORD(ecx) = (unsigned long)(block.base) & 0xffff; + _LWORD(ebx) = ((unsigned long)(block.base) >> 16) & 0xffff; } break; case 0x0504: /* Allocate linear mem, 1.0 */ @@ -3100,8 +2674,7 @@ err: unsigned long newsize, handle; dpmi_pm_block *old_block, block; unsigned short *sel_array; - dosaddr_t old_base; - unsigned old_len; + unsigned long old_base, old_len; /* JES Unsure of ASSUMING sel_array OK to be nit to NULL */ sel_array = NULL; @@ -3122,7 +2695,7 @@ err: _LWORD(eax) = 0x8023; /* invalid handle */ break; } - old_base = (dosaddr_t)old_block->base; + old_base = (unsigned long)old_block->base; old_len = old_block->size; if(_edx & 0x2) { /* update descriptor required */ @@ -3135,29 +2708,29 @@ err: _eflags |= CF; break; } - _ebx = (dosaddr_t)block.base; + _ebx = (unsigned long)block.base; _esi = block.handle; if(_edx & 0x2) { /* update descriptor required */ int i; unsigned short sel; - dosaddr_t sel_base; + unsigned long sel_base; for(i=0; i< _edi; i++) { sel = sel_array[i]; - if (segment_user(sel >> 3) == 0) + if (Segments[sel >> 3].used == 0) continue; - if (Segments(sel >> 3).type & MODIFY_LDT_CONTENTS_STACK) { - if(Segments(sel >> 3).is_big) - sel_base = Segments(sel>>3).base_addr + - Segments(sel>>3).limit*DPMI_page_size-1; + if (Segments[sel >> 3].type & MODIFY_LDT_CONTENTS_STACK) { + if(Segments[sel >> 3].is_big) + sel_base = Segments[sel>>3].base_addr + + Segments[sel>>3].limit*DPMI_page_size-1; else - sel_base = Segments(sel>>3).base_addr + Segments(sel>>3).limit - 1; + sel_base = Segments[sel>>3].base_addr + Segments[sel>>3].limit - 1; }else - sel_base = Segments(sel>>3).base_addr; + sel_base = Segments[sel>>3].base_addr; if ((old_base <= sel_base) && ( sel_base < (old_base+old_len))) SetSegmentBaseAddress(sel, - Segments(sel>>3).base_addr + - (dosaddr_t)block.base - + Segments[sel>>3].base_addr + + (unsigned long)block.base - old_base); } } @@ -3165,8 +2738,7 @@ err: break; case 0x0509: /* Map conventional memory,1.0 */ { - dosaddr_t low_addr; - unsigned handle, offset; + unsigned long low_addr, handle, offset; handle = _esi; low_addr = _edx; @@ -3184,7 +2756,7 @@ err: break; } - D_printf("DPMI: Map conventional mem for handle %d, offset %x at low address %x\n", handle, offset, low_addr); + D_printf("DPMI: Map conventional mem for handle %ld, offset %lx at low address %lx\n", handle, offset, low_addr); switch (DPMIMapConventionalMemory(handle, offset, low_addr, _ecx)) { case -2: _eflags |= CF; @@ -3201,7 +2773,7 @@ err: { unsigned long handle; dpmi_pm_block *block; - handle = (_LWORD(esi) << 16) | _LWORD(edi); + handle = (_LWORD(esi))<<16 | (_LWORD(edi)); if((block = lookup_pm_block(&DPMI_CLIENT.pm_block_root, handle)) == NULL) { _LWORD(eax) = 0x8023; @@ -3215,14 +2787,6 @@ err: _LWORD(ebx) = HI_WORD(block->base); } break; - case 0x050b: - { - unsigned int lp[0x20]; - GetFreeMemoryInformationExt(lp); - memcpy_2dos(GetSegmentBase(_es) + API_16_32(_edi), lp, sizeof(lp)); - } - break; - case 0x0600: /* Lock Linear Region */ case 0x0601: /* Unlock Linear Region */ case 0x0602: /* Mark Real Mode Region as Pageable */ @@ -3269,11 +2833,12 @@ err: case 0x0c00: /* Install Resident Service Provider Callback */ { - int err = do_install_rsp(SEL_ADR_X(_es, _edi)); - if (err) { + struct RSPcall_s *callback = SEL_ADR_X(_es, _edi); + if (RSP_num >= DPMI_MAX_CLIENTS) { _eflags |= CF; _LWORD(eax) = 0x8015; } else { + RSP_callbacks[RSP_num].call = *callback; DPMI_CLIENT.RSP_installed = 1; D_printf("installed Resident Service Provider Callback %i\n", RSP_num); } @@ -3284,14 +2849,7 @@ err: break; case 0x0d00: { /* Allocate Shared Memory */ - dosaddr_t p; - int err; - if (API_32(scp)) - p = GetSegmentBase(_es) + _edi; - else - p = GetSegmentBase(_es) + LO_WORD(_edi); - e_invalidate(p, sizeof(struct SHM_desc)); - err = DPMIAllocateShared(LINEAR2UNIX(p)); + int err = DPMIAllocateShared(SEL_ADR_X(_es, _edi)); if (err) { _eflags |= CF; _LWORD(eax) = 0x8014; @@ -3308,26 +2866,6 @@ err: break; } - case 0x0d02: { /* Lock Shared Memory */ - int err = DPMILockShared(scp, (_LWORD_(esi) << 16) | _LWORD_(edi), - _LWORD_(edx)); - if (err) { - _eflags |= CF; - _LWORD(eax) = err; - } - break; - } - - case 0x0d03: { /* Unlock Shared Memory */ - int err = DPMIUnlockShared((_LWORD_(esi) << 16) | _LWORD_(edi), - _LWORD_(edx)); - if (err) { - _eflags |= CF; - _LWORD(eax) = err; - } - break; - } - case 0x0e00: /* Get Coprocessor Status */ _LWORD(eax) = 0x4d; break; @@ -3336,13 +2874,13 @@ err: case 0x0506: /* Get Page Attributes */ D_printf("DPMI: Get Page Attributes for %i pages\n", _ecx); - if (!DPMIGetPageAttributes(_esi, _ebx, (uint16_t *)SEL_ADR(_es, _edx), _ecx)) + if (!DPMIGetPageAttributes(_esi, _ebx, (us *)SEL_ADR(_es, _edx), _ecx)) _eflags |= CF; break; case 0x0507: /* Set Page Attributes */ D_printf("DPMI: Set Page Attributes for %i pages\n", _ecx); - if (!DPMISetPageAttributes(_esi, _ebx, (uint16_t *)SEL_ADR(_es, _edx), _ecx)) + if (!DPMISetPageAttributes(_esi, _ebx, (us *)SEL_ADR(_es, _edx), _ecx)) _eflags |= CF; break; @@ -3352,46 +2890,28 @@ err: _eflags |= CF; break; + case 0x0700: /* Reserved,MARK PAGES AS PAGING CANDIDATES, see intr. lst */ case 0x0702: /* Mark Page as Demand Paging Candidate */ case 0x0703: /* Discard Page Contents */ - { -#if HAVE_DECL_MADV_COLD - /* Note: 0x703 can use MADV_FREE, but in that case we'd have - * to check that the entire area belongs to this client. - * Fortunately DPMI spec doesn't demand the 0x703 pages to be - * zeroed out. */ - int rc; - dosaddr_t addr = (_LWORD_(ebx) << 16) | (_LWORD_(ecx)); - unsigned size = (_LWORD_(esi) << 16) | (_LWORD_(edi)); - if (addr + size > config.dpmi_base + dpmi_mem_size()) { - D_printf("DPMI: Failing bad paging call\n"); - rc = -1; - } else { - rc = madvise(MEM_BASE32(addr), size, MADV_COLD); - } - if (rc == -1) { - _LWORD(eax) = 0x8025; - _eflags |= CF; - } -#endif + D_printf("DPMI: unimplemented int31 func %#x\n",_LWORD(eax)); break; - } case 0x0800: { /* create Physical Address Mapping */ - dosaddr_t addr; - unsigned size; - dosaddr_t base; + unsigned addr, size; + dpmi_pm_block *blk; addr = (_LWORD_(ebx) << 16) | (_LWORD_(ecx)); size = (_LWORD_(esi) << 16) | (_LWORD_(edi)); - base = DPMIMapHWRam(addr, size); - if (base == (unsigned)-1) { + D_printf("DPMI: Map Physical Memory, addr=%#08x size=%#x\n", addr, size); + + blk = DPMI_mapHWRam(&DPMI_CLIENT.pm_block_root, addr, size); + if (!blk) { _eflags |= CF; break; } - _LWORD(ebx) = base >> 16; - _LWORD(ecx) = base; + _LWORD(ebx) = blk->base >> 16; + _LWORD(ecx) = blk->base; D_printf("DPMI: getting physical memory area at 0x%x, size 0x%x, " "ret=%#x:%#x\n", addr, size, _LWORD(ebx), _LWORD(ecx)); @@ -3401,7 +2921,8 @@ err: size_t vbase; int rc; vbase = (_LWORD_(ebx) << 16) | (_LWORD_(ecx)); - rc = DPMIUnmapHWRam(vbase); + D_printf("DPMI: Unmap Physical Memory, vbase=%#08zx\n", vbase); + rc = DPMI_unmapHWRam(&DPMI_CLIENT.pm_block_root, vbase); if (rc == -1) { _eflags |= CF; break; @@ -3417,7 +2938,7 @@ err: D_printf("DPMI: dpmi function failed, CF=1\n"); } -static void make_iret_frame(cpuctx_t *scp, void *sp, +static void make_iret_frame(sigcontext_t *scp, void *sp, uint32_t cs, uint32_t eip) { if (DPMI_CLIENT.is_32) { @@ -3435,7 +2956,7 @@ static void make_iret_frame(cpuctx_t *scp, void *sp, } } -static void make_retf_frame(cpuctx_t *scp, void *sp, +static void make_retf_frame(sigcontext_t *scp, void *sp, uint32_t cs, uint32_t eip) { if (DPMI_CLIENT.is_32) { @@ -3451,7 +2972,7 @@ static void make_retf_frame(cpuctx_t *scp, void *sp, } } -static void make_xretf_frame(cpuctx_t *scp, void *sp, +static void make_xretf_frame(sigcontext_t *scp, void *sp, uint32_t cs, uint32_t eip) { if (DPMI_CLIENT.is_32) { @@ -3470,7 +2991,7 @@ static void make_xretf_frame(cpuctx_t *scp, void *sp, dpmi_set_pm(1); } -static void remove_xretf_frame(cpuctx_t *scp, void *sp) +static void remove_xretf_frame(sigcontext_t *scp, void *sp) { if (DPMI_CLIENT.is_32) { unsigned int *ssp = sp; @@ -3494,20 +3015,14 @@ static void remove_xretf_frame(cpuctx_t *scp, void *sp) static void dpmi_realmode_callback(int rmcb_client, int num) { void *sp; - int changed = 0; - cpuctx_t *scp = &DPMI_CLIENT.stack_frame; + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; if (rmcb_client >= in_dpmi || num >= DPMI_MAX_RMCBS) return; D_printf("DPMI: Real Mode Callback for #%i address of client %i (from %i)\n", num, rmcb_client, current_client); - DPMI_save_rm_regs(DPMIclient[rmcb_client].realModeCallBack[num].rmreg, ~0); - if (rmcb_client != current_client) { - clnt_switch(rmcb_client); - scp = &DPMI_CLIENT.stack_frame; // refresh switch - changed++; - } + DPMI_save_rm_regs(DPMIclient[rmcb_client].realModeCallBack[num].rmreg); save_pm_regs(scp); sp = enter_lpms(scp); @@ -3530,9 +3045,6 @@ static void dpmi_realmode_callback(int rmcb_client, int num) dpmi_set_pm(1); dpmi_cli(); - - if (changed) - msdos_set_client(scp, rmcb_client); } static void rmcb_hlt(Bit16u off, HLT_ARG(arg)) @@ -3540,25 +3052,11 @@ static void rmcb_hlt(Bit16u off, HLT_ARG(arg)) dpmi_realmode_callback((long)arg, off); } -static int is_same_desc(unsigned short sel, unsigned desc[2]) -{ - unsigned lp[2]; - - GetDescriptor(sel, lp); - lp[1] &= ~0x1f0100; - desc[1] &= ~0x1f0100; - return (memcmp(lp, desc, 8) == 0); -} - -static void do_RSP_call(cpuctx_t *scp, int num, int clnt, - int terminating, int inh_or_prv) +static void dpmi_RSP_call(sigcontext_t *scp, int num, int terminating) { unsigned char *code, *data; void *sp; - uint32_t eip; - - if (terminating > 1 && !(RSP_callbacks[num].call.flags & RSP_F_SW)) - return; // client doesn't support such call + unsigned long eip; if (DPMI_CLIENT.is_32) { if ((RSP_callbacks[num].call.code32[5] & 0x88) != 0x88) return; @@ -3574,14 +3072,8 @@ static void do_RSP_call(cpuctx_t *scp, int num, int clnt, } if (!terminating) { - if (is_same_desc(_dpmi_sel16, (unsigned *)code)) { - DPMI_CLIENT.RSP_cs[num] = _dpmi_sel16; - } else if (is_same_desc(_dpmi_sel32, (unsigned *)code)) { - DPMI_CLIENT.RSP_cs[num] = _dpmi_sel32; - } else { - DPMI_CLIENT.RSP_cs[num] = AllocateDescriptors(1); - SetDescriptor(DPMI_CLIENT.RSP_cs[num], (unsigned int *)code); - } + DPMI_CLIENT.RSP_cs[num] = AllocateDescriptors(1); + SetDescriptor(DPMI_CLIENT.RSP_cs[num], (unsigned int *)code); if ((data[5] & 0x88) == 0x80) { DPMI_CLIENT.RSP_ds[num] = AllocateDescriptors(1); SetDescriptor(DPMI_CLIENT.RSP_ds[num], (unsigned int *)data); @@ -3593,136 +3085,31 @@ static void do_RSP_call(cpuctx_t *scp, int num, int clnt, save_pm_regs(scp); sp = enter_lpms(scp); - if (terminating == 1) - make_xretf_frame(scp, sp, dpmi_sel(), - DPMI_SEL_OFF(DPMI_return_from_RSPcall_exit)); - else - make_xretf_frame(scp, sp, dpmi_sel(), - DPMI_SEL_OFF(DPMI_return_from_RSPcall)); + make_xretf_frame(scp, sp, dpmi_sel(), + DPMI_SEL_OFF(DPMI_return_from_RSPcall)); _es = _fs = _gs = 0; _ds = DPMI_CLIENT.RSP_ds[num]; _cs = DPMI_CLIENT.RSP_cs[num]; _eip = eip; _eax = terminating; - _ebx = clnt; - /* extension: ecx has inherit_idt flag on startup and prev client on term */ - _ecx = inh_or_prv; - _edx = DPMI_CLIENT.private_data_segment + DPMI_private_paragraphs + - RSP_callbacks[num].lm_para_off; - _esi = DPMI_CLIENT.initial_psp; + _ebx = current_client; + if (terminating) + _ecx = current_client - 1; // extension! (can be -1) + else + _ecx = -1; } -static void dpmi_RSP_call(cpuctx_t *scp, int clnt, int terminating, - int inh_or_prv) -{ - int i; - - for (i = 0; i < DPMI_CLIENT.RSP_num; i++) { - D_printf("DPMI: Calling RSP %i for %i\n", i, terminating); - do_RSP_call(scp, i, clnt, terminating, inh_or_prv); - } -} - -static int rsp_get_para(void) -{ - int i, cnt = 0; - - for (i = 0; i < RSP_num; i++) { - if (RSP_callbacks[i].call.flags & RSP_F_LOWMEM) - cnt += RSP_callbacks[i].call.para; - } - D_printf("DPMI: added 0x%x para for RSP\n", cnt); - return cnt; -} - -static void msdos_set_client(cpuctx_t *scp, int num) -{ - dpmi_RSP_call(scp, num, 2, -1); -} - -static int prev_clnt(void) -{ - int prv = in_dpmi - 1; - if (prv == current_client) - prv--; - return prv; -} - -#ifdef USE_DJDEV64 - -void register_djdev64(const struct djdev64_ops *ops) -{ - djdev64 = ops; -} - -static void dpmi_dj64_open(cpuctx_t *scp) -{ - int handle = (_LWORD(esi) << 16) | _LWORD(edi); - const char *mp = "/dev/shm"; - char *path; - dpmi_pm_block *ptr; - int djh; - void *dlh = load_plugin("dj64"); - - _eflags |= CF; - if (!dlh || !djdev64) - return; - ptr = lookup_pm_block(&DPMI_CLIENT.pm_block_root, handle); - if (!ptr) { - error("DJ64: invalid handle\n"); - return; - } - if (ptr->shm_dir) - mp = ptr->shm_dir; - path = assemble_path(mp, ptr->rshmname + 1); - djh = djdev64->open(path); - free(path); - if (djh != -1) { - _eflags &= ~CF; - ptr->flags |= PMBF_DJ64; - ptr->opaque = djh; - _eax = djh; - _es = dpmi_sel(); - _edi = djdev64->call(djh); - _esi = djdev64->ctrl(djh); - D_printf("DPMI: dj64 opened\n"); - } -} - -static void dpmi_dj64_close(cpuctx_t *scp) -{ - int handle = (_LWORD(esi) << 16) | _LWORD(edi); - dpmi_pm_block *ptr; - - _eflags |= CF; - if (!djdev64) - return; - ptr = lookup_pm_block(&DPMI_CLIENT.pm_block_root, handle); - if (!ptr || !(ptr->flags & PMBF_DJ64) || ptr->opaque != _eax) { - error("DJ64: invalid handle\n"); - return; - } - djdev64->close(_eax); - ptr->flags &= ~PMBF_DJ64; // to not close again on exit - _eflags &= ~CF; -} - -#endif - static void dpmi_cleanup(void) { D_printf("DPMI: cleanup\n"); if (in_dpmi_pm()) dosemu_error("Quitting DPMI while in_dpmi_pm\n"); - /* restore env seg */ - if (DPMI_CLIENT.envp) - WRITE_WORD(SEGOFF2LINEAR(DPMI_CLIENT.initial_psp, 0x2c), DPMI_CLIENT.envp); if (current_client != in_dpmi - 1) { error("DPMI: termination of non-last client\n"); /* leave the leak. * TODO: fixing that leak is a lot of work, in particular - * FreeAllDescriptors() + * msdos_done() would be out of sync and FreeAllDescriptors() * will need to use "current_client" instead of "in_dpmi" * to wipe only the needed descs. * That happens only if the one started 32rtm by some tool like @@ -3732,15 +3119,18 @@ static void dpmi_cleanup(void) * Starting 32rtm by hands may go here if you terminate the * parent DPMI shell (comcom32), but nobody does that. * Lets say this is a very pathological case for a big code surgery. */ - clnt_switch(in_dpmi - 1); + set_client_num(in_dpmi - 1); return; } + if (config.pm_dos_api) + msdos_done(); FreeAllDescriptors(); DPMI_free(&host_pm_block_root, DPMI_CLIENT.pm_stack->handle); hlt_unregister_handler_vm86(DPMI_CLIENT.rmcb_off); if (!DPMI_CLIENT.RSP_installed) { - DPMIfreeAll(&DPMI_CLIENT.pm_block_root); -// free(__fpstate); + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; + DPMIfreeAll(); + free(__fpstate); } if (win3x_mode != INACTIVE) { @@ -3748,26 +3138,19 @@ static void dpmi_cleanup(void) if (win3x_mode == INACTIVE) SETIVEC(0x66, 0, 0); // winos2 } - SETIVEC(0x1c, DPMI_CLIENT.s_i1c.segment, DPMI_CLIENT.s_i1c.offset); - SETIVEC(0x23, DPMI_CLIENT.s_i23.segment, DPMI_CLIENT.s_i23.offset); - SETIVEC(0x24, DPMI_CLIENT.s_i24.segment, DPMI_CLIENT.s_i24.offset); - cli_blacklisted = 0; dpmi_is_cli = 0; in_dpmi--; - if (in_dpmi) { - clnt_switch(in_dpmi - 1); - clear_ZF(); - } else { - current_client = -1; - set_ZF(); /* reset FPU */ - } + set_client_num(in_dpmi - 1); } static void dpmi_soft_cleanup(void) { dpmi_cleanup(); if (in_dpmi == 0) { + SETIVEC(0x1c, s_i1c.segment, s_i1c.offset); + SETIVEC(0x23, s_i23.segment, s_i23.offset); + SETIVEC(0x24, s_i24.segment, s_i24.offset); if (ldt_mon_on) error("DPMI: ldt mon still on\n"); } else if (ldt_mon_on) { @@ -3775,9 +3158,10 @@ static void dpmi_soft_cleanup(void) } } -static void quit_dpmi(cpuctx_t *scp, unsigned short errcode, +static void quit_dpmi(sigcontext_t *scp, unsigned short errcode, int tsr, unsigned short tsr_para, int dos_exit) { + int i; int have_tsr = tsr && DPMI_CLIENT.RSP_installed; /* this is checked in dpmi_cleanup */ @@ -3788,14 +3172,16 @@ static void quit_dpmi(cpuctx_t *scp, unsigned short errcode, if (DPMI_CLIENT.in_dpmi_pm_stack) { error("DPMI: Warning: trying to leave DPMI when in_dpmi_pm_stack=%i\n", DPMI_CLIENT.in_dpmi_pm_stack); - port_outb(0x21, DPMI_CLIENT.orig_imr); + port_outb(0x21, DPMI_CLIENT.imr); DPMI_CLIENT.in_dpmi_pm_stack = 0; } if (DPMI_CLIENT.RSP_state == 0) { - int prv = prev_clnt(); DPMI_CLIENT.RSP_state = 1; - dpmi_RSP_call(scp, current_client, 1, prv); + for (i = 0;i < RSP_num; i++) { + D_printf("DPMI: Calling RSP %i for termination\n", i); + dpmi_RSP_call(scp, i, 1); + } } if (have_tsr) { @@ -3809,16 +3195,17 @@ static void quit_dpmi(cpuctx_t *scp, unsigned short errcode, if (!have_tsr || !tsr_para) { HI(ax) = 0x4c; LO(ax) = errcode; + do_int(0x21); } else { HI(ax) = 0x31; LO(ax) = errcode; LWORD(edx) = tsr_para; + do_int(0x21); } - jmp_to(DPMI_SEG, DPMI_OFF + HLT_OFF(DPMI_exit)); } } -static void chain_rm_int(cpuctx_t *scp, int i) +static void chain_rm_int(sigcontext_t *scp, int i) { D_printf("DPMI: Calling real mode handler for int 0x%02x\n", i); save_rm_regs(); @@ -3828,7 +3215,7 @@ static void chain_rm_int(cpuctx_t *scp, int i) do_int(i); } -static void chain_hooked_int(cpuctx_t *scp, int i) +static void chain_hooked_int(sigcontext_t *scp, int i) { far_t iaddr; D_printf("DPMI: Calling real mode handler for int 0x%02x\n", i); @@ -3838,13 +3225,13 @@ static void chain_hooked_int(cpuctx_t *scp, int i) REG(eip) = DPMI_OFF + HLT_OFF(DPMI_return_from_dos); switch (i) { case 0x1c: - iaddr = DPMI_CLIENT.s_i1c; + iaddr = s_i1c; break; case 0x23: - iaddr = DPMI_CLIENT.s_i23; + iaddr = s_i23; break; case 0x24: - iaddr = DPMI_CLIENT.s_i24; + iaddr = s_i24; break; default: return; @@ -3855,19 +3242,20 @@ static void chain_hooked_int(cpuctx_t *scp, int i) fake_int_to(iaddr.segment, iaddr.offset); } -static void do_dpmi_int(cpuctx_t *scp, int i) +static void do_dpmi_int(sigcontext_t *scp, int i) { switch (i) { case 0x2f: switch (_LWORD(eax)) { +#if 0 + /* this is disabled. coopth currently can't handle delays + * in protected mode... :( */ case 0x1680: /* give up time slice */ - /* hackish impl because DPMI-1.0 spec requires that here. - * The proper one (coopth-based) is in msdos.c. */ - if (config.cpu_vm_dpmi == CPUVM_NATIVE) - signal_unblock_async_sigs(); - dosemu_sleep(); - _LO(ax) = 0; + idle_enable(0, 100, 0, "int2f_idle_dpmi"); + if (config.hogthreshold) + _LO(ax) = 0; return; +#endif case 0x1684: D_printf("DPMI: Get VxD entry point, BX = 0x%04x\n", _LWORD(ebx)); get_VXD_entry(scp); @@ -3930,17 +3318,20 @@ static void do_dpmi_int(cpuctx_t *scp, int i) * DANG_END_FUNCTION */ -static void do_pm_int(cpuctx_t *scp, int i) +void run_pm_int(int i) { void *sp; unsigned short old_ss; unsigned int old_esp; unsigned char imr; + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; D_printf("DPMI: run_pm_int(0x%02x) called, in_dpmi_pm=0x%02x\n",i,in_dpmi_pm()); - if (DEFAULT_INT(i)) { + if (DPMI_CLIENT.Interrupt_Table[i].selector == dpmi_sel()) { + D_printf("DPMI: Calling real mode handler for int 0x%02x\n", i); + if (in_dpmi_pm()) fake_pm_int(); real_run_int(i); @@ -3951,8 +3342,6 @@ static void do_pm_int(cpuctx_t *scp, int i) old_esp = _esp; sp = enter_lpms(&DPMI_CLIENT.stack_frame); imr = port_inb(0x21); - DPMI_CLIENT.imr[0] = imr; - DPMI_CLIENT.imr[1] = port_inb(0xa1); D_printf("DPMI: Calling protected mode handler for int 0x%02x\n", i); if (DPMI_CLIENT.is_32) { @@ -4005,8 +3394,7 @@ static void do_pm_int(cpuctx_t *scp, int i) * are two problems with that: * - STI can be done also by the chained real-mode handler * - We need to allow processing the different IRQ levels for performance - * So simply mask the currently processing IRQ on PIC0 (in case of RTC - * we mask entire PIC1 for a moment). */ + * So simply mask the currently processing IRQ on PIC. */ if (i == 8 || i == 0x70) { /* PIT or RTC interrupt */ unsigned char isr; @@ -4019,11 +3407,6 @@ static void do_pm_int(cpuctx_t *scp, int i) #endif } -void run_pm_int(int i) -{ - do_pm_int(&DPMI_CLIENT.stack_frame, i); -} - /* DANG_BEGIN_FUNCTION run_pm_dos_int * * This routine is used for reflecting the software @@ -4034,23 +3417,23 @@ void run_pm_int(int i) static void run_pm_dos_int(int i) { void *sp; - uint32_t ret_eip; - cpuctx_t *scp = &DPMI_CLIENT.stack_frame; + unsigned long ret_eip; + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; D_printf("DPMI: run_pm_dos_int(0x%02x) called\n",i); - if (DEFAULT_INT(i)) { + if (DPMI_CLIENT.Interrupt_Table[i].selector == dpmi_sel()) { far_t iaddr; D_printf("DPMI: Calling real mode handler for int 0x%02x\n", i); switch (i) { case 0x1c: - iaddr = DPMI_CLIENT.s_i1c; + iaddr = s_i1c; break; case 0x23: - iaddr = DPMI_CLIENT.s_i23; + iaddr = s_i23; break; case 0x24: - iaddr = DPMI_CLIENT.s_i24; + iaddr = s_i24; break; default: error("run_pm_dos_int with int=%x\n", i); @@ -4100,6 +3483,10 @@ void run_dpmi(void) #ifdef USE_MHPDBG int retcode; #endif + if (return_requested) { + return_requested = 0; + return; + } #ifdef USE_MHPDBG if (mhpdbg_is_stopped()) return; @@ -4114,15 +3501,17 @@ void run_dpmi(void) void dpmi_setup(void) { - int i, type, np, err; + int i, type, err; unsigned int base_addr, limit, *lp; dpmi_pm_block *block; unsigned short data_sel; if (!config.dpmi) return; - get_ldt(ldt_buffer, LDT_ENTRIES * LDT_ENTRY_SIZE); - memset(seg_meta, 0, sizeof(seg_meta)); + dpmi_set_map_flags(0); + + get_ldt(ldt_buffer); + memset(Segments, 0, sizeof(Segments)); for (i = 0; i < MAX_SELECTORS; i++) { lp = (unsigned int *)&ldt_buffer[i * LDT_ENTRY_SIZE]; base_addr = (*lp >> 16) & 0x0000FFFF; @@ -4131,10 +3520,9 @@ void dpmi_setup(void) base_addr |= (*lp & 0xFF000000) | ((*lp << 16) & 0x00FF0000); limit |= (*lp & 0x000F0000); type = (*lp >> 10) & 3; - np = ((*lp >> 15) & 1) ^ 1; - if (!np) { + if (base_addr || limit || type) { D_printf("LDT entry 0x%x used: b=0x%x l=0x%x t=%i\n",i,base_addr,limit,type); - segment_set_user(i, 0xfe); + Segments[i].used = 0xfe; } } @@ -4151,11 +3539,8 @@ void dpmi_setup(void) error("DPMI: can't allocate memory for DPMI host helper code\n"); goto err2; } - MEMCPY_2DOS(block->base, _binary_dpmisel_o_bin_start, - _binary_dpmisel_o_bin_end - _binary_dpmisel_o_bin_start); - mprotect_mapping(MAPPING_DPMI, block->base, - PAGE_ALIGN(DPMI_sel_code_end-DPMI_sel_code_start), - PROT_READ | PROT_EXEC); + MEMCPY_2DOS(block->base, DPMI_sel_code_start, + DPMI_sel_code_end-DPMI_sel_code_start); err = SetSelector(_dpmi_sel16, block->base, DPMI_SEL_OFF(DPMI_sel_code_end)-1, 0, MODIFY_LDT_CONTENTS_CODE, 0, 0, 0, 0); @@ -4203,7 +3588,7 @@ void dpmi_setup(void) if (SetSelector(data_sel, block->base, DPMI_page_size - 1, 1, MODIFY_LDT_CONTENTS_DATA, 0, 0, 0, 0)) goto err; - dpmi_api_init(data_sel, block->base, DPMI_page_size * 2); + dpmi_api_init(data_sel, block->base, DPMI_page_size); if (config.pm_dos_api) msdos_setup(); @@ -4214,32 +3599,24 @@ void dpmi_setup(void) break; case CPUVM_NATIVE: warn("Using native DPMI control\n"); - err = native_dpmi_setup(); - if (err) - goto err; + native_dpmi_setup(); break; case CPUVM_EMU: warn("Using DPMI with CPU emulator\n"); break; } - prn_tid = coopth_create("dpmi print thr", print_thr); - + dpmi_set_map_flags(MAPPING_IMMEDIATE); return; err: - error("DPMI initialization failed, exiting\n"); + error("DPMI initialization failed, disabling\n"); err2: - config.exitearly = 1; + config.dpmi = 0; } void dpmi_reset(void) { - if (!config.dpmi) return; - - RSP_num = 0; - if (config.pm_dos_api) - msdos_reset(); current_client = in_dpmi - 1; while (in_dpmi) { if (in_dpmi_pm()) @@ -4248,20 +3625,73 @@ void dpmi_reset(void) native_dpmi_exit(&DPMI_CLIENT.stack_frame); dpmi_cleanup(); } - ldt_mon_on = 0; - ldt_bitmap_cnt = 0; - DPMI_rm_procedure_running = 0; - DPMI_pm_procedure_running = 0; - in_dpmi_irq = 0; - cli_blacklisted = 0; + if (config.pm_dos_api) + msdos_reset(); } -static void setup_int_exc(int inherit_idt) +void dpmi_init(void) { - int i; - DPMI_INTDESC desc; + /* Holding spots for REGS and Return Code */ + unsigned short CS, DS, ES, SS, psp, my_cs; + unsigned int ssp, sp; + unsigned int my_ip, i; + unsigned char *cp; + int inherit_idt; + sigcontext_t *scp; + emu_hlt_t hlt_hdlr = HLT_INITIALIZER; + + CARRY; + + if (!config.dpmi) + return; + + if (in_dpmi>=DPMI_MAX_CLIENTS) { + p_dos_str("Sorry, only %d DPMI clients supported under DOSEMU :-(\n", DPMI_MAX_CLIENTS); + return; + } + + current_client = in_dpmi++; + D_printf("DPMI: initializing %i\n", in_dpmi); + memset(&DPMI_CLIENT, 0, sizeof(DPMI_CLIENT)); + dpmi_is_cli = 0; + + DPMI_CLIENT.is_32 = LWORD(eax) ? 1 : 0; + + if (in_dpmi == 1 && !RSP_num) { + DPMI_rm_procedure_running = 0; + pm_block_handle_used = 1; + } + + DPMI_CLIENT.private_data_segment = SREG(es); + + DPMI_CLIENT.pm_stack = DPMI_malloc(&host_pm_block_root, + PAGE_ALIGN(DPMI_pm_stack_size)); + if (DPMI_CLIENT.pm_stack == NULL) { + error("DPMI: can't allocate memory for locked protected mode stack\n"); + goto err; + } + + if (!(DPMI_CLIENT.PMSTACK_SEL = AllocateDescriptors(1))) goto err; + if (SetSelector(DPMI_CLIENT.PMSTACK_SEL, DPMI_CLIENT.pm_stack->base, + DPMI_pm_stack_size-1, DPMI_CLIENT.is_32, + MODIFY_LDT_CONTENTS_DATA, 0, 0, 0, 0)) goto err; + + if (in_dpmi > 1) + inherit_idt = DPMI_CLIENT.is_32 == PREV_DPMI_CLIENT.is_32 + /* inheriting from PharLap causes 0x4c to be passed to DOS directly! */ + && !(PREV_DPMI_CLIENT.feature_flags & DF_PHARLAP) + /* save RSPs from inheriting their own handlers */ + && !RSP_num +#if WINDOWS_HACKS +/* work around the disability of win31 in Standard mode to run the DPMI apps */ + && (win3x_mode != STANDARD) +#endif + ; + else + inherit_idt = 0; for (i=0;i<0x100;i++) { + DPMI_INTDESC desc; if (inherit_idt) { desc.offset32 = PREV_DPMI_CLIENT.Interrupt_Table[i].offset; desc.selector = PREV_DPMI_CLIENT.Interrupt_Table[i].selector; @@ -4271,21 +3701,7 @@ static void setup_int_exc(int inherit_idt) } dpmi_set_interrupt_vector(i, desc); } - - /* vtmr interrupts are not inherited */ - desc.selector = dpmi_sel(); - desc.offset32 = DPMI_SEL_OFF(DPMI_interrupt) + VTMR_INTERRUPT; - DPMI_CLIENT.vtmr_prev = desc; - desc.selector = dpmi_sel(); - desc.offset32 = DPMI_SEL_OFF(DPMI_vtmr_irq); - dpmi_set_interrupt_vector(VTMR_INTERRUPT, desc); - - desc.selector = dpmi_sel(); - desc.offset32 = DPMI_SEL_OFF(DPMI_interrupt) + VRTC_INTERRUPT; - DPMI_CLIENT.vrtc_prev = desc; - desc.selector = dpmi_sel(); - desc.offset32 = DPMI_SEL_OFF(DPMI_vrtc_irq); - dpmi_set_interrupt_vector(VRTC_INTERRUPT, desc); + DPMI_CLIENT.imr = port_inb(0x21); for (i=0;i<0x20;i++) { if (inherit_idt) { @@ -4300,132 +3716,6 @@ static void setup_int_exc(int inherit_idt) DPMI_CLIENT.Exception_Table_RM[i].offset = DPMI_SEL_OFF(DPMI_rm_exception) + i; DPMI_CLIENT.Exception_Table_RM[i].selector = dpmi_sel(); } -} - -static void dpmi_reinit(cpuctx_t *scp) -{ - unsigned short DS, ES, SS, rights; - int i; - - _eflags |= CF; - D_printf("DPMI: reinit called, %i %i\n", _LWORD(eax), DPMI_CLIENT.is_32); - D_printf("%s", DPMI_show_state(scp)); - do_dpmi_retf(scp, SEL_ADR(_ss, _esp)); - - if ((_LWORD(eax) & 1) == DPMI_CLIENT.is_32) - _eflags &= ~CF; - else if (DPMI_CLIENT.is_32) - return; - - DPMI_CLIENT.is_32 = (_LWORD(eax) & 1); - DS = CreateAliasDescriptor(_ds); - SetSegmentLimit(DS, 0xffff); - GetDescriptorAccessRights(DS, &rights); - if (DPMI_CLIENT.is_32) - SetDescriptorAccessRights(DS, rights | 0x4000); // 32bit - else - SetDescriptorAccessRights(DS, rights & ~0x4000); // 16bit - if (_ss == _ds) { - SS = DS; - } else { - SS = CreateAliasDescriptor(_ss); - SetSegmentLimit(SS, 0xffff); - GetDescriptorAccessRights(SS, &rights); - if (DPMI_CLIENT.is_32) - SetDescriptorAccessRights(SS, rights | 0x4000); // 32bit - else - SetDescriptorAccessRights(SS, rights & ~0x4000); // 16bit - } - ES = DPMI_CLIENT.psp_sel; - - setup_int_exc(0); - SETIVEC(0x1b, BIOSSEG, INT_OFF(0x1b)); // for buggy causeway extender - - _ds = DS; - _es = ES; - _ss = SS; - /* if came from coopth, we need to hack CS here and use custom - * ret16 helper in msdos.c */ - if (_cs == _dpmi_sel16) - _cs = _dpmi_sel32; - /* also hack CS for RSP */ - for (i = 0; i < DPMI_CLIENT.RSP_num; i++) { - if (DPMI_CLIENT.RSP_cs[i] == _dpmi_sel16) - DPMI_CLIENT.RSP_cs[i] = _dpmi_sel32; - } - - _eflags &= ~CF; - D_printf("%s", DPMI_show_state(scp)); -} - -void dpmi_init(void) -{ - /* Holding spots for REGS and Return Code */ - unsigned short CS, DS, ES, SS, psp, my_cs; - unsigned int ssp, sp; - unsigned int my_ip, i; - unsigned char *cp; - int inherit_idt; - cpuctx_t *scp; - emu_hlt_t hlt_hdlr = HLT_INITIALIZER; - - CARRY; - - if (!config.dpmi) - return; - - if (in_dpmi>=DPMI_MAX_CLIENTS) { - p_direct_str("Sorry, only %d DPMI clients supported under DOSEMU :-(\n", DPMI_MAX_CLIENTS); - return; - } - - in_dpmi++; - memset(&DPMIclient[in_dpmi - 1], 0, sizeof(DPMI_CLIENT)); - if (config.cpu_vm == CPUVM_KVM || config.cpu_vm_dpmi == CPUVM_KVM) - kvm_get_fpu(); - memcpy(&DPMIclient[in_dpmi - 1].saved_fpu_state, &vm86_fpu_state, - sizeof(vm86_fpu_state)); - clnt_switch(in_dpmi - 1); - - dpmi_is_cli = 0; - - DPMI_CLIENT.is_32 = (LWORD(eax) & 1); - D_printf("DPMI: initializing client %i, %s\n", current_client, - DPMI_CLIENT.is_32 ? "32bit" : "16bit"); - - if (in_dpmi == 1 && !RSP_num) { - DPMI_rm_procedure_running = 0; - pm_block_handle_used = 1; - } - - DPMI_CLIENT.private_data_segment = SREG(es); - - DPMI_CLIENT.pm_stack = DPMI_malloc(&host_pm_block_root, DPMI_pm_stack_size); - if (DPMI_CLIENT.pm_stack == NULL) { - error("DPMI: can't allocate memory for locked protected mode stack\n"); - goto err; - } - - if (!(DPMI_CLIENT.PMSTACK_SEL = AllocateDescriptors(1))) goto err; - if (SetSelector(DPMI_CLIENT.PMSTACK_SEL, DPMI_CLIENT.pm_stack->base, - DPMI_pm_stack_size-1, DPMI_CLIENT.is_32, - MODIFY_LDT_CONTENTS_DATA, 0, 0, 0, 0)) goto err; - - if (in_dpmi > 1) { - inherit_idt = DPMI_CLIENT.is_32 == PREV_DPMI_CLIENT.is_32 - /* inheriting from PharLap causes 0x4c to be passed to DOS directly! */ - && !(PREV_DPMI_CLIENT.feature_flags & DF_PHARLAP) -#if WINDOWS_HACKS -/* work around the disability of win31 in Standard mode to run the DPMI apps */ - && (win3x_mode != STANDARD) -#endif - ; - } else - inherit_idt = 0; - - setup_int_exc(inherit_idt); - - DPMI_CLIENT.orig_imr = port_inb(0x21); hlt_hdlr.name = "DPMI rm cb"; hlt_hdlr.len = DPMI_MAX_RMCBS; @@ -4479,7 +3769,7 @@ void dpmi_init(void) } if (!(CS = AllocateDescriptors(1))) goto err; - if (SetSelector(CS, (dosaddr_t) (my_cs << 4), 0xffff, 0, + if (SetSelector(CS, (unsigned long) (my_cs << 4), 0xffff, 0, MODIFY_LDT_CONTENTS_CODE, 0, 0, 0, 0)) goto err; if (!(SS = ConvertSegmentToDescriptor(SREG(ss)))) goto err; @@ -4488,15 +3778,6 @@ void dpmi_init(void) if (!(ES = AllocateDescriptors(1))) goto err; SetSegmentBaseAddress(ES, psp << 4); SetSegmentLimit(ES, 0xff); - DPMI_CLIENT.psp_sel = ES; - /* convert environment pointer to a descriptor */ - DPMI_CLIENT.envp = READ_WORD(SEGOFF2LINEAR(psp, 0x2c)); - if (DPMI_CLIENT.envp) { - unsigned short env_sel = ConvertSegmentToDescriptor(DPMI_CLIENT.envp); - WRITE_WORD(SEGOFF2LINEAR(psp, 0x2c), env_sel); - D_printf("DPMI: env segment %#x converted to descriptor %#x\n", - DPMI_CLIENT.envp, env_sel); - } if (debug_level('M')) { print_ldt(); @@ -4514,6 +3795,11 @@ void dpmi_init(void) _es = ES; _fs = 0; _gs = 0; +#ifdef __linux__ + /* fpu_state needs to be paragraph aligned for fxrstor/fxsave */ + __fpstate = aligned_alloc(16, sizeof(*__fpstate)); + *__fpstate = *vm86_fpu_state; +#endif NOCARRY; rm_to_pm_regs(&DPMI_CLIENT.stack_frame, ~0); /* on cpu-emu we work with IOPL=3 to avoid doom work-around */ @@ -4521,26 +3807,29 @@ void dpmi_init(void) _eflags |= IOPL_MASK; DPMI_CLIENT.win3x_mode = win3x_mode; - DPMI_CLIENT.s_i1c.segment = ISEG(0x1c); - DPMI_CLIENT.s_i1c.offset = IOFF(0x1c); - DPMI_CLIENT.s_i23.segment = ISEG(0x23); - DPMI_CLIENT.s_i23.offset = IOFF(0x23); - DPMI_CLIENT.s_i24.segment = ISEG(0x24); - DPMI_CLIENT.s_i24.offset = IOFF(0x24); - SETIVEC(0x1c, DPMI_SEG, DPMI_OFF + HLT_OFF(DPMI_int1c) + current_client * 3); - SETIVEC(0x23, DPMI_SEG, DPMI_OFF + HLT_OFF(DPMI_int23) + current_client * 3); - SETIVEC(0x24, DPMI_SEG, DPMI_OFF + HLT_OFF(DPMI_int24) + current_client * 3); + if (config.pm_dos_api) + msdos_init(DPMI_CLIENT.is_32, + DPMI_CLIENT.private_data_segment + DPMI_private_paragraphs, psp); if (in_dpmi == 1) { + s_i1c.segment = ISEG(0x1c); + s_i1c.offset = IOFF(0x1c); + s_i23.segment = ISEG(0x23); + s_i23.offset = IOFF(0x23); + s_i24.segment = ISEG(0x24); + s_i24.offset = IOFF(0x24); + SETIVEC(0x1c, DPMI_SEG, DPMI_OFF + HLT_OFF(DPMI_int1c)); + SETIVEC(0x23, DPMI_SEG, DPMI_OFF + HLT_OFF(DPMI_int23)); + SETIVEC(0x24, DPMI_SEG, DPMI_OFF + HLT_OFF(DPMI_int24)); + in_dpmi_irq = 0; - /* something else global? */ } dpmi_set_pm(1); - /* remember RSP_num on start, so that if some are added later, they - * not to trigger on termination */ - DPMI_CLIENT.RSP_num = RSP_num; - dpmi_RSP_call(&DPMI_CLIENT.stack_frame, current_client, 0, inherit_idt); + for (i = 0; i < RSP_num; i++) { + D_printf("DPMI: Calling RSP %i\n", i); + dpmi_RSP_call(&DPMI_CLIENT.stack_frame, i, 0); + } dpmi_ldt_call(scp); return; /* return immediately to the main loop */ @@ -4552,17 +3841,27 @@ err: CARRY; FreeAllDescriptors(); DPMI_free(&host_pm_block_root, DPMI_CLIENT.pm_stack->handle); - DPMIfreeAll(&DPMI_CLIENT.pm_block_root); + DPMIfreeAll(); in_dpmi--; - if (in_dpmi) - clnt_switch(in_dpmi - 1); - else - current_client = -1; + set_client_num(in_dpmi - 1); } -static void return_from_exception(cpuctx_t *scp) +void dpmi_sigio(sigcontext_t *scp) +{ + if (DPMIValidSelector(_cs)) { +/* DANG_FIXTHIS We shouldn't return to dosemu code if IF=0, but it helps - WHY? */ +/* + Because IF is not set by popf and because dosemu have to do some background + job (like DMA transfer) regardless whether IF is set or not. +*/ + dpmi_return(scp, DPMI_RET_DOSEMU); + } +} + +static void return_from_exception(sigcontext_t *scp) { void *sp; + leave_lpms(scp); D_printf("DPMI: Return from client exception handler, " "in_dpmi_pm_stack=%i\n", DPMI_CLIENT.in_dpmi_pm_stack); @@ -4570,7 +3869,7 @@ static void return_from_exception(cpuctx_t *scp) if (DPMI_CLIENT.is_32) { unsigned int *ssp = sp; - /* popping error code */ + /* poping error code */ ssp++; _eip = *ssp++; _cs = *ssp++; @@ -4579,7 +3878,7 @@ static void return_from_exception(cpuctx_t *scp) _ss = *ssp++; } else { unsigned short *ssp = sp; - /* popping error code */ + /* poping error code */ ssp++; _LWORD(eip) = *ssp++; _cs = *ssp++; @@ -4590,24 +3889,20 @@ static void return_from_exception(cpuctx_t *scp) } } -static void cpu_exception_rm(cpuctx_t *scp, int trapno) +static void cpu_exception_rm(sigcontext_t *scp, int trapno) { switch (trapno) { - case 0x00: /* divz */ case 0x01: /* debug */ - case 0x02: /* NMI */ case 0x03: /* int3 */ case 0x04: /* overflow */ - case 0x05: /* bound */ - case 0x07: /* no FPU */ __fake_pm_int(scp); do_int(trapno); break; default: - quit_dpmi(scp, 0xff, 0, 0, 1); - p_direct_str("DPMI: Unhandled Exception %02x - Terminating Client\n" + p_dos_str("DPMI: Unhandled Exception %02x - Terminating Client\n" "It is likely that dosemu is unstable now and should be rebooted\n", trapno); + quit_dpmi(scp, 0xff, 0, 0, 1); break; } } @@ -4623,10 +3918,10 @@ static void cpu_exception_rm(cpuctx_t *scp, int trapno) * DANG_END_FUNCTION */ -static void do_default_cpu_exception(cpuctx_t *scp, int trapno) +static void do_default_cpu_exception(sigcontext_t *scp, int trapno) { void * sp; - sp = (uint16_t *)SEL_ADR(_ss,_esp); + sp = (us *)SEL_ADR(_ss,_esp); #ifdef TRACE_DPMI if (debug_level('t') && (trapno==1)) { @@ -4637,7 +3932,7 @@ static void do_default_cpu_exception(cpuctx_t *scp, int trapno) #endif #ifdef USE_MHPDBG - mhp_intercept("\nCPU Exception occurred, invoking dosdebug\n\n", "+9M"); + mhp_intercept("\nCPU Exception occured, invoking dosdebug\n\n", "+9M"); #endif if ((_trapno != 0x3 && _trapno != 0x1) #ifdef X86_EMULATOR @@ -4652,9 +3947,10 @@ static void do_default_cpu_exception(cpuctx_t *scp, int trapno) D_printf("DPMI: do_default_cpu_exception 0x%02x at %#x:%#x ss:sp=%x:%x\n", trapno, (int)_cs, (int)_eip, (int)_ss, (int)_esp); - /* Route the 0.9 PM exception to protected-mode interrupt handler or + /* Route the 0.9 exception to protected-mode interrupt handler or * terminate the client if the one is not installed. */ - if (trapno == 6 || trapno >= 8 || DEFAULT_INT(trapno)) { + if (trapno == 6 || trapno >= 8 || + DPMI_CLIENT.Interrupt_Table[trapno].selector == dpmi_sel()) { cpu_exception_rm(scp, trapno); return; } @@ -4674,7 +3970,7 @@ static void do_default_cpu_exception(cpuctx_t *scp, int trapno) * * DANG_END_FUNCTION */ -static void do_pm_cpu_exception(cpuctx_t *scp, INTDESC entry) +static void do_pm_cpu_exception(sigcontext_t *scp, INTDESC entry) { unsigned int *ssp; unsigned short old_ss; @@ -4686,7 +3982,7 @@ static void do_pm_cpu_exception(cpuctx_t *scp, INTDESC entry) /* Extended exception stack frame - DPMI 1.0 */ *--ssp = 0; /* PTE */ - *--ssp = _cr2; + *--ssp = DOSADDR_REL(LINP(_cr2)); *--ssp = _gs; *--ssp = _fs; *--ssp = _ds; @@ -4734,19 +4030,14 @@ static void do_pm_cpu_exception(cpuctx_t *scp, INTDESC entry) _eflags &= ~(TF | NT | AC); } -int dpmi_realmode_exception(unsigned trapno, unsigned err, uint32_t cr2) +int dpmi_realmode_exception(unsigned trapno, unsigned err, dosaddr_t cr2) { - cpuctx_t *scp = &DPMI_CLIENT.stack_frame; + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; unsigned int *ssp; - unsigned short old_ss; - unsigned int old_esp; - if (trapno >= 0x20 || - DPMI_CLIENT.Exception_Table_RM[trapno].selector == dpmi_sel()) + if (DPMI_CLIENT.Exception_Table_RM[trapno].selector == dpmi_sel()) return 0; - old_ss = _ss; - old_esp = _esp; save_pm_regs(&DPMI_CLIENT.stack_frame); rm_to_pm_regs(&DPMI_CLIENT.stack_frame, ~0); ssp = enter_lpms(&DPMI_CLIENT.stack_frame); @@ -4773,23 +4064,23 @@ int dpmi_realmode_exception(unsigned trapno, unsigned err, uint32_t cr2) } /* Standard exception stack frame - DPMI 0.9 */ if (DPMI_CLIENT.is_32) { - *--ssp = old_ss; - *--ssp = old_esp; - *--ssp = dpmi_flags_to_stack(_eflags); - *--ssp = _cs; - *--ssp = _eip; - *--ssp = _err; + *--ssp = _SS; + *--ssp = _SP; + *--ssp = get_FLAGS(REG(eflags)) | VM_MASK; + *--ssp = _CS; + *--ssp = _IP; + *--ssp = err; *--ssp = dpmi_sel(); *--ssp = DPMI_SEL_OFF(DPMI_return_from_rm_exception); } else { *--ssp = 0; *--ssp = 0; *--ssp = 0; - *--ssp = old_esp >> 16; // save high esp word or it can be corrupted + *--ssp = 0; - *--ssp = (old_ss << 16) | (unsigned short) old_esp; - *--ssp = ((unsigned short) dpmi_flags_to_stack(_eflags) << 16) | _cs; - *--ssp = (_LWORD_(eip) << 16) | _err; + *--ssp = (_SS << 16) | (unsigned short) _SP; + *--ssp = ((unsigned short) (get_FLAGS(REG(eflags)) | VM_MASK) << 16) | _CS; + *--ssp = ((unsigned)_IP << 16) | err; *--ssp = (dpmi_sel() << 16) | DPMI_SEL_OFF(DPMI_return_from_rm_exception); } ADD_16_32(_esp, -0x58); @@ -4805,7 +4096,7 @@ int dpmi_realmode_exception(unsigned trapno, unsigned err, uint32_t cr2) return 1; } -static void do_legacy_cpu_exception(cpuctx_t *scp, INTDESC entry) +static void do_legacy_cpu_exception(sigcontext_t *scp, INTDESC entry) { unsigned int *ssp; unsigned short old_ss; @@ -4842,20 +4133,17 @@ static void do_legacy_cpu_exception(cpuctx_t *scp, INTDESC entry) _eflags &= ~(TF | NT | AC); } -static void do_cpu_exception(cpuctx_t *scp) +static void do_cpu_exception(sigcontext_t *scp) { - D_printf("DPMI: do_cpu_exception(0x%02x) at %#x:%#x, ss:esp=%x:%x, cr2=%#x, err=%#x\n", +#ifdef USE_MHPDBG + if (_trapno == 0xd) + mhp_intercept("\nCPU Exception occured, invoking dosdebug\n\n", "+9M"); +#endif + D_printf("DPMI: do_cpu_exception(0x%02x) at %#x:%#x, ss:esp=%x:%x, cr2=%#"PRI_RG", err=%#x\n", _trapno, _cs, _eip, _ss, _esp, _cr2, _err); if (debug_level('M') > 5) D_printf("DPMI: %s\n", DPMI_show_state(scp)); -#ifdef USE_MHPDBG - if (mhpdbg.active && _trapno == 3) { - mhp_intercept("\nINT3 occurred, invoking dosdebug\n\n", "+9M"); - return; - } -#endif - if (DPMI_CLIENT.Exception_Table_PM[_trapno].selector != dpmi_sel() || DPMI_CLIENT.Exception_Table_PM[_trapno].offset >= DPMI_SEL_OFF(DPMI_sel_end)) { @@ -4870,7 +4158,7 @@ static void do_cpu_exception(cpuctx_t *scp) do_default_cpu_exception(scp, _trapno); } -static void do_dpmi_retf(cpuctx_t *scp, void * const sp) +static void do_dpmi_retf(sigcontext_t *scp, void * const sp) { if (DPMI_CLIENT.is_32) { unsigned int *ssp = sp; @@ -4885,8 +4173,7 @@ static void do_dpmi_retf(cpuctx_t *scp, void * const sp) } } -/* rough iret emulation for HW handlers only */ -static void do_dpmi_iret(cpuctx_t *scp, void * const sp) +static void do_dpmi_iret(sigcontext_t *scp, void * const sp) { if (DPMI_CLIENT.is_32) { unsigned int *ssp = sp; @@ -4903,85 +4190,7 @@ static void do_dpmi_iret(cpuctx_t *scp, void * const sp) } } -/* more precise iret emulation suitable for SW handlers */ -static void emu_dpmi_iret(cpuctx_t *scp, void * const sp) -{ - int stk32 = Segments(_ss >> 3).is_32; - - if (Segments(_cs >> 3).is_32) { - unsigned int *ssp = sp; - _eip = *ssp++; - _cs = *ssp++; - _eflags = dpmi_flags_from_stack_iret(scp, *ssp++); - if (stk32) - _esp += 12; - else - _LWORD(esp) += 12; - } else { - unsigned short *ssp = sp; - _LWORD(eip) = *ssp++; - _cs = *ssp++; - _eflags = dpmi_flags_from_stack_iret(scp, *ssp++); - if (stk32) - _esp += 6; - else - _LWORD(esp) += 6; - } -} - -static void return_from_hwint(cpuctx_t *scp, void * const sp) -{ -#ifdef USE_MHPDBG - int tf = _isset_TF(); -#endif - unsigned char imr; - leave_lpms(scp); - D_printf("DPMI: Return from hardware interrupt handler, " - "in_dpmi_pm_stack=%i\n", DPMI_CLIENT.in_dpmi_pm_stack); - if (DPMI_CLIENT.is_32) { - unsigned int *ssp = sp; - int pm; - _eip = *ssp++; - _cs = *ssp++; - _eflags = dpmi_flags_from_stack_r0(*ssp++); - _esp = *ssp++; - _ss = *ssp++; - pm = *ssp++; - if (pm > 1) { - error("DPMI: HW interrupt stack corrupted\n"); - leavedos(38); - } - dpmi_set_pm(pm); - ssp++; - imr = *ssp++; - } else { - unsigned short *ssp = sp; - int pm; - _LWORD(eip) = *ssp++; - _cs = *ssp++; - _eflags = dpmi_flags_from_stack_r0(*ssp++); - _LWORD(esp) = *ssp++; - _ss = *ssp++; - pm = *ssp++; - if (pm > 1) { - error("DPMI: HW interrupt stack corrupted\n"); - leavedos(38); - } - dpmi_set_pm(pm); - _HWORD(esp) = *ssp++; - imr = *ssp++; - } - in_dpmi_irq--; - port_outb(0x21, imr); - dpmi_sti(); -#ifdef USE_MHPDBG - /* allow tracing from PM hwints */ - if (mhpdbg.active && tf) - _eflags |= TF; -#endif -} - -static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) +static void do_dpmi_hlt(sigcontext_t *scp, uint8_t *lina, void *sp) { _eip += 1; if (_cs == dpmi_sel()) { @@ -5007,7 +4216,7 @@ static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) } else if (_eip==1+DPMI_SEL_OFF(DPMI_save_restore_pm)) { if (_LO(ax)==0) { D_printf("DPMI: save real mode registers\n"); - DPMI_save_rm_regs(SEL_ADR_X(_es, _edi), ~0); + DPMI_save_rm_regs(SEL_ADR_X(_es, _edi)); } else { D_printf("DPMI: restore real mode registers\n"); DPMI_restore_rm_regs(SEL_ADR_X(_es, _edi), ~0); @@ -5039,10 +4248,48 @@ static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) } } else if (_eip==1+DPMI_SEL_OFF(DPMI_return_from_pm)) { - return_from_hwint(scp, sp); + unsigned char imr; + leave_lpms(scp); + D_printf("DPMI: Return from hardware interrupt handler, " + "in_dpmi_pm_stack=%i\n", DPMI_CLIENT.in_dpmi_pm_stack); + if (DPMI_CLIENT.is_32) { + unsigned int *ssp = sp; + int pm; + _eip = *ssp++; + _cs = *ssp++; + _eflags = dpmi_flags_from_stack_r0(*ssp++); + _esp = *ssp++; + _ss = *ssp++; + pm = *ssp++; + if (pm > 1) { + error("DPMI: HW interrupt stack corrupted\n"); + leavedos(38); + } + dpmi_set_pm(pm); + ssp++; + imr = *ssp++; + } else { + unsigned short *ssp = sp; + int pm; + _LWORD(eip) = *ssp++; + _cs = *ssp++; + _eflags = dpmi_flags_from_stack_r0(*ssp++); + _LWORD(esp) = *ssp++; + _ss = *ssp++; + pm = *ssp++; + if (pm > 1) { + error("DPMI: HW interrupt stack corrupted\n"); + leavedos(38); + } + dpmi_set_pm(pm); + _HWORD(esp) = *ssp++; + imr = *ssp++; + } + in_dpmi_irq--; + port_outb(0x21, imr); + dpmi_sti(); } else if (_eip==1+DPMI_SEL_OFF(DPMI_return_from_exception)) { - leave_lpms(scp); return_from_exception(scp); } else if (_eip==1+DPMI_SEL_OFF(DPMI_return_from_ext_exception)) { @@ -5068,9 +4315,27 @@ static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) "in_dpmi_pm_stack=%i\n", DPMI_CLIENT.in_dpmi_pm_stack); leave_lpms(scp); pm_to_rm_regs(scp, ~0); - return_from_exception(scp); restore_pm_regs(scp); dpmi_set_pm(0); + if (DPMI_CLIENT.is_32) { + unsigned int *ssp = sp; + /* poping error code */ + ssp++; + _IP = *ssp++; + _CS = *ssp++; + set_EFLAGS(REG(eflags), *ssp++); + _SP = *ssp++; + _SS = *ssp++; + } else { + unsigned short *ssp = sp; + /* poping error code */ + ssp++; + _IP = *ssp++; + _CS = *ssp++; + set_EFLAGS(REG(eflags), *ssp++); + _SP = *ssp++; + _SS = *ssp++; + } } else if (_eip==1+DPMI_SEL_OFF(DPMI_return_from_rm_ext_exception)) { unsigned int *ssp = sp; @@ -5102,11 +4367,6 @@ static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) DPMI_restore_rm_regs(SEL_ADR_X(_es, _edi), ~0); restore_pm_regs(scp); dpmi_set_pm(0); - if (current_client != in_dpmi - 1) { - clnt_switch(in_dpmi - 1); - scp = &DPMI_CLIENT.stack_frame; // refresh after switch - msdos_set_client(scp, current_client); - } } else if (_eip==1+DPMI_SEL_OFF(DPMI_return_from_int_1c)) { leave_lpms(scp); @@ -5118,7 +4378,7 @@ static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) dpmi_set_pm(0); } else if (_eip==1+DPMI_SEL_OFF(DPMI_return_from_int_23)) { - cpuctx_t old_ctx = {}, *curscp; + sigcontext_t old_ctx = {}, *curscp; unsigned int old_esp; int esp_delta; int killed = 0; @@ -5128,6 +4388,7 @@ static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) DPMI_CLIENT.in_dpmi_pm_stack); pm_to_rm_regs(scp, ~0); + old_ctx.fpregs = scp->fpregs; restore_pm_regs(&old_ctx); curscp = scp; scp = &old_ctx; @@ -5188,90 +4449,17 @@ static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) DPMI_CLIENT.in_dpmi_pm_stack, in_dpmi_pm()); leave_lpms(scp); restore_pm_regs(scp); - - } else if (_eip==1+DPMI_SEL_OFF(DPMI_return_from_RSPcall_exit)) { - remove_xretf_frame(scp, sp); - D_printf("DPMI: Return from RSPcall, in_dpmi_pm_stack=%i, dpmi_pm=%i\n", - DPMI_CLIENT.in_dpmi_pm_stack, in_dpmi_pm()); - leave_lpms(scp); - restore_pm_regs(scp); if (!in_dpmi_pm()) { /* app terminated */ dpmi_soft_cleanup(); } - } else if (_eip==1+DPMI_SEL_OFF(DPMI_vtmr_irq)) { - if (DEFAULT_INT(8)) { - /* just jump to default entry that leads us to RM */ - D_printf("VTMR: jump to RM handler\n"); - _cs = DPMI_CLIENT.vtmr_prev.selector; - _eip = DPMI_CLIENT.vtmr_prev.offset32; - } else { - int masked = vtmr_pre_irq_dpmi(DPMI_CLIENT.imr); - if (masked) - _eflags |= CF; - else - _eflags &= ~CF; - D_printf("VTMR: running PM handler, masked=%i\n", masked); - } - - } else if (_eip==1+DPMI_SEL_OFF(DPMI_vtmr_post_irq)) { - int masked = !!(_eflags & CF); - vtmr_post_irq_dpmi(masked); - D_printf("VTMR: return from PM handler\n"); - - } else if (_eip==1+DPMI_SEL_OFF(DPMI_vrtc_irq)) { - if (DEFAULT_INT(0x70)) { - /* just jump to default entry that leads us to RM */ - D_printf("VRTC: jump to RM handler\n"); - _cs = DPMI_CLIENT.vrtc_prev.selector; - _eip = DPMI_CLIENT.vrtc_prev.offset32; - } else { - int masked = vrtc_pre_irq_dpmi(DPMI_CLIENT.imr); - if (masked) - _eflags |= CF; - else - _eflags &= ~CF; - D_printf("VRTC: running PM handler, masked=%i\n", masked); - } - - } else if (_eip==1+DPMI_SEL_OFF(DPMI_vrtc_post_irq)) { - int masked = !!(_eflags & CF); - vrtc_post_irq_dpmi(masked); - D_printf("VRTC: return from PM handler\n"); - - } else if (_eip==1+DPMI_SEL_OFF(DPMI_reinit)) { - dpmi_reinit(scp); - - } else if (_eip==1+DPMI_SEL_OFF(DPMI_shlock)) { - LockShared(scp, (_LWORD_(esi) << 16) | _LWORD_(edi), _LWORD_(edx)); - -#ifdef USE_DJDEV64 - } else if (_eip==1+DPMI_SEL_OFF(DPMI_dj64)) { - switch (_ebx) { - case 0: - if (_eax == 0) - dpmi_dj64_open(scp); - break; - case 1: - D_printf("DPMI: djdev64_close()\n"); - dpmi_dj64_close(scp); - break; - default: - error("dj64: unknown cmd %x\n", _eax); - break; - } -#endif - } else if (_eip==1+DPMI_SEL_OFF(DPMI_abort)) { - error("DPMI abort called\n"); - } else if ((_eip>=1+DPMI_SEL_OFF(DPMI_exception)) && (_eip<=32+DPMI_SEL_OFF(DPMI_exception))) { int excp = _eip-1-DPMI_SEL_OFF(DPMI_exception); + D_printf("DPMI: default exception handler 0x%02x called\n",excp); do_dpmi_retf(scp, sp); /* legacy (0.9) exceptions are routed to PM int handlers */ - leave_lpms(scp); return_from_exception(scp); - D_printf("DPMI: default exception handler 0x%02x called\n",excp); do_default_cpu_exception(scp, excp); } else if ((_eip>=1+DPMI_SEL_OFF(DPMI_ext_exception)) && (_eip<=32+DPMI_SEL_OFF(DPMI_ext_exception))) { @@ -5283,42 +4471,21 @@ static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) _cs = DPMI_CLIENT.Exception_Table[excp].selector; _eip = DPMI_CLIENT.Exception_Table[excp].offset; } else { - do_dpmi_retf(scp, sp); - leave_lpms(scp); - return_from_exception(scp); // also returns from ext exception /* 1.0 DPMI spec says this should go straight to RM */ cpu_exception_rm(scp, excp); } } else if ((_eip>=1+DPMI_SEL_OFF(DPMI_rm_exception)) && (_eip<=32+DPMI_SEL_OFF(DPMI_rm_exception))) { int excp = _eip-1-DPMI_SEL_OFF(DPMI_rm_exception); - do_dpmi_retf(scp, sp); - leave_lpms(scp); - return_from_exception(scp); D_printf("DPMI: default rm exception handler 0x%02x called\n",excp); - restore_pm_regs(scp); - dpmi_set_pm(0); - do_int(excp); + cpu_exception_rm(scp, excp); } else if ((_eip>=1+DPMI_SEL_OFF(DPMI_interrupt)) && (_eip<1+256+DPMI_SEL_OFF(DPMI_interrupt))) { int intr = _eip-1-DPMI_SEL_OFF(DPMI_interrupt); D_printf("DPMI: default protected mode interrupthandler 0x%02x called\n",intr); do_dpmi_iret(scp, sp); - sp = SEL_ADR(_ss, _esp); - /* Most progs actually jump to prev handler, not call it. - * See if this is the case. */ - if (_cs == dpmi_sel() && _eip == DPMI_SEL_OFF(DPMI_return_from_pm)) { - if (debug_level('M')>=9) - D_printf("DPMI: jump to prev handler in hwint, going to RM\n"); - return_from_hwint(scp, sp); - /* do similar to run_pm_int() */ - if (in_dpmi_pm()) - fake_pm_int(); - real_run_int(intr); - } else { - do_dpmi_int(scp, intr); - } + do_dpmi_int(scp, intr); } else if ((_eip>=1+DPMI_SEL_OFF(DPMI_VXD_start)) && (_eip<1+DPMI_SEL_OFF(DPMI_VXD_end))) { @@ -5341,35 +4508,17 @@ static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) } } -static void unprot_stack_page(cpuctx_t *scp) -{ - dosaddr_t p; - - if (Segments(_ss >> 3).is_32) - p = GetSegmentBase(_ss) + _esp; - else - p = GetSegmentBase(_ss) + _LWORD(esp); - - e_invalidate(p & _PAGE_MASK, PAGE_SIZE); - /* if ptr is on page boundary, then unprot also page below */ - if (!(p & (PAGE_SIZE - 1))) - e_invalidate(p - PAGE_SIZE, PAGE_SIZE); -} - -static int dpmi_gpf_simple(cpuctx_t *scp, uint8_t *lina, void *sp, int *rv) +static int dpmi_gpf_simple(sigcontext_t *scp, uint8_t *lina, void *sp, int *rv) { int hlt_cnt = 0; *rv = DPMI_RET_CLIENT; - - unprot_stack_page(scp); - if ((_err & 7) == 2) { /* int xx */ int inum = _err >> 3; if (inum != lina[1]) { error("DPMI: internal error, %x %x\n", inum, lina[1]); + p_dos_str("DPMI: internal error, %x %x\n", inum, lina[1]); quit_dpmi(scp, 0xff, 0, 0, 1); - p_direct_str("DPMI: internal error, %x %x\n", inum, lina[1]); return 1; } D_printf("DPMI: int 0x%04x, AX=0x%04x\n", inum, _LWORD(eax)); @@ -5386,12 +4535,13 @@ static int dpmi_gpf_simple(cpuctx_t *scp, uint8_t *lina, void *sp, int *rv) #endif /* Bypass the int instruction */ _eip += 2; - _err = 0; - if (DEFAULT_INT(inum)) { + if (DPMI_CLIENT.Interrupt_Table[inum].selector == dpmi_sel() && + DPMI_CLIENT.Interrupt_Table[inum].offset < + DPMI_SEL_OFF(DPMI_sel_end)) { do_dpmi_int(scp, inum); } else { - uint16_t cs2 = _cs; - uint32_t eip2 = _eip; + us cs2 = _cs; + unsigned long eip2 = _eip; if (debug_level('M')>=9) D_printf("DPMI: int 0x%x\n", lina[1]); make_iret_frame(scp, sp, _cs, _eip); @@ -5401,7 +4551,7 @@ static int dpmi_gpf_simple(cpuctx_t *scp, uint8_t *lina, void *sp, int *rv) _eflags &= ~(TF | NT | AC); _cs = DPMI_CLIENT.Interrupt_Table[inum].selector; _eip = DPMI_CLIENT.Interrupt_Table[inum].offset; - D_printf("DPMI: call inthandler %#02x(%#04x) at %#04x:%#08x\n\t\tret=%#04x:%#08x\n", + D_printf("DPMI: call inthandler %#02x(%#04x) at %#04x:%#08x\n\t\tret=%#04x:%#08lx\n", inum, _LWORD(eax), _cs, _eip, cs2, eip2); if ((inum == 0x2f)&&((_LWORD(eax)== 0xfb42)||(_LWORD(eax)==0xfb43))) @@ -5420,7 +4570,6 @@ static int dpmi_gpf_simple(cpuctx_t *scp, uint8_t *lina, void *sp, int *rv) hlt_cnt++; if (!dpmi_pm) break; - scp = &DPMI_CLIENT.stack_frame; // update, could change lina = (unsigned char *) SEL_ADR(_cs, _eip); sp = SEL_ADR(_ss, _esp); } while (*lina == 0xf4); @@ -5443,24 +4592,16 @@ static int dpmi_gpf_simple(cpuctx_t *scp, uint8_t *lina, void *sp, int *rv) break; } current_cli = lina; - /* look for - * "pushfd; pop eax; cli" (DOOM), + /* look for "pushfd; pop eax; cli" (DOOM), * "ret; pushfd; cli" (NFS-SE), - * "pusha; pushfd; cli" (drally), - * "pushfw; cli" (PoliceQuest4) - * "pushfw; pop ax; cli" (PoliceQuest4) - * patterns */ + * "pusha; pushfd; cli" (drally) patterns */ if (!in_dpmi_irq && _eip >= 2 && ((lina[-2] == 0x9c && lina[-1] == 0x58) || (lina[-2] == 0xc3 && lina[-1] == 0x9c) || - (lina[-2] == 0x60 && lina[-1] == 0x9c) || - (lina[-2] == 0x66 && lina[-1] == 0x9c) || - (_eip >= 4 && lina[-4] == 0x66 && lina[-3] == 0x9c && - lina[-2] == 0x66 && lina[-1] == 0x58) + (lina[-2] == 0x60 && lina[-1] == 0x9c) )) { D_printf("DOOM cli work-around\n"); - if (!dpmi_is_cli) - dpmi_is_cli = 1; + dpmi_is_cli = 1; } dpmi_cli(); break; @@ -5470,20 +4611,6 @@ static int dpmi_gpf_simple(cpuctx_t *scp, uint8_t *lina, void *sp, int *rv) D_printf("DPMI: sti\n"); _eip += 1; dpmi_sti(); - /* sti/iret must be atomic, no IRQs within */ - if (lina[1] == 0xcf) { - if (debug_level('M')>=9) - D_printf("DPMI: sti/iret detected\n"); - /* This may not be our HW inthandler, but some user's sw interrupt. - * Needs to call emu_dpmi_iret() that emulates iret more precisely. */ - emu_dpmi_iret(scp, sp); - sp = SEL_ADR(_ss, _esp); - if (_cs == dpmi_sel() && _eip == DPMI_SEL_OFF(DPMI_return_from_pm)) { - if (debug_level('M')>=9) - D_printf("DPMI: sti/iret of hwint\n"); - return_from_hwint(scp, sp); - } - } break; default: @@ -5509,11 +4636,11 @@ static int dpmi_gpf_simple(cpuctx_t *scp, uint8_t *lina, void *sp, int *rv) * * DANG_END_FUNCTION */ -static int dpmi_fault1(cpuctx_t *scp) +static int dpmi_fault1(sigcontext_t *scp) { -#define LWORD32(x,y) {if (Segments(_cs >> 3).is_32) _##x y; else _LWORD(x) y;} -#define ASIZE_IS_32 (Segments(_cs >> 3).is_32 ^ prefix67) -#define OSIZE_IS_32 (Segments(_cs >> 3).is_32 ^ prefix66) +#define LWORD32(x,y) {if (Segments[_cs >> 3].is_32) _##x y; else _LWORD(x) y;} +#define ASIZE_IS_32 (Segments[_cs >> 3].is_32 ^ prefix67) +#define OSIZE_IS_32 (Segments[_cs >> 3].is_32 ^ prefix66) /* both clear: non-prefixed in a 16-bit CS = 16-bit * one set: non-prefixed in 32-bit CS or prefixed in 16-bit CS = 32-bit * both set: prefixed in a 32-bit CS = 16-bit @@ -5533,8 +4660,8 @@ static int dpmi_fault1(cpuctx_t *scp) Note: we used to check for kernel space bits in the high part of ESP but that method is unreliable for 32-bit DOSEMU on x86-64 kernels. */ - if (_esp > 0xffff && !Segments(_cs >> 3).is_32 && Segments(_ss >> 3).is_32 && - Segments(_ss >> 3).type != MODIFY_LDT_CONTENTS_STACK && + if (_esp > 0xffff && !Segments[_cs >> 3].is_32 && Segments[_ss >> 3].is_32 && + Segments[_ss >> 3].type != MODIFY_LDT_CONTENTS_STACK && _esp > GetSegmentLimit(_ss)) { D_printf("DPMI: ESP bug, esp=%#x, ebp=%#x, limit=%#x\n", _esp, _ebp, GetSegmentLimit(_ss)); @@ -5581,17 +4708,8 @@ static int dpmi_fault1(cpuctx_t *scp) if (dpmi_gpf_simple(scp, csp, sp, &ret)) { /* can go to RM with LDT changes, either for * DOS memory or for termination - no other cases I hope? */ - if (!in_dpmi_pm()) - return ret; - scp = &DPMI_CLIENT.stack_frame; // update, could change - if (ldt_bitmap_cnt) + if (ldt_bitmap_cnt && in_dpmi_pm()) dpmi_ldt_call(scp); - lina = (unsigned char *) SEL_ADR(_cs, _eip); - sp = SEL_ADR(_ss, _esp); - if (*lina == 0xf4) { - D_printf("DPMI: more hlt to handle\n"); - dpmi_gpf_simple(scp, lina, sp, &ret); - } return ret; } @@ -5713,55 +4831,55 @@ static int dpmi_fault1(cpuctx_t *scp) case 0xe5: /* inw xx, ind xx */ if (debug_level('M')>=9) D_printf("DPMI: in%s xx\n", OSIZE_IS_32 ? "d" : "w"); - if (OSIZE_IS_32) _eax = port_ind((int) csp[0]); - else _LWORD(eax) = port_inw((int) csp[0]); + if (OSIZE_IS_32) _eax = ind((int) csp[0]); + else _LWORD(eax) = inw((int) csp[0]); LWORD32(eip, += 2); break; case 0xe4: /* inb xx */ if (debug_level('M')>=9) D_printf("DPMI: inb xx\n"); _LWORD(eax) &= ~0xff; - _LWORD(eax) |= port_inb((int) csp[0]); + _LWORD(eax) |= inb((int) csp[0]); LWORD32(eip, += 2); break; case 0xed: /* inw dx */ if (debug_level('M')>=9) D_printf("DPMI: in%s dx\n", OSIZE_IS_32 ? "d" : "w"); - if (OSIZE_IS_32) _eax = port_ind(_LWORD(edx)); - else _LWORD(eax) = port_inw(_LWORD(edx)); + if (OSIZE_IS_32) _eax = ind(_LWORD(edx)); + else _LWORD(eax) = inw(_LWORD(edx)); LWORD32(eip,++); break; case 0xec: /* inb dx */ if (debug_level('M')>=9) D_printf("DPMI: inb dx\n"); _LWORD(eax) &= ~0xff; - _LWORD(eax) |= port_inb(_LWORD(edx)); + _LWORD(eax) |= inb(_LWORD(edx)); LWORD32(eip, += 1); break; case 0xe7: /* outw xx */ if (debug_level('M')>=9) D_printf("DPMI: out%s xx\n", OSIZE_IS_32 ? "d" : "w"); - if (OSIZE_IS_32) port_outd((int)csp[0], _eax); - else port_outw((int)csp[0], _LWORD(eax)); + if (OSIZE_IS_32) outd((int)csp[0], _eax); + else outw((int)csp[0], _LWORD(eax)); LWORD32(eip, += 2); break; case 0xe6: /* outb xx */ if (debug_level('M')>=9) D_printf("DPMI: outb xx\n"); - port_outb((int) csp[0], _LO(ax)); + outb((int) csp[0], _LO(ax)); LWORD32(eip, += 2); break; case 0xef: /* outw dx */ if (debug_level('M')>=9) D_printf("DPMI: out%s dx\n", OSIZE_IS_32 ? "d" : "w"); - if (OSIZE_IS_32) port_outd(_LWORD(edx), _eax); - else port_outw(_LWORD(edx), _LWORD(eax)); + if (OSIZE_IS_32) outd(_LWORD(edx), _eax); + else outw(_LWORD(edx), _LWORD(eax)); LWORD32(eip, += 1); break; case 0xee: /* outb dx */ if (debug_level('M')>=9) D_printf("DPMI: outb dx\n"); - port_outb(_LWORD(edx), _LO(ax)); + outb(_LWORD(edx), _LO(ax)); LWORD32(eip, += 1); break; @@ -5776,7 +4894,7 @@ static int dpmi_fault1(cpuctx_t *scp) case 1: // SGDT, SIDT, SMSW ... switch (csp[1] & 0xc0) { case 0xc0: // register dest - /* just write 0 - no one uses SMSW in PM */ + /* just write 0 */ if (OSIZE_IS_32) *reg32[csp[1] & 7] = 0; else @@ -5785,11 +4903,11 @@ static int dpmi_fault1(cpuctx_t *scp) break; default: error("DPMI: unsupported SLDT dest %x\n", csp[1]); - LWORD32(eip, = org_eip + instr_len(lina, Segments(_cs>>3).is_32)); + LWORD32(eip, += 3); break; } break; - case 0x20: // mov r/m,crX + case 0x20: switch (csp[1] & 0xc0) { case 0xc0: // register dest /* just write 0 */ @@ -5800,16 +4918,16 @@ static int dpmi_fault1(cpuctx_t *scp) break; default: error("DPMI: unsupported mov xx,cr0 dest %x\n", csp[1]); - LWORD32(eip, = org_eip + instr_len(lina, Segments(_cs>>3).is_32)); + LWORD32(eip, += 3); break; } break; case 0x22: /* mov cr0, xx - ignore */ - LWORD32(eip, = org_eip + instr_len(lina, Segments(_cs>>3).is_32)); + LWORD32(eip, += 3); break; default: - D_printf("%s", DPMI_show_state(scp)); + error("%s", DPMI_show_state(scp)); goto out; } break; @@ -5822,7 +4940,7 @@ out: } /* _trapno==13 */ else { if (_trapno == 0x0c) { - if (Segments(_cs >> 3).is_32 && !Segments(_ss >> 3).is_32 && + if (Segments[_cs >> 3].is_32 && !Segments[_ss >> 3].is_32 && _esp > 0xffff) { unsigned char *p = csp; unsigned int *regs[8] = { &_eax, &_ecx, &_edx, &_ebx, @@ -5885,10 +5003,10 @@ out: "In that case try to convince Intel to fix that bug.\n" "Now patching the B bit, get your fingers crossed...\n", DPMI_show_state(scp)); - SetSelector(_ss, Segments(_ss >> 3).base_addr, Segments(_ss >> 3).limit, - 1, Segments(_ss >> 3).type, Segments(_ss >> 3).readonly, - Segments(_ss >> 3).is_big, - Segments(_ss >> 3).not_present, Segments(_ss >> 3).useable + SetSelector(_ss, Segments[_ss >> 3].base_addr, Segments[_ss >> 3].limit, + 1, Segments[_ss >> 3].type, Segments[_ss >> 3].readonly, + Segments[_ss >> 3].is_big, + Segments[_ss >> 3].not_present, Segments[_ss >> 3].useable ); return ret; #endif @@ -5902,9 +5020,24 @@ out: return ret; } +int dpmi_fault(sigcontext_t *scp) +{ + /* If this is an exception 0x11, we have to ignore it. The reason is that + * under real DOS the AM bit of CR0 is not set. + * Also clear the AC flag to prevent it from re-occuring. + */ + if (_trapno == 0x11) { + g_printf("Exception 0x11 occured, clearing AC\n"); + _eflags &= ~AC; + return DPMI_RET_CLIENT; + } + + return DPMI_RET_FAULT; // process the rest in dosemu context +} + void dpmi_realmode_hlt(unsigned int lina) { - cpuctx_t *scp; + sigcontext_t *scp; if (!in_dpmi) { D_printf("ERROR: DPMI call while not in dpmi!\n"); LWORD(eip)++; @@ -5932,44 +5065,32 @@ void dpmi_realmode_hlt(unsigned int lina) } else if (lina >= DPMI_ADD + HLT_OFF(DPMI_return_from_rmint) && lina < DPMI_ADD + HLT_OFF(DPMI_return_from_rmint) + DPMI_MAX_CLIENTS) { int i = lina - (DPMI_ADD + HLT_OFF(DPMI_return_from_rmint)); - int changed = post_rm_call(i); - if (changed) - scp = &DPMI_CLIENT.stack_frame; // refresh after post_rm_call() + post_rm_call(i); + scp = &DPMI_CLIENT.stack_frame; // refresh after post_rm_call() D_printf("DPMI: Return from RM Interrupt, client=%i\n", i); rm_to_pm_regs(&DPMI_CLIENT.stack_frame, ~0); restore_rm_regs(); dpmi_set_pm(1); - if (changed) - msdos_set_client(scp, current_client); } else if (lina >= DPMI_ADD + HLT_OFF(DPMI_return_from_realmode) && lina < DPMI_ADD + HLT_OFF(DPMI_return_from_realmode) + DPMI_MAX_CLIENTS) { int i = lina - (DPMI_ADD + HLT_OFF(DPMI_return_from_realmode)); - struct RealModeCallStructure *rmreg; - int changed = post_rm_call(i); - if (changed) - scp = &DPMI_CLIENT.stack_frame; // refresh after post_rm_call() - rmreg = SEL_ADR_X(_es, _edi); D_printf("DPMI: Return from Real Mode Procedure, clnt=%i\n", i); #if SHOWREGS if (debug_level('M') > 5) show_regs(); #endif + post_rm_call(i); + scp = &DPMI_CLIENT.stack_frame; // refresh after post_rm_call() /* remove passed arguments */ LWORD(esp) += 2 * _LWORD(ecx); - /* Some progs forget to reset stack for subsequent calls, which - * leads to problems. DPMI-1.0 spec says to not modify cs,ip,ss,sp. */ - DPMI_save_rm_regs(rmreg, ~((1 << ss_INDEX) | (1 << esp_INDEX) | - (1 << cs_INDEX) | (1 << eip_INDEX))); + DPMI_save_rm_regs(SEL_ADR_X(_es, _edi)); restore_rm_regs(); dpmi_set_pm(1); - if (changed) - msdos_set_client(scp, current_client); } else if (lina == DPMI_ADD + HLT_OFF(DPMI_return_from_dos_memory)) { - unsigned length; - dosaddr_t base; + unsigned long length, base; unsigned short begin_selector, num_descs; int i; @@ -6032,7 +5153,7 @@ done: dpmi_ldt_call(scp); } else if (lina == DPMI_ADD + HLT_OFF(DPMI_raw_mode_switch_rm)) { - if (!segment_user(LWORD(esi) >> 3)) { + if (!Segments[LWORD(esi) >> 3].used) { error("DPMI: PM switch to unused segment %x\n", LWORD(esi)); leavedos(61); } @@ -6070,16 +5191,16 @@ done: unsigned short *buffer = LINEAR2UNIX(buf); if (LO(ax)==0) { D_printf("DPMI: save protected mode registers\n"); - *(uint32_t *)buffer = _eflags, buffer += 2; - *(uint32_t *)buffer = _eax, buffer += 2; - *(uint32_t *)buffer = _ebx, buffer += 2; - *(uint32_t *)buffer = _ecx, buffer += 2; - *(uint32_t *)buffer = _edx, buffer += 2; - *(uint32_t *)buffer = _esi, buffer += 2; - *(uint32_t *)buffer = _edi, buffer += 2; - *(uint32_t *)buffer = _esp, buffer += 2; - *(uint32_t *)buffer = _ebp, buffer += 2; - *(uint32_t *)buffer = _eip, buffer += 2; + *(unsigned long *)buffer = _eflags, buffer += 2; + *(unsigned long *)buffer = _eax, buffer += 2; + *(unsigned long *)buffer = _ebx, buffer += 2; + *(unsigned long *)buffer = _ecx, buffer += 2; + *(unsigned long *)buffer = _edx, buffer += 2; + *(unsigned long *)buffer = _esi, buffer += 2; + *(unsigned long *)buffer = _edi, buffer += 2; + *(unsigned long *)buffer = _esp, buffer += 2; + *(unsigned long *)buffer = _ebp, buffer += 2; + *(unsigned long *)buffer = _eip, buffer += 2; /* 10 regs, 40 bytes */ *buffer++ = _cs; *buffer++ = _ds; @@ -6092,16 +5213,16 @@ done: * so the segment regs are saved as 2-bytes. */ } else { D_printf("DPMI: restore protected mode registers\n"); - _eflags = *(uint32_t *)buffer, buffer += 2; - _eax = *(uint32_t *)buffer, buffer += 2; - _ebx = *(uint32_t *)buffer, buffer += 2; - _ecx = *(uint32_t *)buffer, buffer += 2; - _edx = *(uint32_t *)buffer, buffer += 2; - _esi = *(uint32_t *)buffer, buffer += 2; - _edi = *(uint32_t *)buffer, buffer += 2; - _esp = *(uint32_t *)buffer, buffer += 2; - _ebp = *(uint32_t *)buffer, buffer += 2; - _eip = *(uint32_t *)buffer, buffer += 2; + _eflags = *(unsigned long *)buffer, buffer += 2; + _eax = *(unsigned long *)buffer, buffer += 2; + _ebx = *(unsigned long *)buffer, buffer += 2; + _ecx = *(unsigned long *)buffer, buffer += 2; + _edx = *(unsigned long *)buffer, buffer += 2; + _esi = *(unsigned long *)buffer, buffer += 2; + _edi = *(unsigned long *)buffer, buffer += 2; + _esp = *(unsigned long *)buffer, buffer += 2; + _ebp = *(unsigned long *)buffer, buffer += 2; + _eip = *(unsigned long *)buffer, buffer += 2; /* 10 regs, 40 bytes */ _cs = *buffer++; _ds = *buffer++; @@ -6115,38 +5236,18 @@ done: } REG(eip) += 1; /* skip halt to point to FAR RET */ - } else if (lina >= DPMI_ADD + HLT_OFF(DPMI_int1c) && - lina < DPMI_ADD + HLT_OFF(DPMI_int1c_end)) { - int i = (lina - (DPMI_ADD + HLT_OFF(DPMI_int1c))) / 3; - if (i == current_client) { - REG(eip) += 1; - run_pm_dos_int(0x1c); - } else - jmp_to(DPMIclient[i].s_i1c.segment, DPMIclient[i].s_i1c.offset); - - } else if (lina >= DPMI_ADD + HLT_OFF(DPMI_int23) && - lina < DPMI_ADD + HLT_OFF(DPMI_int23_end)) { - int i = (lina - (DPMI_ADD + HLT_OFF(DPMI_int23))) / 3; - assert(i <= current_client); - if (i == current_client) - REG(eip) += 1; - else - jmp_to(DPMIclient[i].s_i23.segment, DPMIclient[i].s_i23.offset); + } else if (lina == DPMI_ADD + HLT_OFF(DPMI_int1c)) { + REG(eip) += 1; + run_pm_dos_int(0x1c); } else if (lina == DPMI_ADD + HLT_OFF(DPMI_int23_1)) { REG(eip) += 1; DPMI_CLIENT.int23_psp = LWORD(ebx); } else if (lina == DPMI_ADD + HLT_OFF(DPMI_int23_2)) { REG(eip) += 1; run_pm_dos_int(0x23); - - } else if (lina >= DPMI_ADD + HLT_OFF(DPMI_int24) && - lina < DPMI_ADD + HLT_OFF(DPMI_int24_end)) { - int i = (lina - (DPMI_ADD + HLT_OFF(DPMI_int24))) / 3; - if (i == current_client) { - REG(eip) += 1; - run_pm_dos_int(0x24); - } else - jmp_to(DPMIclient[i].s_i24.segment, DPMIclient[i].s_i24.offset); + } else if (lina == DPMI_ADD + HLT_OFF(DPMI_int24)) { + REG(eip) += 1; + run_pm_dos_int(0x24); } else { D_printf("DPMI: unhandled HLT: lina=%#x\n", lina); @@ -6156,7 +5257,7 @@ done: int DPMIValidSelector(unsigned short selector) { /* does this selector refer to the LDT? */ - return segment_user(selector >> 3) != 0xfe && (selector & 4); + return Segments[selector >> 3].used != 0xfe && (selector & 4); } uint8_t *dpmi_get_ldt_buffer(void) @@ -6166,14 +5267,14 @@ uint8_t *dpmi_get_ldt_buffer(void) int dpmi_segment_is32(int sel) { - return (Segments(sel >> 3).is_32); + return (Segments[sel >> 3].is_32); } #ifdef USE_MHPDBG /* dosdebug support */ int dpmi_mhp_regs(void) { - cpuctx_t *scp; + sigcontext_t *scp; if (!in_dpmi || !in_dpmi_pm()) return 0; scp=&DPMI_CLIENT.stack_frame; mhp_printf("\nEAX: %08x EBX: %08x ECX: %08x EDX: %08x eflags: %08x", @@ -6186,7 +5287,7 @@ int dpmi_mhp_regs(void) void dpmi_mhp_getcseip(unsigned int *seg, unsigned int *off) { - cpuctx_t *scp = &DPMI_CLIENT.stack_frame; + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; *seg = _cs; *off = _eip; @@ -6194,13 +5295,13 @@ void dpmi_mhp_getcseip(unsigned int *seg, unsigned int *off) void dpmi_mhp_modify_eip(int delta) { - cpuctx_t *scp = &DPMI_CLIENT.stack_frame; + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; _eip +=delta; } void dpmi_mhp_getssesp(unsigned int *seg, unsigned int *off) { - cpuctx_t *scp = &DPMI_CLIENT.stack_frame; + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; *seg = _ss; *off = _esp; @@ -6208,7 +5309,7 @@ void dpmi_mhp_getssesp(unsigned int *seg, unsigned int *off) int dpmi_mhp_getcsdefault(void) { - cpuctx_t *scp = &DPMI_CLIENT.stack_frame; + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; return dpmi_segment_is32(_cs); } @@ -6217,9 +5318,9 @@ void dpmi_mhp_GetDescriptor(unsigned short selector, unsigned int *lp) memcpy(lp, &ldt_buffer[selector & 0xfff8], 8); } -uint32_t dpmi_mhp_getreg(regnum_t regnum) +unsigned long dpmi_mhp_getreg(regnum_t regnum) { - cpuctx_t *scp; + sigcontext_t *scp; assert(in_dpmi && in_dpmi_pm()); @@ -6256,9 +5357,9 @@ uint32_t dpmi_mhp_getreg(regnum_t regnum) return -1; // keep compiler happy, control never reaches here } -void dpmi_mhp_setreg(regnum_t regnum, uint32_t val) +void dpmi_mhp_setreg(regnum_t regnum, unsigned long val) { - cpuctx_t *scp; + sigcontext_t *scp; assert(in_dpmi && in_dpmi_pm()); @@ -6295,7 +5396,7 @@ void dpmi_mhp_setreg(regnum_t regnum, uint32_t val) } } -static int dpmi_mhp_intxx_pending(cpuctx_t *scp, int intno) +static int dpmi_mhp_intxx_pending(sigcontext_t *scp, int intno) { if (dpmi_mhp_intxxtab[intno] & 1) { if (dpmi_mhp_intxxtab[intno] & 0x80) { @@ -6306,7 +5407,7 @@ static int dpmi_mhp_intxx_pending(cpuctx_t *scp, int intno) return 0; } -static int dpmi_mhp_intxx_check(cpuctx_t *scp, int intno) +static int dpmi_mhp_intxx_check(sigcontext_t *scp, int intno) { switch (dpmi_mhp_intxx_pending(scp,intno)) { case -1: return DPMI_RET_CLIENT; @@ -6321,7 +5422,7 @@ static int dpmi_mhp_intxx_check(cpuctx_t *scp, int intno) int dpmi_mhp_setTF(int on) { - cpuctx_t *scp; + sigcontext_t *scp; if (!in_dpmi_pm()) return 0; scp=&DPMI_CLIENT.stack_frame; @@ -6330,15 +5431,6 @@ int dpmi_mhp_setTF(int on) return 1; } -int dpmi_mhp_issetTF(void) -{ - cpuctx_t *scp; - if (!in_dpmi_pm()) - return 0; - scp=&DPMI_CLIENT.stack_frame; - return !!(_eflags & TF); -} - #endif /* dosdebug support */ static void add_cli_to_blacklist(unsigned char *addr) @@ -6366,6 +5458,16 @@ static int find_cli_in_blacklist(unsigned char *cur_cli) return 0; } +void dpmi_return_request(void) +{ + return_requested = 1; +} + +int dpmi_check_return(void) +{ + return return_requested ? DPMI_RET_DOSEMU : DPMI_RET_CLIENT; +} + int in_dpmi_pm(void) { return dpmi_pm; @@ -6376,19 +5478,10 @@ int dpmi_active(void) return in_dpmi; } -void dpmi_done0(void) -{ - D_printf("DPMI: finalizing, stage 0\n"); - dpmi_reset(); -} - void dpmi_done(void) { - int i; - - if (!config.dpmi) return; - D_printf("DPMI: finalizing\n"); + current_client = in_dpmi - 1; while (in_dpmi) { if (in_dpmi_pm()) @@ -6396,23 +5489,21 @@ void dpmi_done(void) dpmi_cleanup(); } - for (i = 0; i < RSP_num; i++) - DPMIfreeAll(&RSP_callbacks[i].pm_block_root); - DPMIfreeAll(&host_pm_block_root); + DPMI_freeAll(&host_pm_block_root); dpmi_free_pool(); native_dpmi_done(); } /* for debug only */ -cpuctx_t *dpmi_get_scp(void) +sigcontext_t *dpmi_get_scp(void) { if (!in_dpmi) return NULL; return &DPMI_CLIENT.stack_frame; } -static uint16_t decode_selector(cpuctx_t *scp) +static uint16_t decode_selector(sigcontext_t *scp) { int done, pref_seg; uint8_t *csp; @@ -6442,14 +5533,14 @@ static uint16_t decode_selector(cpuctx_t *scp) return pref_seg; } -char *DPMI_show_state(cpuctx_t *scp) +char *DPMI_show_state(sigcontext_t *scp) { static char buf[4096]; int pos = 0; unsigned char *csp2, *ssp2; dosaddr_t daddr, saddr; pos += sprintf(buf + pos, "eip: 0x%08x esp: 0x%08x eflags: 0x%08x\n" - "\ttrapno: 0x%02x errorcode: 0x%08x cr2: 0x%08x\n" + "\ttrapno: 0x%02x errorcode: 0x%08x cr2: 0x%08"PRI_RG"\n" "\tcs: 0x%04x ds: 0x%04x es: 0x%04x ss: 0x%04x fs: 0x%04x gs: 0x%04x\n", _eip, _esp, _eflags, _trapno, _err, _cr2, _cs, _ds, _es, _ss, _fs, _gs); pos += sprintf(buf + pos, "EAX: %08x EBX: %08x ECX: %08x EDX: %08x\n", @@ -6471,7 +5562,7 @@ char *DPMI_show_state(cpuctx_t *scp) else { /* LDT */ csp2 = SEL_ADR(_cs, _eip); - daddr = GetSegmentBase(_cs) + client_eip(scp); + daddr = GetSegmentBase(_cs) + D_16_32(_eip); } /* We have a problem here, if we get a page fault or any kind of * 'not present' error and then we try accessing the code/stack @@ -6514,7 +5605,7 @@ char *DPMI_show_state(cpuctx_t *scp) else { /* LDT */ ssp2 = SEL_ADR(_ss, _esp); - saddr = GetSegmentBase(_ss) + client_esp(scp); + saddr = GetSegmentBase(_ss) + D_16_32(_esp); } #define SSPP (ssp2 - 10) pos += sprintf(buf + pos, "STACK: "); @@ -6544,11 +5635,9 @@ char *DPMI_show_state(cpuctx_t *scp) pos += sprintf(buf + pos, "GPF on selector 0x%x base=%08x lim=%x\n", sel, GetSegmentBase(sel), GetSegmentLimit(sel)); #if WITH_DPMI - if (config.pm_dos_api && DPMI_CLIENT.RSP_num) { - msd_dsc = msdos_describe_selector(sel); - if (msd_dsc) - pos += sprintf(buf + pos, "MSDOS selector: %s\n", msd_dsc); - } + msd_dsc = msdos_describe_selector(sel); + if (msd_dsc) + pos += sprintf(buf + pos, "MSDOS selector: %s\n", msd_dsc); #endif } @@ -6557,9 +5646,8 @@ char *DPMI_show_state(cpuctx_t *scp) void dpmi_timer(void) { - if (dpmi_pm && !DPMI_CLIENT.in_dpmi_pm_stack && - config.cli_timeout && dpmi_is_cli) { - cpuctx_t *scp = &DPMI_CLIENT.stack_frame; + if (dpmi_pm && config.cli_timeout && dpmi_is_cli) { + sigcontext_t *scp = &DPMI_CLIENT.stack_frame; /* XXX as IF is not set by popf, we have to set it explicitly after a reasonable delay. This will allow Doom to work with sound one day. diff --git a/src/dosext/dpmi/dpmi_api.c b/src/dosext/dpmi/dpmi_api.c index fe1d07e..35b9667 100644 --- a/src/dosext/dpmi/dpmi_api.c +++ b/src/dosext/dpmi/dpmi_api.c @@ -20,7 +20,6 @@ * Author: Stas Sergeev */ #include -#include #include "smalloc.h" #include "emudpmi.h" #include "dpmisel.h" @@ -36,9 +35,9 @@ static smpool apool; #define POOL_OFS(p) ((unsigned char *)(p) - pool_base) -static void do_callf(cpuctx_t *scp, int is_32, struct pmaddr_s pma) +static void do_callf(sigcontext_t *scp, int is_32, struct pmaddr_s pma) { - void *sp = SEL_ADR(_ss, _esp); + void *sp = SEL_ADR_CLNT(_ss, _esp, is_32); if (is_32) { unsigned int *ssp = sp; *--ssp = _cs; @@ -52,303 +51,164 @@ static void do_callf(cpuctx_t *scp, int is_32, struct pmaddr_s pma) } _cs = pma.selector; _eip = pma.offset; - coopth_sched(); } -static void do_dpmi_callf(cpuctx_t *scp, int is_32) -{ - struct pmaddr_s pma = { - .offset = DPMI_SEL_OFF(DPMI_call), - .selector = dpmi_sel(), - }; - do_callf(scp, is_32, pma); -} - -void _dpmi_yield(cpuctx_t *scp, int is_32) +void _dpmi_yield(sigcontext_t *scp, int is_32) { /* INT 0x2F AX=1680 */ - struct pmaddr_s pma = { - .offset = DPMI_SEL_OFF(DPMI_int2f), - .selector = dpmi_sel(), - }; - cpuctx_t sa = *scp; - _eax = 0x1680; - do_callf(scp, is_32, pma); - *scp = sa; } -int _dpmi_allocate_ldt_descriptors(cpuctx_t *scp, int is_32, int _count) +int _dpmi_allocate_ldt_descriptors(sigcontext_t *scp, int is_32, int _count) { /* DPMI 0.9 AX=0000 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0; - _ecx = _count; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - else - ret = _eax; - *scp = sa; - return ret; + return 0; } -int _dpmi_free_ldt_descriptor(cpuctx_t *scp, int is_32, int _descriptor) +int _dpmi_free_ldt_descriptor(sigcontext_t *scp, int is_32, int _descriptor) { /* DPMI 0.9 AX=0001 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 1; - _ebx = _descriptor; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - *scp = sa; - return ret; + return 0; } -int _dpmi_segment_to_descriptor(cpuctx_t *scp, int is_32, int _segment) +int _dpmi_segment_to_descriptor(sigcontext_t *scp, int is_32, int _segment) { /* DPMI 0.9 AX=0002 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 2; - _ebx = _segment; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - else - ret = _eax; - *scp = sa; - return ret; + return 0; } -int _dpmi_get_selector_increment_value(cpuctx_t *scp, int is_32) +int _dpmi_get_selector_increment_value(sigcontext_t *scp, int is_32) { /* DPMI 0.9 AX=0003 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 3; - do_dpmi_callf(scp, is_32); - ret = _eax; - *scp = sa; - return ret; + return 0; } -int _dpmi_get_segment_base_address(cpuctx_t *scp, int is_32, int _selector, ULONG *_addr) +int _dpmi_get_segment_base_address(sigcontext_t *scp, int is_32, int _selector, ULONG *_addr) { /* DPMI 0.9 AX=0006 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 6; - _ebx = _selector; - _ecx = _edx = 0; // clear high parts - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - else - *_addr = (_ecx << 16) | _edx; - *scp = sa; - return ret; + return 0; } -int _dpmi_set_segment_base_address(cpuctx_t *scp, int is_32, int _selector, ULONG _address) +int _dpmi_set_segment_base_address(sigcontext_t *scp, int is_32, int _selector, ULONG _address) { /* DPMI 0.9 AX=0007 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 7; - _ebx = _selector; - _ecx = _address >> 16; - _edx = _address & 0xffff; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - *scp = sa; - return ret; + return 0; } -ULONG _dpmi_get_segment_limit(cpuctx_t *scp, int is_32, int _selector) +ULONG _dpmi_get_segment_limit(sigcontext_t *scp, int is_32, int _selector) { /* LSL instruction */ return 0; } -int _dpmi_set_segment_limit(cpuctx_t *scp, int is_32, int _selector, ULONG _limit) +int _dpmi_set_segment_limit(sigcontext_t *scp, int is_32, int _selector, ULONG _limit) { /* DPMI 0.9 AX=0008 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 8; - _ebx = _selector; - _ecx = _limit >> 16; - _edx = _limit & 0xffff; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - *scp = sa; - return ret; + return 0; } -int _dpmi_get_descriptor_access_rights(cpuctx_t *scp, int is_32, int _selector) +int _dpmi_get_descriptor_access_rights(sigcontext_t *scp, int is_32, int _selector) { /* LAR instruction */ return 0; } -int _dpmi_set_descriptor_access_rights(cpuctx_t *scp, int is_32, int _selector, int _rights) +int _dpmi_set_descriptor_access_rights(sigcontext_t *scp, int is_32, int _selector, int _rights) { /* DPMI 0.9 AX=0009 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 9; - _ebx = _selector; - _ecx = _rights; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - *scp = sa; - return ret; + return 0; } -int _dpmi_create_alias_descriptor(cpuctx_t *scp, int is_32, int _selector) +int _dpmi_create_alias_descriptor(sigcontext_t *scp, int is_32, int _selector) { /* DPMI 0.9 AX=000a */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0xa; - _ebx = _selector; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - else - ret = _eax; - *scp = sa; - return ret; + return 0; } -int _dpmi_get_descriptor(cpuctx_t *scp, int is_32, int _selector, void *_buffer) +int _dpmi_get_descriptor(sigcontext_t *scp, int is_32, int _selector, void *_buffer) { /* DPMI 0.9 AX=000b */ return 0; } -int _dpmi_set_descriptor(cpuctx_t *scp, int is_32, int _selector, void *_buffer) +int _dpmi_set_descriptor(sigcontext_t *scp, int is_32, int _selector, void *_buffer) { /* DPMI 0.9 AX=000c */ return 0; } -int _dpmi_allocate_specific_ldt_descriptor(cpuctx_t *scp, int is_32, int _selector) +int _dpmi_allocate_specific_ldt_descriptor(sigcontext_t *scp, int is_32, int _selector) { /* DPMI 0.9 AX=000d */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0xd; - _ebx = _selector; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - *scp = sa; - return ret; + return 0; } -int _dpmi_get_multiple_descriptors(cpuctx_t *scp, int is_32, int _count, void *_buffer) +int _dpmi_get_multiple_descriptors(sigcontext_t *scp, int is_32, int _count, void *_buffer) { /* DPMI 1.0 AX=000e */ return 0; } -int _dpmi_set_multiple_descriptors(cpuctx_t *scp, int is_32, int _count, void *_buffer) +int _dpmi_set_multiple_descriptors(sigcontext_t *scp, int is_32, int _count, void *_buffer) { /* DPMI 1.0 AX=000f */ return 0; } -int _dpmi_allocate_dos_memory(cpuctx_t *scp, int is_32, int _paragraphs, int *_ret_selector_or_max) +int _dpmi_allocate_dos_memory(sigcontext_t *scp, int is_32, int _paragraphs, int *_ret_selector_or_max) { /* DPMI 0.9 AX=0100 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x100; - _ebx = _paragraphs; - _edx = 0; // clear high part - do_dpmi_callf(scp, is_32); - if (_eflags & CF) { - ret = -1; - *_ret_selector_or_max = _ebx; - } else { - ret = _eax; - *_ret_selector_or_max = _edx; - } - *scp = sa; - return ret; + return 0; } -int _dpmi_free_dos_memory(cpuctx_t *scp, int is_32, int _selector) +int _dpmi_free_dos_memory(sigcontext_t *scp, int is_32, int _selector) { /* DPMI 0.9 AX=0101 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x101; - _edx = _selector; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - *scp = sa; - return ret; + return 0; } -int _dpmi_resize_dos_memory(cpuctx_t *scp, int is_32, int _selector, int _newpara, int *_ret_max) +int _dpmi_resize_dos_memory(sigcontext_t *scp, int is_32, int _selector, int _newpara, int *_ret_max) { /* DPMI 0.9 AX=0102 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x102; - _ebx = _newpara; - _edx = _selector; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) { - ret = -1; - *_ret_max = _ebx; - } - *scp = sa; - return ret; + return 0; } -int _dpmi_get_real_mode_interrupt_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_raddr *_address) +int _dpmi_get_real_mode_interrupt_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_raddr *_address) { /* DPMI 0.9 AX=0200 */ return 0; } -int _dpmi_set_real_mode_interrupt_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_raddr *_address) +int _dpmi_set_real_mode_interrupt_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_raddr *_address) { /* DPMI 0.9 AX=0201 */ return 0; } -int _dpmi_get_processor_exception_handler_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address) +int _dpmi_get_processor_exception_handler_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address) { /* DPMI 0.9 AX=0202 */ return 0; } -int _dpmi_set_processor_exception_handler_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address) +int _dpmi_set_processor_exception_handler_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address) { /* DPMI 0.9 AX=0203 */ return 0; } -int _dpmi_get_protected_mode_interrupt_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address) +int _dpmi_get_protected_mode_interrupt_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address) { /* DPMI 0.9 AX=0204 */ return 0; } -int _dpmi_set_protected_mode_interrupt_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address) +int _dpmi_set_protected_mode_interrupt_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address) { /* DPMI 0.9 AX=0205 */ return 0; } -int _dpmi_get_extended_exception_handler_vector_pm(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address) +int _dpmi_get_extended_exception_handler_vector_pm(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address) { /* DPMI 1.0 AX=0210 */ return 0; } -int _dpmi_get_extended_exception_handler_vector_rm(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address) +int _dpmi_get_extended_exception_handler_vector_rm(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address) { /* DPMI 1.0 AX=0211 */ return 0; } -int _dpmi_set_extended_exception_handler_vector_pm(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address) +int _dpmi_set_extended_exception_handler_vector_pm(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address) { /* DPMI 1.0 AX=0212 */ return 0; } -int _dpmi_set_extended_exception_handler_vector_rm(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address) +int _dpmi_set_extended_exception_handler_vector_rm(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address) { /* DPMI 1.0 AX=0213 */ return 0; } -int _dpmi_simulate_real_mode_interrupt(cpuctx_t *scp, int is_32, int _vector, __dpmi_regs *__regs) +int _dpmi_simulate_real_mode_interrupt(sigcontext_t *scp, int is_32, int _vector, __dpmi_regs *_regs) { /* DPMI 0.9 AX=0300 */ - cpuctx_t sa = *scp; + struct pmaddr_s pma = { + .offset = DPMI_SEL_OFF(DPMI_call), + .selector = dpmi_sel(), + }; + sigcontext_t sa = *scp; __dpmi_regs *regs = smalloc(&apool, sizeof(*regs)); _eax = 0x300; @@ -356,19 +216,24 @@ int _dpmi_simulate_real_mode_interrupt(cpuctx_t *scp, int is_32, int _vector, __ _ecx = 0; _es = data_sel; _edi = POOL_OFS(regs); - memcpy(regs, __regs, sizeof(*regs)); + memcpy(regs, _regs, sizeof(*regs)); + do_callf(scp, is_32, pma); D_printf("MSDOS: sched to dos thread for int 0x%x\n", _vector); - do_dpmi_callf(scp, is_32); + coopth_sched(); D_printf("MSDOS: return from dos thread\n"); - memcpy(__regs, regs, sizeof(*regs)); + memcpy(_regs, regs, sizeof(*regs)); smfree(&apool, regs); *scp = sa; return 0; } -int _dpmi_int(cpuctx_t *scp, int is_32, int _vector, __dpmi_regs *__regs) +int _dpmi_int(sigcontext_t *scp, int is_32, int _vector, __dpmi_regs *_regs) { /* like above, but sets ss sp fl */ /* DPMI 0.9 AX=0300 */ - cpuctx_t sa = *scp; + struct pmaddr_s pma = { + .offset = DPMI_SEL_OFF(DPMI_call), + .selector = dpmi_sel(), + }; + sigcontext_t sa = *scp; __dpmi_regs *regs = smalloc(&apool, sizeof(*regs)); _eax = 0x300; @@ -376,79 +241,58 @@ int _dpmi_int(cpuctx_t *scp, int is_32, int _vector, __dpmi_regs *__regs) _ecx = 0; _es = data_sel; _edi = POOL_OFS(regs); - __regs->x.ss = __dpmi_int_ss; - __regs->x.sp = __dpmi_int_sp; - __regs->x.flags = __dpmi_int_flags; - memcpy(regs, __regs, sizeof(*regs)); + _regs->x.ss = __dpmi_int_ss; + _regs->x.sp = __dpmi_int_sp; + _regs->x.flags = __dpmi_int_flags; + memcpy(regs, _regs, sizeof(*regs)); + do_callf(scp, is_32, pma); D_printf("MSDOS: sched to dos thread for int 0x%x\n", _vector); - do_dpmi_callf(scp, is_32); + coopth_sched(); D_printf("MSDOS: return from dos thread\n"); - memcpy(__regs, regs, sizeof(*regs)); + memcpy(_regs, regs, sizeof(*regs)); smfree(&apool, regs); *scp = sa; return 0; } -static void do_procedure_retf(cpuctx_t *scp, - int is_32, __dpmi_regs *__regs, int words) +int _dpmi_simulate_real_mode_procedure_retf(sigcontext_t *scp, int is_32, __dpmi_regs *_regs) { /* DPMI 0.9 AX=0301 */ struct pmaddr_s pma = { - .offset = DPMI_SEL_OFF(DPMI_call_args), + .offset = DPMI_SEL_OFF(DPMI_call), .selector = dpmi_sel(), }; - struct pmaddr_s pma16 = { - .offset = DPMI_SEL_OFF(DPMI_call_args16), - .selector = dpmi_sel(), - }; - cpuctx_t sa = *scp; + sigcontext_t sa = *scp; __dpmi_regs *regs = smalloc(&apool, sizeof(*regs)); _eax = 0x301; _ebx = 0; - _ecx = words; + _ecx = 0; _es = data_sel; _edi = POOL_OFS(regs); - memcpy(regs, __regs, sizeof(*regs)); + memcpy(regs, _regs, sizeof(*regs)); + do_callf(scp, is_32, pma); D_printf("MSDOS: sched to dos thread for call to %x:%x\n", - __regs->x.cs, __regs->x.ip); - do_callf(scp, is_32, is_32 ? pma : pma16); + _regs->x.cs, _regs->x.ip); + coopth_sched(); D_printf("MSDOS: return from dos thread\n"); - memcpy(__regs, regs, sizeof(*regs)); + memcpy(_regs, regs, sizeof(*regs)); smfree(&apool, regs); *scp = sa; -} - -int _dpmi_simulate_real_mode_procedure_retf(cpuctx_t *scp, int is_32, - __dpmi_regs *__regs) -{ /* DPMI 0.9 AX=0301 */ - do_procedure_retf(scp, is_32, __regs, 0); return 0; } -int _dpmi_simulate_real_mode_procedure_retf_stack(cpuctx_t *scp, int is_32, - __dpmi_regs *__regs, int stack_words_to_copy, const void *stack_data) +int _dpmi_simulate_real_mode_procedure_retf_stack(sigcontext_t *scp, int is_32, __dpmi_regs *_regs, int stack_words_to_copy, const void *stack_data) { /* DPMI 0.9 AX=0301 */ - unsigned short *sp = SEL_ADR_CLNT(_ss, _esp, is_32); - const unsigned short *d = stack_data; - int i; - - for (i = 0; i < stack_words_to_copy; i++) - *--sp = d[stack_words_to_copy - 1 - i]; - if (is_32) - _esp -= stack_words_to_copy * 2; - else - _LWORD(esp) -= stack_words_to_copy * 2; - do_procedure_retf(scp, is_32, __regs, stack_words_to_copy); - if (is_32) - _esp += stack_words_to_copy * 2; - else - _LWORD(esp) += stack_words_to_copy * 2; return 0; } -int _dpmi_simulate_real_mode_procedure_iret(cpuctx_t *scp, int is_32, __dpmi_regs *__regs) +int _dpmi_simulate_real_mode_procedure_iret(sigcontext_t *scp, int is_32, __dpmi_regs *_regs) { /* DPMI 0.9 AX=0302 */ - cpuctx_t sa = *scp; + struct pmaddr_s pma = { + .offset = DPMI_SEL_OFF(DPMI_call), + .selector = dpmi_sel(), + }; + sigcontext_t sa = *scp; __dpmi_regs *regs = smalloc(&apool, sizeof(*regs)); _eax = 0x302; @@ -456,344 +300,237 @@ int _dpmi_simulate_real_mode_procedure_iret(cpuctx_t *scp, int is_32, __dpmi_reg _ecx = 0; _es = data_sel; _edi = POOL_OFS(regs); - memcpy(regs, __regs, sizeof(*regs)); + memcpy(regs, _regs, sizeof(*regs)); + do_callf(scp, is_32, pma); D_printf("MSDOS: sched to dos thread for call to %x:%x\n", - __regs->x.cs, __regs->x.ip); - do_dpmi_callf(scp, is_32); + _regs->x.cs, _regs->x.ip); + coopth_sched(); D_printf("MSDOS: return from dos thread\n"); - memcpy(__regs, regs, sizeof(*regs)); + memcpy(_regs, regs, sizeof(*regs)); smfree(&apool, regs); *scp = sa; return 0; } -int _dpmi_allocate_real_mode_callback(cpuctx_t *scp, int is_32, void (*_handler)(void), __dpmi_regs *__regs, __dpmi_raddr *_ret) +int _dpmi_allocate_real_mode_callback(sigcontext_t *scp, int is_32, void (*_handler)(void), __dpmi_regs *_regs, __dpmi_raddr *_ret) { /* DPMI 0.9 AX=0303 */ return 0; } -int _dpmi_free_real_mode_callback(cpuctx_t *scp, int is_32, __dpmi_raddr *_addr) +int _dpmi_free_real_mode_callback(sigcontext_t *scp, int is_32, __dpmi_raddr *_addr) { /* DPMI 0.9 AX=0304 */ return 0; } -int _dpmi_get_state_save_restore_addr(cpuctx_t *scp, int is_32, __dpmi_raddr *_rm, __dpmi_paddr *_pm) +int _dpmi_get_state_save_restore_addr(sigcontext_t *scp, int is_32, __dpmi_raddr *_rm, __dpmi_paddr *_pm) { /* DPMI 0.9 AX=0305 */ return 0; } -int _dpmi_get_raw_mode_switch_addr(cpuctx_t *scp, int is_32, __dpmi_raddr *_rm, __dpmi_paddr *_pm) +int _dpmi_get_raw_mode_switch_addr(sigcontext_t *scp, int is_32, __dpmi_raddr *_rm, __dpmi_paddr *_pm) { /* DPMI 0.9 AX=0306 */ return 0; } -int _dpmi_get_version(cpuctx_t *scp, int is_32, __dpmi_version_ret *_ret) +int _dpmi_get_version(sigcontext_t *scp, int is_32, __dpmi_version_ret *_ret) { /* DPMI 0.9 AX=0400 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x400; - _ebx = _edx = 0; // clear high part - do_dpmi_callf(scp, is_32); - if (_eflags & CF) { - ret = -1; - } else { - _ret->major = (_eax >> 8) & 0xff; - _ret->minor = _eax & 0xff; - _ret->flags = _ebx; - _ret->cpu = _ecx & 0xff; - _ret->master_pic = (_edx >> 8) & 0xff; - _ret->slave_pic = _edx & 0xff; - } - *scp = sa; - return ret; + return 0; } -int _dpmi_get_capabilities(cpuctx_t *scp, int is_32, int *_flags, char *vendor_info) +int _dpmi_get_capabilities(sigcontext_t *scp, int is_32, int *_flags, char *vendor_info) { /* DPMI 1.0 AX=0401 */ return 0; } -int _dpmi_get_free_memory_information(cpuctx_t *scp, int is_32, __dpmi_free_mem_info *_info) +int _dpmi_get_free_memory_information(sigcontext_t *scp, int is_32, __dpmi_free_mem_info *_info) { /* DPMI 0.9 AX=0500 */ return 0; } -int _dpmi_allocate_memory(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_allocate_memory(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 0.9 AX=0501 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x501; - _ebx = _info->size >> 16; - _ecx = _info->size & 0xffff; - _esi = _edi = 0; // clear high parts - do_dpmi_callf(scp, is_32); - if (_eflags & CF) { - ret = -1; - } else { - _info->address = (_ebx << 16) | _ecx; - _info->handle = (_esi << 16) | _edi; - } - *scp = sa; - return ret; + return 0; } -int _dpmi_free_memory(cpuctx_t *scp, int is_32, ULONG _handle) +int _dpmi_free_memory(sigcontext_t *scp, int is_32, ULONG _handle) { /* DPMI 0.9 AX=0502 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x502; - _esi = _handle >> 16; - _edi = _handle & 0xffff; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - *scp = sa; - return ret; + return 0; } -int _dpmi_resize_memory(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_resize_memory(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 0.9 AX=0503 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x503; - _ebx = _info->size >> 16; - _ecx = _info->size & 0xffff; - _esi = _info->handle >> 16; - _edi = _info->handle & 0xffff; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) { - ret = -1; - } else { - _info->address = (_ebx << 16) | _ecx; - _info->handle = (_esi << 16) | _edi; - } - *scp = sa; - return ret; + return 0; } -int _dpmi_allocate_linear_memory(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, int _commit) +int _dpmi_allocate_linear_memory(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, int _commit) { /* DPMI 1.0 AX=0504 */ return 0; } -int _dpmi_resize_linear_memory(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, int _commit) +int _dpmi_resize_linear_memory(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, int _commit) { /* DPMI 1.0 AX=0505 */ return 0; } -int _dpmi_get_page_attributes(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, short *_buffer) +int _dpmi_get_page_attributes(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, short *_buffer) { /* DPMI 1.0 AX=0506 */ return 0; } -int _dpmi_set_page_attributes(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, short *_buffer) +int _dpmi_set_page_attributes(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, short *_buffer) { /* DPMI 1.0 AX=0507 */ return 0; } -int _dpmi_map_device_in_memory_block(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, ULONG _physaddr) +int _dpmi_map_device_in_memory_block(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, ULONG _physaddr) { /* DPMI 1.0 AX=0508 */ return 0; } -int _dpmi_map_conventional_memory_in_memory_block(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, ULONG _physaddr) +int _dpmi_map_conventional_memory_in_memory_block(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, ULONG _physaddr) { /* DPMI 1.0 AX=0509 */ return 0; } -int _dpmi_get_memory_block_size_and_base(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_get_memory_block_size_and_base(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 1.0 AX=050a */ return 0; } -int _dpmi_get_memory_information(cpuctx_t *scp, int is_32, __dpmi_memory_info *_buffer) +int _dpmi_get_memory_information(sigcontext_t *scp, int is_32, __dpmi_memory_info *_buffer) { /* DPMI 1.0 AX=050b */ return 0; } -int _dpmi_lock_linear_region(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_lock_linear_region(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 0.9 AX=0600 */ return 0; } -int _dpmi_unlock_linear_region(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_unlock_linear_region(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 0.9 AX=0601 */ return 0; } -int _dpmi_mark_real_mode_region_as_pageable(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_mark_real_mode_region_as_pageable(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 0.9 AX=0602 */ return 0; } -int _dpmi_relock_real_mode_region(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_relock_real_mode_region(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 0.9 AX=0603 */ return 0; } -int _dpmi_get_page_size(cpuctx_t *scp, int is_32, ULONG *_size) +int _dpmi_get_page_size(sigcontext_t *scp, int is_32, ULONG *_size) { /* DPMI 0.9 AX=0604 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x604; - _ebx = _ecx = 0; // clear high parts - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - else - *_size = (_ebx << 16) | _ecx; - *scp = sa; - return ret; + return 0; } -int _dpmi_mark_page_as_demand_paging_candidate(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_mark_page_as_demand_paging_candidate(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 0.9 AX=0702 */ return 0; } -int _dpmi_discard_page_contents(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_discard_page_contents(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 0.9 AX=0703 */ return 0; } -int _dpmi_physical_address_mapping(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_physical_address_mapping(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 0.9 AX=0800 */ return 0; } -int _dpmi_free_physical_address_mapping(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info) +int _dpmi_free_physical_address_mapping(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info) { /* DPMI 0.9 AX=0801 */ return 0; } /* These next four functions return the old state */ -int _dpmi_get_and_disable_virtual_interrupt_state(cpuctx_t *scp, int is_32) +int _dpmi_get_and_disable_virtual_interrupt_state(sigcontext_t *scp, int is_32) { /* DPMI 0.9 AX=0900 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x900; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - else - ret = _eax & 1; - *scp = sa; - return ret; + return 0; } -int _dpmi_get_and_enable_virtual_interrupt_state(cpuctx_t *scp, int is_32) +int _dpmi_get_and_enable_virtual_interrupt_state(sigcontext_t *scp, int is_32) { /* DPMI 0.9 AX=0901 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x901; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - else - ret = _eax & 1; - *scp = sa; - return ret; + return 0; } -int _dpmi_get_and_set_virtual_interrupt_state(cpuctx_t *scp, int is_32, int _old_state) +int _dpmi_get_and_set_virtual_interrupt_state(sigcontext_t *scp, int is_32, int _old_state) { /* DPMI 0.9 AH=09 */ return 0; } -int _dpmi_get_virtual_interrupt_state(cpuctx_t *scp, int is_32) +int _dpmi_get_virtual_interrupt_state(sigcontext_t *scp, int is_32) { /* DPMI 0.9 AX=0902 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0x902; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - else - ret = _eax & 1; - *scp = sa; - return ret; + return 0; } -int _dpmi_get_vendor_specific_api_entry_point(cpuctx_t *scp, int is_32, char *_id, __dpmi_paddr *_api) +int _dpmi_get_vendor_specific_api_entry_point(sigcontext_t *scp, int is_32, char *_id, __dpmi_paddr *_api) { /* DPMI 0.9 AX=0a00 */ return 0; } -int _dpmi_set_debug_watchpoint(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, int _type) +int _dpmi_set_debug_watchpoint(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, int _type) { /* DPMI 0.9 AX=0b00 */ return 0; } -int _dpmi_clear_debug_watchpoint(cpuctx_t *scp, int is_32, ULONG _handle) +int _dpmi_clear_debug_watchpoint(sigcontext_t *scp, int is_32, ULONG _handle) { /* DPMI 0.9 AX=0b01 */ return 0; } -int _dpmi_get_state_of_debug_watchpoint(cpuctx_t *scp, int is_32, ULONG _handle, int *_status) +int _dpmi_get_state_of_debug_watchpoint(sigcontext_t *scp, int is_32, ULONG _handle, int *_status) { /* DPMI 0.9 AX=0b02 */ return 0; } -int _dpmi_reset_debug_watchpoint(cpuctx_t *scp, int is_32, ULONG _handle) +int _dpmi_reset_debug_watchpoint(sigcontext_t *scp, int is_32, ULONG _handle) { /* DPMI 0.9 AX=0b03 */ return 0; } -int _dpmi_install_resident_service_provider_callback(cpuctx_t *scp, int is_32, __dpmi_callback_info *_info) +int _dpmi_install_resident_service_provider_callback(sigcontext_t *scp, int is_32, __dpmi_callback_info *_info) { /* DPMI 1.0 AX=0c00 */ return 0; } -int _dpmi_terminate_and_stay_resident(cpuctx_t *scp, int is_32, int return_code, int paragraphs_to_keep) +int _dpmi_terminate_and_stay_resident(sigcontext_t *scp, int is_32, int return_code, int paragraphs_to_keep) { /* DPMI 1.0 AX=0c01 */ return 0; } -int _dpmi_allocate_shared_memory(cpuctx_t *scp, int is_32, __dpmi_shminfo *_info) +int _dpmi_allocate_shared_memory(sigcontext_t *scp, int is_32, __dpmi_shminfo *_info) { /* DPMI 1.0 AX=0d00 */ return 0; } -int _dpmi_free_shared_memory(cpuctx_t *scp, int is_32, ULONG _handle) +int _dpmi_free_shared_memory(sigcontext_t *scp, int is_32, ULONG _handle) { /* DPMI 1.0 AX=0d01 */ return 0; } -int _dpmi_serialize_on_shared_memory(cpuctx_t *scp, int is_32, ULONG _handle, int _flags) +int _dpmi_serialize_on_shared_memory(sigcontext_t *scp, int is_32, ULONG _handle, int _flags) { /* DPMI 1.0 AX=0d02 */ return 0; } -int _dpmi_free_serialization_on_shared_memory(cpuctx_t *scp, int is_32, ULONG _handle, int _flags) +int _dpmi_free_serialization_on_shared_memory(sigcontext_t *scp, int is_32, ULONG _handle, int _flags) { /* DPMI 1.0 AX=0d03 */ return 0; } -int _dpmi_get_coprocessor_status(cpuctx_t *scp, int is_32) +int _dpmi_get_coprocessor_status(sigcontext_t *scp, int is_32) { /* DPMI 1.0 AX=0e00 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0xe00; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - else - ret = _eax & 0xff; - *scp = sa; - return ret; + return 0; } -int _dpmi_set_coprocessor_emulation(cpuctx_t *scp, int is_32, int _flags) +int _dpmi_set_coprocessor_emulation(sigcontext_t *scp, int is_32, int _flags) { /* DPMI 1.0 AX=0e01 */ - cpuctx_t sa = *scp; - int ret = 0; - _eax = 0xe01; - _ebx = _flags; - do_dpmi_callf(scp, is_32); - if (_eflags & CF) - ret = -1; - *scp = sa; - return ret; + return 0; } void dpmi_api_init(uint16_t selector, dosaddr_t pool, int pool_size) @@ -802,22 +539,3 @@ void dpmi_api_init(uint16_t selector, dosaddr_t pool, int pool_size) pool_base = MEM_BASE32(pool); sminit(&apool, pool_base, pool_size); } - -__dpmi_paddr dapi_alloc(int len) -{ - __dpmi_paddr ret = {}; - void *ptr = smalloc(&apool, len); - if (ptr) { - ret.selector = data_sel; - ret.offset32 = POOL_OFS(ptr); - } - return ret; -} - -void dapi_free(__dpmi_paddr ptr) -{ - if (!ptr.selector) - return; - assert(ptr.selector == data_sel); - smfree(&apool, pool_base + ptr.offset32); -} diff --git a/src/dosext/dpmi/dpmi_api.h b/src/dosext/dpmi/dpmi_api.h index 8a34cd5..4f98f34 100644 --- a/src/dosext/dpmi/dpmi_api.h +++ b/src/dosext/dpmi/dpmi_api.h @@ -1,114 +1,113 @@ #ifndef DPMI_API_H #define DPMI_API_H -#include "cpu.h" +#include "sig.h" #include "memory.h" -#include "djdpmi.h" +#undef _POSIX_SOURCE +#undef _regs +#include "stub/dpmi.h" -void _dpmi_yield(cpuctx_t *scp, int is_32); /* INT 0x2F AX=1680 */ +void _dpmi_yield(sigcontext_t *scp, int is_32); /* INT 0x2F AX=1680 */ -int _dpmi_allocate_ldt_descriptors(cpuctx_t *scp, int is_32, int _count); /* DPMI 0.9 AX=0000 */ -int _dpmi_free_ldt_descriptor(cpuctx_t *scp, int is_32, int _descriptor); /* DPMI 0.9 AX=0001 */ -int _dpmi_segment_to_descriptor(cpuctx_t *scp, int is_32, int _segment); /* DPMI 0.9 AX=0002 */ -int _dpmi_get_selector_increment_value(cpuctx_t *scp, int is_32); /* DPMI 0.9 AX=0003 */ -int _dpmi_get_segment_base_address(cpuctx_t *scp, int is_32, int _selector, ULONG *_addr); /* DPMI 0.9 AX=0006 */ -int _dpmi_set_segment_base_address(cpuctx_t *scp, int is_32, int _selector, ULONG _address); /* DPMI 0.9 AX=0007 */ -ULONG _dpmi_get_segment_limit(cpuctx_t *scp, int is_32, int _selector); /* LSL instruction */ -int _dpmi_set_segment_limit(cpuctx_t *scp, int is_32, int _selector, ULONG _limit); /* DPMI 0.9 AX=0008 */ -int _dpmi_get_descriptor_access_rights(cpuctx_t *scp, int is_32, int _selector); /* LAR instruction */ -int _dpmi_set_descriptor_access_rights(cpuctx_t *scp, int is_32, int _selector, int _rights); /* DPMI 0.9 AX=0009 */ -int _dpmi_create_alias_descriptor(cpuctx_t *scp, int is_32, int _selector); /* DPMI 0.9 AX=000a */ -int _dpmi_get_descriptor(cpuctx_t *scp, int is_32, int _selector, void *_buffer); /* DPMI 0.9 AX=000b */ -int _dpmi_set_descriptor(cpuctx_t *scp, int is_32, int _selector, void *_buffer); /* DPMI 0.9 AX=000c */ -int _dpmi_allocate_specific_ldt_descriptor(cpuctx_t *scp, int is_32, int _selector); /* DPMI 0.9 AX=000d */ +int _dpmi_allocate_ldt_descriptors(sigcontext_t *scp, int is_32, int _count); /* DPMI 0.9 AX=0000 */ +int _dpmi_free_ldt_descriptor(sigcontext_t *scp, int is_32, int _descriptor); /* DPMI 0.9 AX=0001 */ +int _dpmi_segment_to_descriptor(sigcontext_t *scp, int is_32, int _segment); /* DPMI 0.9 AX=0002 */ +int _dpmi_get_selector_increment_value(sigcontext_t *scp, int is_32); /* DPMI 0.9 AX=0003 */ +int _dpmi_get_segment_base_address(sigcontext_t *scp, int is_32, int _selector, ULONG *_addr); /* DPMI 0.9 AX=0006 */ +int _dpmi_set_segment_base_address(sigcontext_t *scp, int is_32, int _selector, ULONG _address); /* DPMI 0.9 AX=0007 */ +ULONG _dpmi_get_segment_limit(sigcontext_t *scp, int is_32, int _selector); /* LSL instruction */ +int _dpmi_set_segment_limit(sigcontext_t *scp, int is_32, int _selector, ULONG _limit); /* DPMI 0.9 AX=0008 */ +int _dpmi_get_descriptor_access_rights(sigcontext_t *scp, int is_32, int _selector); /* LAR instruction */ +int _dpmi_set_descriptor_access_rights(sigcontext_t *scp, int is_32, int _selector, int _rights); /* DPMI 0.9 AX=0009 */ +int _dpmi_create_alias_descriptor(sigcontext_t *scp, int is_32, int _selector); /* DPMI 0.9 AX=000a */ +int _dpmi_get_descriptor(sigcontext_t *scp, int is_32, int _selector, void *_buffer); /* DPMI 0.9 AX=000b */ +int _dpmi_set_descriptor(sigcontext_t *scp, int is_32, int _selector, void *_buffer); /* DPMI 0.9 AX=000c */ +int _dpmi_allocate_specific_ldt_descriptor(sigcontext_t *scp, int is_32, int _selector); /* DPMI 0.9 AX=000d */ -int _dpmi_get_multiple_descriptors(cpuctx_t *scp, int is_32, int _count, void *_buffer); /* DPMI 1.0 AX=000e */ -int _dpmi_set_multiple_descriptors(cpuctx_t *scp, int is_32, int _count, void *_buffer); /* DPMI 1.0 AX=000f */ +int _dpmi_get_multiple_descriptors(sigcontext_t *scp, int is_32, int _count, void *_buffer); /* DPMI 1.0 AX=000e */ +int _dpmi_set_multiple_descriptors(sigcontext_t *scp, int is_32, int _count, void *_buffer); /* DPMI 1.0 AX=000f */ -int _dpmi_allocate_dos_memory(cpuctx_t *scp, int is_32, int _paragraphs, int *_ret_selector_or_max); /* DPMI 0.9 AX=0100 */ -int _dpmi_free_dos_memory(cpuctx_t *scp, int is_32, int _selector); /* DPMI 0.9 AX=0101 */ -int _dpmi_resize_dos_memory(cpuctx_t *scp, int is_32, int _selector, int _newpara, int *_ret_max); /* DPMI 0.9 AX=0102 */ +int _dpmi_allocate_dos_memory(sigcontext_t *scp, int is_32, int _paragraphs, int *_ret_selector_or_max); /* DPMI 0.9 AX=0100 */ +int _dpmi_free_dos_memory(sigcontext_t *scp, int is_32, int _selector); /* DPMI 0.9 AX=0101 */ +int _dpmi_resize_dos_memory(sigcontext_t *scp, int is_32, int _selector, int _newpara, int *_ret_max); /* DPMI 0.9 AX=0102 */ -int _dpmi_get_real_mode_interrupt_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_raddr *_address); /* DPMI 0.9 AX=0200 */ -int _dpmi_set_real_mode_interrupt_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_raddr *_address); /* DPMI 0.9 AX=0201 */ -int _dpmi_get_processor_exception_handler_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0202 */ -int _dpmi_set_processor_exception_handler_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0203 */ -int _dpmi_get_protected_mode_interrupt_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0204 */ -int _dpmi_set_protected_mode_interrupt_vector(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0205 */ +int _dpmi_get_real_mode_interrupt_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_raddr *_address); /* DPMI 0.9 AX=0200 */ +int _dpmi_set_real_mode_interrupt_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_raddr *_address); /* DPMI 0.9 AX=0201 */ +int _dpmi_get_processor_exception_handler_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0202 */ +int _dpmi_set_processor_exception_handler_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0203 */ +int _dpmi_get_protected_mode_interrupt_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0204 */ +int _dpmi_set_protected_mode_interrupt_vector(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0205 */ -int _dpmi_get_extended_exception_handler_vector_pm(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0210 */ -int _dpmi_get_extended_exception_handler_vector_rm(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0211 */ -int _dpmi_set_extended_exception_handler_vector_pm(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0212 */ -int _dpmi_set_extended_exception_handler_vector_rm(cpuctx_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0213 */ +int _dpmi_get_extended_exception_handler_vector_pm(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0210 */ +int _dpmi_get_extended_exception_handler_vector_rm(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0211 */ +int _dpmi_set_extended_exception_handler_vector_pm(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0212 */ +int _dpmi_set_extended_exception_handler_vector_rm(sigcontext_t *scp, int is_32, int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0213 */ -int _dpmi_simulate_real_mode_interrupt(cpuctx_t *scp, int is_32, int _vector, __dpmi_regs *__regs); /* DPMI 0.9 AX=0300 */ -int _dpmi_int(cpuctx_t *scp, int is_32, int _vector, __dpmi_regs *__regs); /* like above, but sets ss sp fl */ /* DPMI 0.9 AX=0300 */ +int _dpmi_simulate_real_mode_interrupt(sigcontext_t *scp, int is_32, int _vector, __dpmi_regs *_regs); /* DPMI 0.9 AX=0300 */ +int _dpmi_int(sigcontext_t *scp, int is_32, int _vector, __dpmi_regs *_regs); /* like above, but sets ss sp fl */ /* DPMI 0.9 AX=0300 */ -int _dpmi_simulate_real_mode_procedure_retf(cpuctx_t *scp, int is_32, __dpmi_regs *__regs); /* DPMI 0.9 AX=0301 */ -int _dpmi_simulate_real_mode_procedure_retf_stack(cpuctx_t *scp, int is_32, __dpmi_regs *__regs, int stack_words_to_copy, const void *stack_data); /* DPMI 0.9 AX=0301 */ -int _dpmi_simulate_real_mode_procedure_iret(cpuctx_t *scp, int is_32, __dpmi_regs *__regs); /* DPMI 0.9 AX=0302 */ -int _dpmi_allocate_real_mode_callback(cpuctx_t *scp, int is_32, void (*_handler)(void), __dpmi_regs *__regs, __dpmi_raddr *_ret); /* DPMI 0.9 AX=0303 */ -int _dpmi_free_real_mode_callback(cpuctx_t *scp, int is_32, __dpmi_raddr *_addr); /* DPMI 0.9 AX=0304 */ -int _dpmi_get_state_save_restore_addr(cpuctx_t *scp, int is_32, __dpmi_raddr *_rm, __dpmi_paddr *_pm); /* DPMI 0.9 AX=0305 */ -int _dpmi_get_raw_mode_switch_addr(cpuctx_t *scp, int is_32, __dpmi_raddr *_rm, __dpmi_paddr *_pm); /* DPMI 0.9 AX=0306 */ +int _dpmi_simulate_real_mode_procedure_retf(sigcontext_t *scp, int is_32, __dpmi_regs *_regs); /* DPMI 0.9 AX=0301 */ +int _dpmi_simulate_real_mode_procedure_retf_stack(sigcontext_t *scp, int is_32, __dpmi_regs *_regs, int stack_words_to_copy, const void *stack_data); /* DPMI 0.9 AX=0301 */ +int _dpmi_simulate_real_mode_procedure_iret(sigcontext_t *scp, int is_32, __dpmi_regs *_regs); /* DPMI 0.9 AX=0302 */ +int _dpmi_allocate_real_mode_callback(sigcontext_t *scp, int is_32, void (*_handler)(void), __dpmi_regs *_regs, __dpmi_raddr *_ret); /* DPMI 0.9 AX=0303 */ +int _dpmi_free_real_mode_callback(sigcontext_t *scp, int is_32, __dpmi_raddr *_addr); /* DPMI 0.9 AX=0304 */ +int _dpmi_get_state_save_restore_addr(sigcontext_t *scp, int is_32, __dpmi_raddr *_rm, __dpmi_paddr *_pm); /* DPMI 0.9 AX=0305 */ +int _dpmi_get_raw_mode_switch_addr(sigcontext_t *scp, int is_32, __dpmi_raddr *_rm, __dpmi_paddr *_pm); /* DPMI 0.9 AX=0306 */ -int _dpmi_get_version(cpuctx_t *scp, int is_32, __dpmi_version_ret *_ret); /* DPMI 0.9 AX=0400 */ +int _dpmi_get_version(sigcontext_t *scp, int is_32, __dpmi_version_ret *_ret); /* DPMI 0.9 AX=0400 */ -int _dpmi_get_capabilities(cpuctx_t *scp, int is_32, int *_flags, char *vendor_info); /* DPMI 1.0 AX=0401 */ +int _dpmi_get_capabilities(sigcontext_t *scp, int is_32, int *_flags, char *vendor_info); /* DPMI 1.0 AX=0401 */ -int _dpmi_get_free_memory_information(cpuctx_t *scp, int is_32, __dpmi_free_mem_info *_info); /* DPMI 0.9 AX=0500 */ -int _dpmi_allocate_memory(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0501 */ -int _dpmi_free_memory(cpuctx_t *scp, int is_32, ULONG _handle); /* DPMI 0.9 AX=0502 */ -int _dpmi_resize_memory(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0503 */ +int _dpmi_get_free_memory_information(sigcontext_t *scp, int is_32, __dpmi_free_mem_info *_info); /* DPMI 0.9 AX=0500 */ +int _dpmi_allocate_memory(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0501 */ +int _dpmi_free_memory(sigcontext_t *scp, int is_32, ULONG _handle); /* DPMI 0.9 AX=0502 */ +int _dpmi_resize_memory(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0503 */ -int _dpmi_allocate_linear_memory(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, int _commit); /* DPMI 1.0 AX=0504 */ -int _dpmi_resize_linear_memory(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, int _commit); /* DPMI 1.0 AX=0505 */ -int _dpmi_get_page_attributes(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, short *_buffer); /* DPMI 1.0 AX=0506 */ -int _dpmi_set_page_attributes(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, short *_buffer); /* DPMI 1.0 AX=0507 */ -int _dpmi_map_device_in_memory_block(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, ULONG _physaddr); /* DPMI 1.0 AX=0508 */ -int _dpmi_map_conventional_memory_in_memory_block(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, ULONG _physaddr); /* DPMI 1.0 AX=0509 */ -int _dpmi_get_memory_block_size_and_base(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 1.0 AX=050a */ -int _dpmi_get_memory_information(cpuctx_t *scp, int is_32, __dpmi_memory_info *_buffer); /* DPMI 1.0 AX=050b */ +int _dpmi_allocate_linear_memory(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, int _commit); /* DPMI 1.0 AX=0504 */ +int _dpmi_resize_linear_memory(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, int _commit); /* DPMI 1.0 AX=0505 */ +int _dpmi_get_page_attributes(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, short *_buffer); /* DPMI 1.0 AX=0506 */ +int _dpmi_set_page_attributes(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, short *_buffer); /* DPMI 1.0 AX=0507 */ +int _dpmi_map_device_in_memory_block(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, ULONG _physaddr); /* DPMI 1.0 AX=0508 */ +int _dpmi_map_conventional_memory_in_memory_block(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, ULONG _physaddr); /* DPMI 1.0 AX=0509 */ +int _dpmi_get_memory_block_size_and_base(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 1.0 AX=050a */ +int _dpmi_get_memory_information(sigcontext_t *scp, int is_32, __dpmi_memory_info *_buffer); /* DPMI 1.0 AX=050b */ -int _dpmi_lock_linear_region(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0600 */ -int _dpmi_unlock_linear_region(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0601 */ -int _dpmi_mark_real_mode_region_as_pageable(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0602 */ -int _dpmi_relock_real_mode_region(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0603 */ -int _dpmi_get_page_size(cpuctx_t *scp, int is_32, ULONG *_size); /* DPMI 0.9 AX=0604 */ +int _dpmi_lock_linear_region(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0600 */ +int _dpmi_unlock_linear_region(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0601 */ +int _dpmi_mark_real_mode_region_as_pageable(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0602 */ +int _dpmi_relock_real_mode_region(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0603 */ +int _dpmi_get_page_size(sigcontext_t *scp, int is_32, ULONG *_size); /* DPMI 0.9 AX=0604 */ -int _dpmi_mark_page_as_demand_paging_candidate(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0702 */ -int _dpmi_discard_page_contents(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0703 */ +int _dpmi_mark_page_as_demand_paging_candidate(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0702 */ +int _dpmi_discard_page_contents(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0703 */ -int _dpmi_physical_address_mapping(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0800 */ -int _dpmi_free_physical_address_mapping(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0801 */ +int _dpmi_physical_address_mapping(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0800 */ +int _dpmi_free_physical_address_mapping(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info); /* DPMI 0.9 AX=0801 */ /* These next four functions return the old state */ -int _dpmi_get_and_disable_virtual_interrupt_state(cpuctx_t *scp, int is_32); /* DPMI 0.9 AX=0900 */ -int _dpmi_get_and_enable_virtual_interrupt_state(cpuctx_t *scp, int is_32); /* DPMI 0.9 AX=0901 */ -int _dpmi_get_and_set_virtual_interrupt_state(cpuctx_t *scp, int is_32, int _old_state); /* DPMI 0.9 AH=09 */ -int _dpmi_get_virtual_interrupt_state(cpuctx_t *scp, int is_32); /* DPMI 0.9 AX=0902 */ +int _dpmi_get_and_disable_virtual_interrupt_state(sigcontext_t *scp, int is_32); /* DPMI 0.9 AX=0900 */ +int _dpmi_get_and_enable_virtual_interrupt_state(sigcontext_t *scp, int is_32); /* DPMI 0.9 AX=0901 */ +int _dpmi_get_and_set_virtual_interrupt_state(sigcontext_t *scp, int is_32, int _old_state); /* DPMI 0.9 AH=09 */ +int _dpmi_get_virtual_interrupt_state(sigcontext_t *scp, int is_32); /* DPMI 0.9 AX=0902 */ -int _dpmi_get_vendor_specific_api_entry_point(cpuctx_t *scp, int is_32, char *_id, __dpmi_paddr *_api); /* DPMI 0.9 AX=0a00 */ +int _dpmi_get_vendor_specific_api_entry_point(sigcontext_t *scp, int is_32, char *_id, __dpmi_paddr *_api); /* DPMI 0.9 AX=0a00 */ -int _dpmi_set_debug_watchpoint(cpuctx_t *scp, int is_32, __dpmi_meminfo *_info, int _type); /* DPMI 0.9 AX=0b00 */ -int _dpmi_clear_debug_watchpoint(cpuctx_t *scp, int is_32, ULONG _handle); /* DPMI 0.9 AX=0b01 */ -int _dpmi_get_state_of_debug_watchpoint(cpuctx_t *scp, int is_32, ULONG _handle, int *_status); /* DPMI 0.9 AX=0b02 */ -int _dpmi_reset_debug_watchpoint(cpuctx_t *scp, int is_32, ULONG _handle); /* DPMI 0.9 AX=0b03 */ +int _dpmi_set_debug_watchpoint(sigcontext_t *scp, int is_32, __dpmi_meminfo *_info, int _type); /* DPMI 0.9 AX=0b00 */ +int _dpmi_clear_debug_watchpoint(sigcontext_t *scp, int is_32, ULONG _handle); /* DPMI 0.9 AX=0b01 */ +int _dpmi_get_state_of_debug_watchpoint(sigcontext_t *scp, int is_32, ULONG _handle, int *_status); /* DPMI 0.9 AX=0b02 */ +int _dpmi_reset_debug_watchpoint(sigcontext_t *scp, int is_32, ULONG _handle); /* DPMI 0.9 AX=0b03 */ -int _dpmi_install_resident_service_provider_callback(cpuctx_t *scp, int is_32, __dpmi_callback_info *_info); /* DPMI 1.0 AX=0c00 */ -int _dpmi_terminate_and_stay_resident(cpuctx_t *scp, int is_32, int return_code, int paragraphs_to_keep); /* DPMI 1.0 AX=0c01 */ +int _dpmi_install_resident_service_provider_callback(sigcontext_t *scp, int is_32, __dpmi_callback_info *_info); /* DPMI 1.0 AX=0c00 */ +int _dpmi_terminate_and_stay_resident(sigcontext_t *scp, int is_32, int return_code, int paragraphs_to_keep); /* DPMI 1.0 AX=0c01 */ -int _dpmi_allocate_shared_memory(cpuctx_t *scp, int is_32, __dpmi_shminfo *_info); /* DPMI 1.0 AX=0d00 */ -int _dpmi_free_shared_memory(cpuctx_t *scp, int is_32, ULONG _handle); /* DPMI 1.0 AX=0d01 */ -int _dpmi_serialize_on_shared_memory(cpuctx_t *scp, int is_32, ULONG _handle, int _flags); /* DPMI 1.0 AX=0d02 */ -int _dpmi_free_serialization_on_shared_memory(cpuctx_t *scp, int is_32, ULONG _handle, int _flags); /* DPMI 1.0 AX=0d03 */ +int _dpmi_allocate_shared_memory(sigcontext_t *scp, int is_32, __dpmi_shminfo *_info); /* DPMI 1.0 AX=0d00 */ +int _dpmi_free_shared_memory(sigcontext_t *scp, int is_32, ULONG _handle); /* DPMI 1.0 AX=0d01 */ +int _dpmi_serialize_on_shared_memory(sigcontext_t *scp, int is_32, ULONG _handle, int _flags); /* DPMI 1.0 AX=0d02 */ +int _dpmi_free_serialization_on_shared_memory(sigcontext_t *scp, int is_32, ULONG _handle, int _flags); /* DPMI 1.0 AX=0d03 */ -int _dpmi_get_coprocessor_status(cpuctx_t *scp, int is_32); /* DPMI 1.0 AX=0e00 */ -int _dpmi_set_coprocessor_emulation(cpuctx_t *scp, int is_32, int _flags); /* DPMI 1.0 AX=0e01 */ +int _dpmi_get_coprocessor_status(sigcontext_t *scp, int is_32); /* DPMI 1.0 AX=0e00 */ +int _dpmi_set_coprocessor_emulation(sigcontext_t *scp, int is_32, int _flags); /* DPMI 1.0 AX=0e01 */ void dpmi_api_init(uint16_t selector, dosaddr_t pool, int pool_size); -__dpmi_paddr dapi_alloc(int len); -void dapi_free(__dpmi_paddr ptr); - #endif diff --git a/src/dosext/dpmi/dpmisel.S b/src/dosext/dpmi/dpmisel.S index 8f90340..b7ecaaf 100644 --- a/src/dosext/dpmi/dpmisel.S +++ b/src/dosext/dpmi/dpmisel.S @@ -8,7 +8,13 @@ #include "macros86.h" .section .text -.code32 + +#ifdef __x86_64__ + .globl DPMI_iret + .type DPMI_iret,@function +DPMI_iret: + iretl +#endif .globl DPMI_sel_code_start DPMI_sel_code_start: @@ -48,8 +54,8 @@ DPMI_exception: DPMI_interrupt: FILL_OPCODE 256,hlt /* ======================= Addr = dpmi_sel():0128 */ - .globl DPMI_return_from_RSPcall_exit -DPMI_return_from_RSPcall_exit: +/* .globl reserved */ +reserved: hlt /* ======================= Addr = dpmi_sel():0129 */ .globl DPMI_return_from_ext_exception @@ -96,25 +102,6 @@ DPMI_return_from_LDTcall: DPMI_return_from_LDTExitCall: hlt /* ======================= Addr = dpmi_sel():0172 */ - .globl DPMI_reinit -DPMI_reinit: - hlt -/* ======================= Addr = dpmi_sel():0173 */ - .globl DPMI_dj64 -DPMI_dj64: - hlt - lretl -/* ======================= Addr = dpmi_sel():0175 */ - .globl DPMI_shlock -DPMI_shlock: - hlt - jc 1f // canceled - jz 1f // success - movl $0x1680, %eax - int $0x2f - jmp DPMI_shlock -1: - lret .globl DPMI_sel_end DPMI_sel_end: @@ -144,14 +131,6 @@ MSDOS_LDT_call16: MSDOS_LDT_call32: hlt lretl - .globl MSDOS_RSP_call16 -MSDOS_RSP_call16: - hlt - lretl - .globl MSDOS_RSP_call32 -MSDOS_RSP_call32: - hlt - lretl .globl MSDOS_rmcb_call_start MSDOS_rmcb_call_start: @@ -180,7 +159,7 @@ MSDOS_rmcb_ret2: MSDOS_rmcb_call_end: .globl MSDOS_hlt_start MSDOS_hlt_start: - FILL_OPCODE 64,hlt + FILL_OPCODE 32,hlt .globl MSDOS_hlt_end MSDOS_hlt_end: .globl MSDOS_pmc_end @@ -247,99 +226,13 @@ DPMI_VXD_end: DPMI_call: int $0x31 lretl - .globl DPMI_call_args -DPMI_call_args: - pushl %ebp - movl %esp, %ebp - pushl %ecx - pushl %edx - movl %ecx, %edx - jcxz 2f -1: - pushw 12-2(%ebp,%ecx,2) - loop 1b - movl %edx, %ecx -2: - int $0x31 - movl -4(%ebp), %ecx - shll $1, %ecx - addl %ecx, %esp - popl %edx - popl %ecx - popl %ebp - lretl - .globl DPMI_call_args16 -DPMI_call_args16: -.code16 - pushw %bp - movw %sp, %bp - pushw %cx - pushw %dx - pushw %si - movw %cx, %dx - jcxz 2f -1: - movw %cx, %si - shlw $1, %si - pushw 6-2(%bp,%si) - loop 1b - movw %dx, %cx -2: - int $0x31 - movw -2(%bp), %cx - shlw $1, %cx - addw %cx, %sp - popw %si - popw %dx - popw %cx - popw %bp - lretw -.code32 - .globl DPMI_int2f -DPMI_int2f: - int $0x2f - lretl .globl DPMI_msdos DPMI_msdos: int $0x21 lretl - .globl DPMI_abort -DPMI_abort: - hlt - movl $0x4c01, %eax - int $0x21 - lretl - -.macro vint name inum - .globl DPMI_\name\()_irq -DPMI_\name\()_irq: - hlt - jc 1f - int $\inum - # IRQ0 is not requested at that point (its not used at all). - # We disable interrupts and then allow timer to tick. - cli - clc -1: - .globl DPMI_\name\()_post_irq -DPMI_\name\()_post_irq: - hlt - /* DPMI spec suggests STI before IRET. - * But if the handler was called by some other handler, - * then STI should not be done, as the caller's handler would - * then be interrupted. - * dosemu2 does not require STI before IRET. - * (STI is only required before POPF in dosemu2) */ - iretl -.endm - - vint vtmr 8 - vint vrtc 0x70 .globl DPMI_sel_code_end DPMI_sel_code_end: - .global _start -_start: // dummy #ifdef __ELF__ .section .note.GNU-stack,"",%progbits diff --git a/src/dosext/dpmi/dpmisel.h b/src/dosext/dpmi/dpmisel.h index baa88ce..1f875c6 100644 --- a/src/dosext/dpmi/dpmisel.h +++ b/src/dosext/dpmi/dpmisel.h @@ -7,11 +7,81 @@ #ifndef DPMISEL_H #define DPMISEL_H -extern char _binary_dpmisel_o_bin_end[] asm("_binary_dpmisel_o_bin_end"); -extern char _binary_dpmisel_o_bin_start[] asm("_binary_dpmisel_o_bin_start"); - #define DPMI_SEL_OFF(x) (x-DPMI_sel_code_start) -#include "dpmisel_offsets.h" +#ifdef __x86_64__ +#ifdef __cplusplus +extern "C" { +#endif +extern void DPMI_iret(void); +#ifdef __cplusplus +}; +#endif +#endif + +extern unsigned char DPMI_sel_code_start[]; + +extern unsigned char DPMI_save_restore_pm[]; +extern unsigned char DPMI_raw_mode_switch_pm[]; +extern unsigned char DPMI_return_from_rm_callback[]; +extern unsigned char DPMI_VXD_start[]; +extern unsigned char DPMI_VXD_end[]; +extern unsigned char DPMI_return_from_RSPcall[]; +extern unsigned char DPMI_return_from_LDTcall[]; +extern unsigned char DPMI_return_from_LDTExitCall[]; +extern unsigned char DPMI_return_from_int_1c[]; +extern unsigned char DPMI_return_from_int_23[]; +extern unsigned char DPMI_return_from_int_24[]; +extern unsigned char DPMI_return_from_rm_callback[]; +extern unsigned char DPMI_return_from_ext_exception[]; +extern unsigned char DPMI_return_from_exception[]; +extern unsigned char DPMI_return_from_rm_ext_exception[]; +extern unsigned char DPMI_return_from_rm_exception[]; +extern unsigned char DPMI_return_from_pm[]; +extern unsigned char DPMI_API_extension[]; +extern unsigned char DPMI_exception[]; +extern unsigned char DPMI_ext_exception[]; +extern unsigned char DPMI_rm_exception[]; +extern unsigned char DPMI_interrupt[]; +extern unsigned char DPMI_sel_end[]; + +extern unsigned char DPMI_VXD_start[]; +extern unsigned char DPMI_VXD_VMM[]; +extern unsigned char DPMI_VXD_PageFile[]; +extern unsigned char DPMI_VXD_Reboot[]; +extern unsigned char DPMI_VXD_VDD[]; +extern unsigned char DPMI_VXD_VMD[]; +extern unsigned char DPMI_VXD_VXDLDR[]; +extern unsigned char DPMI_VXD_SHELL[]; +extern unsigned char DPMI_VXD_VCD[]; +extern unsigned char DPMI_VXD_VTD[]; +extern unsigned char DPMI_VXD_CONFIGMG[]; +extern unsigned char DPMI_VXD_ENABLE[]; +extern unsigned char DPMI_VXD_APM[]; +extern unsigned char DPMI_VXD_VTDAPI[]; +extern unsigned char DPMI_VXD_end[]; + +extern unsigned char MSDOS_pmc_start[]; +extern unsigned char MSDOS_fault[]; +extern unsigned char MSDOS_pagefault[]; +extern unsigned char MSDOS_API_call[]; +extern unsigned char MSDOS_API_WINOS2_call[]; +extern unsigned char MSDOS_LDT_call16[]; +extern unsigned char MSDOS_LDT_call32[]; +extern unsigned char MSDOS_rmcb_call_start[]; +extern unsigned char MSDOS_rmcb_call0[]; +extern unsigned char MSDOS_rmcb_call1[]; +extern unsigned char MSDOS_rmcb_call2[]; +extern unsigned char MSDOS_rmcb_ret0[]; +extern unsigned char MSDOS_rmcb_ret1[]; +extern unsigned char MSDOS_rmcb_ret2[]; +extern unsigned char MSDOS_rmcb_call_end[]; +extern unsigned char MSDOS_hlt_start[]; +extern unsigned char MSDOS_hlt_end[]; +extern unsigned char MSDOS_pmc_end[]; +extern unsigned char DPMI_call[]; +extern unsigned char DPMI_msdos[]; + +extern unsigned char DPMI_sel_code_end[]; #endif diff --git a/src/dosext/dpmi/dpmisel_offsets.h b/src/dosext/dpmi/dpmisel_offsets.h deleted file mode 100644 index 79b4713..0000000 --- a/src/dosext/dpmi/dpmisel_offsets.h +++ /dev/null @@ -1,74 +0,0 @@ -extern const unsigned DPMI_sel_code_start; -extern const unsigned DPMI_save_restore_pm; -extern const unsigned DPMI_raw_mode_switch_pm; -extern const unsigned DPMI_return_from_rm_callback; -extern const unsigned DPMI_VXD_start; -extern const unsigned DPMI_VXD_end; -extern const unsigned DPMI_return_from_RSPcall; -extern const unsigned DPMI_return_from_RSPcall_exit; -extern const unsigned DPMI_return_from_LDTcall; -extern const unsigned DPMI_return_from_LDTExitCall; -extern const unsigned DPMI_return_from_int_1c; -extern const unsigned DPMI_return_from_int_23; -extern const unsigned DPMI_return_from_int_24; -extern const unsigned DPMI_return_from_rm_callback; -extern const unsigned DPMI_return_from_ext_exception; -extern const unsigned DPMI_return_from_exception; -extern const unsigned DPMI_return_from_rm_ext_exception; -extern const unsigned DPMI_return_from_rm_exception; -extern const unsigned DPMI_return_from_pm; -extern const unsigned DPMI_API_extension; -extern const unsigned DPMI_exception; -extern const unsigned DPMI_ext_exception; -extern const unsigned DPMI_rm_exception; -extern const unsigned DPMI_interrupt; -extern const unsigned DPMI_vtmr_irq; -extern const unsigned DPMI_vtmr_post_irq; -extern const unsigned DPMI_vrtc_irq; -extern const unsigned DPMI_vrtc_post_irq; -extern const unsigned DPMI_reinit; -extern const unsigned DPMI_shlock; -extern const unsigned DPMI_dj64; -extern const unsigned DPMI_sel_end; -extern const unsigned DPMI_VXD_start; -extern const unsigned DPMI_VXD_VMM; -extern const unsigned DPMI_VXD_PageFile; -extern const unsigned DPMI_VXD_Reboot; -extern const unsigned DPMI_VXD_VDD; -extern const unsigned DPMI_VXD_VMD; -extern const unsigned DPMI_VXD_VXDLDR; -extern const unsigned DPMI_VXD_SHELL; -extern const unsigned DPMI_VXD_VCD; -extern const unsigned DPMI_VXD_VTD; -extern const unsigned DPMI_VXD_CONFIGMG; -extern const unsigned DPMI_VXD_ENABLE; -extern const unsigned DPMI_VXD_APM; -extern const unsigned DPMI_VXD_VTDAPI; -extern const unsigned DPMI_VXD_end; -extern const unsigned MSDOS_pmc_start; -extern const unsigned MSDOS_fault; -extern const unsigned MSDOS_pagefault; -extern const unsigned MSDOS_API_call; -extern const unsigned MSDOS_API_WINOS2_call; -extern const unsigned MSDOS_LDT_call16; -extern const unsigned MSDOS_LDT_call32; -extern const unsigned MSDOS_RSP_call16; -extern const unsigned MSDOS_RSP_call32; -extern const unsigned MSDOS_rmcb_call_start; -extern const unsigned MSDOS_rmcb_call0; -extern const unsigned MSDOS_rmcb_call1; -extern const unsigned MSDOS_rmcb_call2; -extern const unsigned MSDOS_rmcb_ret0; -extern const unsigned MSDOS_rmcb_ret1; -extern const unsigned MSDOS_rmcb_ret2; -extern const unsigned MSDOS_rmcb_call_end; -extern const unsigned MSDOS_hlt_start; -extern const unsigned MSDOS_hlt_end; -extern const unsigned MSDOS_pmc_end; -extern const unsigned DPMI_call; -extern const unsigned DPMI_call_args; -extern const unsigned DPMI_call_args16; -extern const unsigned DPMI_int2f; -extern const unsigned DPMI_msdos; -extern const unsigned DPMI_abort; -extern const unsigned DPMI_sel_code_end; diff --git a/src/dosext/dpmi/emu-ldt.c b/src/dosext/dpmi/emu-ldt.c index 1872698..54ea541 100644 --- a/src/dosext/dpmi/emu-ldt.c +++ b/src/dosext/dpmi/emu-ldt.c @@ -55,8 +55,10 @@ static int emu_update_LDT (struct user_desc *ldt_info, int oldmode) Descriptor *lp; int bSelType; - /* invalidate segment base cache in cpuemu */ - InvalidateSegs(); +#ifdef X86_EMULATOR + if (config.cpu_vm_dpmi == CPUVM_EMU) + InvalidateSegs(); +#endif /* Install the new entry ... */ lp = &((Descriptor *)dpmi_get_ldt_buffer())[ldt_info->entry_number]; @@ -148,13 +150,13 @@ int emu_modify_ldt(int func, void *ptr, unsigned long bytecount) func, bytecount, lptr[0], lptr[1], lptr[2], lptr[3] ); } #endif switch (func) { - case LDT_READ: + case 0: ret = emu_read_ldt((char *)ptr, bytecount); break; - case LDT_WRITE_OLD: + case 1: ret = emu_write_ldt(ptr, bytecount, 1); break; - case LDT_WRITE: + case 0x11: ret = emu_write_ldt(ptr, bytecount, 0); break; } diff --git a/src/dosext/dpmi/emudpmi.h b/src/dosext/dpmi/emudpmi.h index 2d08ceb..90e2c6f 100644 --- a/src/dosext/dpmi/emudpmi.h +++ b/src/dosext/dpmi/emudpmi.h @@ -6,19 +6,13 @@ #if WITH_DPMI -#if 0 #define DPMI_VERSION 0x00 /* major version 0 */ #define DPMI_DRIVER_VERSION 0x5a /* minor version 0.90 */ -#else -#define DPMI_VERSION 1 /* major version 1 */ -#define DPMI_MINOR_VERSION 0 /* minor version 0 */ -#endif #define DPMI_MAX_CLIENTS 32 /* maximal number of clients */ #ifndef __ASSEMBLER__ -#include #include "cpu.h" #include "emu-ldt.h" #include "emm.h" @@ -41,9 +35,7 @@ #ifdef __linux__ int modify_ldt(int func, void *ptr, unsigned long bytecount); #endif -#define LDT_READ 0 -#define LDT_WRITE_OLD 1 -#define LDT_WRITE 0x11 +#define LDT_WRITE 0x11 /* this is used like: SEL_ADR(_ss, _esp) */ void *SEL_ADR(unsigned short sel, unsigned int reg); @@ -117,12 +109,9 @@ struct SHM_desc { uint32_t addr; uint32_t name_offset32; uint16_t name_selector; + uint16_t padding; #define SHM_NOEXEC 1 -#define SHM_EXCL 2 -#define SHM_NEW_NS 4 -#define SHM_NS 8 - uint16_t flags; - uint32_t opaque; + uint32_t flags; }; enum { DPMI_RET_FAULT=-3, DPMI_RET_EXIT=-2, DPMI_RET_DOSEMU=-1, @@ -142,21 +131,25 @@ typedef enum { } regnum_t; void dpmi_get_entry_point(void); +#ifdef __x86_64__ +extern void dpmi_iret_setup(sigcontext_t *scp); +extern void dpmi_iret_unwind(sigcontext_t *scp); +#else +#define dpmi_iret_setup(x) +#endif +int dpmi_fault(sigcontext_t *scp); void dpmi_realmode_hlt(unsigned int lina); void run_pm_int(int inum); void fake_pm_int(void); int in_dpmi_pm(void); int dpmi_active(void); int dpmi_segment_is32(int sel); -int dpmi_is_32(void); int dpmi_isset_IF(void); -#define isset_IF_async() (in_dpmi_pm() ? dpmi_isset_IF() : isset_IF()) -int p_direct_vstr(const char *fmt, va_list args); /* currently eflags are stored with IF reflecting the actual interrupt state, * so no translation is needed */ #define dpmi_flags_to_stack(flags) (flags) -static inline unsigned dpmi_flags_from_stack_iret(const cpuctx_t *scp, +static inline unsigned dpmi_flags_from_stack_iret(const sigcontext_t *scp, unsigned flags) { int iopl = ((_eflags_ & IOPL_MASK) >> IOPL_SHIFT); @@ -177,41 +170,41 @@ void dpmi_mhp_getcseip(unsigned int *seg, unsigned int *off); void dpmi_mhp_getssesp(unsigned int *seg, unsigned int *off); int dpmi_mhp_getcsdefault(void); int dpmi_mhp_setTF(int on); -int dpmi_mhp_issetTF(void); void dpmi_mhp_GetDescriptor(unsigned short selector, unsigned int *lp); -uint32_t dpmi_mhp_getreg(regnum_t regnum); -void dpmi_mhp_setreg(regnum_t regnum, uint32_t val); +unsigned long dpmi_mhp_getreg(regnum_t regnum); +void dpmi_mhp_setreg(regnum_t regnum, unsigned long val); void dpmi_mhp_modify_eip(int delta); #endif void dpmi_timer(void); dpmi_pm_block DPMImalloc(unsigned long size); -dpmi_pm_block DPMImallocLinear(dosaddr_t base, unsigned long size, int committed); +dpmi_pm_block DPMImallocLinear(unsigned long base, unsigned long size, int committed); int DPMIfree(unsigned long handle); dpmi_pm_block DPMIrealloc(unsigned long handle, unsigned long size); dpmi_pm_block DPMIreallocLinear(unsigned long handle, unsigned long size, int committed); +void DPMIfreeAll(void); int DPMIMapConventionalMemory(unsigned long handle, unsigned long offset, - dosaddr_t low_addr, unsigned long cnt); + unsigned long low_addr, unsigned long cnt); int DPMISetPageAttributes(unsigned long handle, int offs, u_short attrs[], int count); int DPMIGetPageAttributes(unsigned long handle, int offs, u_short attrs[], int count); void GetFreeMemoryInformation(unsigned int *lp); int GetDescriptor(u_short selector, unsigned int *lp); unsigned int GetSegmentBase(unsigned short sel); unsigned int GetSegmentLimit(unsigned short sel); -unsigned int GetSegmentType(unsigned short selector); -int CheckSelectors(cpuctx_t *scp, int in_dosemu); +int CheckSelectors(sigcontext_t *scp, int in_dosemu); int ValidAndUsedSelector(unsigned int selector); int dpmi_is_valid_range(dosaddr_t addr, int len); int dpmi_read_access(dosaddr_t addr); int dpmi_write_access(dosaddr_t addr); -extern char *DPMI_show_state(cpuctx_t *scp); +extern char *DPMI_show_state(sigcontext_t *scp); +extern void dpmi_sigio(sigcontext_t *scp); extern void run_dpmi(void); extern int ConvertSegmentToDescriptor(unsigned short segment); extern int SetSegmentBaseAddress(unsigned short selector, - dosaddr_t baseaddr); + unsigned long baseaddr); extern int SetSegmentLimit(unsigned short, unsigned int); extern DPMI_INTDESC dpmi_get_interrupt_vector(unsigned char num); extern void dpmi_set_interrupt_vector(unsigned char num, DPMI_INTDESC desc); @@ -229,7 +222,7 @@ extern int SetSelector(unsigned short selector, dosaddr_t base_addr, unsigned in unsigned char is_big, unsigned char seg_not_present, unsigned char useable); extern int SetDescriptor(unsigned short selector, unsigned int *lp); extern int FreeDescriptor(unsigned short selector); -extern void FreeSegRegs(cpuctx_t *scp, unsigned short selector); +extern void FreeSegRegs(sigcontext_t *scp, unsigned short selector); extern far_t DPMI_allocate_realmode_callback(u_short sel, int offs, u_short rm_sel, int rm_offs); extern int DPMI_free_realmode_callback(u_short seg, u_short off); @@ -245,39 +238,28 @@ extern void dpmi_ext_ldt_monitor_enable(int on); extern void dpmi_setup(void); extern void dpmi_reset(void); extern void dpmi_done(void); -extern void dpmi_done0(void); -extern int get_ldt(void *buffer, int len); +extern int get_ldt(void *buffer); +void dpmi_return(sigcontext_t *scp, int retcode); +void dpmi_return_request(void); +int dpmi_check_return(void); void dpmi_init(void); +void copy_to_dpmi(sigcontext_t *d, sigcontext_t *s); +void copy_to_emu(sigcontext_t *d, sigcontext_t *s); +void copy_context(sigcontext_t *d, sigcontext_t *s); extern unsigned short dpmi_sel(void); extern unsigned short dpmi_sel16(void); extern unsigned short dpmi_sel32(void); unsigned long dpmi_mem_size(void); +void dpmi_set_mem_bases(void *rsv_base, void *main_base); void dump_maps(void); int DPMIValidSelector(unsigned short selector); uint8_t *dpmi_get_ldt_buffer(void); -cpuctx_t *dpmi_get_scp(void); +sigcontext_t *dpmi_get_scp(void); int dpmi_realmode_exception(unsigned trapno, unsigned err, dosaddr_t cr2); -struct RSPcall_s { - unsigned char data16[8]; - unsigned char code16[8]; - unsigned short ip; -#define RSP_F_SW 1 // switch_client extension -#define RSP_F_LOWMEM 2 // extra lowmem extension - unsigned char flags; // extension - unsigned char para; // extension - unsigned char data32[8]; - unsigned char code32[8]; - unsigned int eip; -}; - -int dpmi_install_rsp(struct RSPcall_s *callback); -dosaddr_t DPMIMapHWRam(unsigned addr, unsigned size); -int DPMIUnmapHWRam(dosaddr_t vbase); - #endif // __ASSEMBLER__ #else #define DPMI_MAX_CLIENTS 0 @@ -321,10 +303,6 @@ static inline void dpmi_done(void) { } -static inline void dpmi_done0(void) -{ -} - static inline int in_dpmi_pm(void) { return 0; @@ -359,6 +337,10 @@ static inline int get_ldt(void *buffer) return -1; } +static inline void dpmi_set_mem_bases(void *rsv_base, void *main_base) +{ +} + static inline unsigned long dpmi_mem_size(void) { return 0; @@ -369,6 +351,11 @@ static inline int dpmi_fault(sigcontext_t *scp) return 0; } +static inline int dpmi_check_return(sigcontext_t *scp) +{ + return 0; +} + static inline void *SEL_ADR(unsigned short sel, unsigned int reg) { return NULL; @@ -384,17 +371,16 @@ static inline int DPMIValidSelector(unsigned short selector) return 0; } -static inline cpuctx_t *dpmi_get_scp(void) +static inline sigcontext_t *dpmi_get_scp(void) { return NULL; } -static inline unsigned int GetSegmentLimit(unsigned short sel) +static inline void dpmi_sigio(sigcontext_t *scp) { - return 0; } -static inline unsigned int GetSegmentType(unsigned short selector) +static inline unsigned int GetSegmentLimit(unsigned short sel) { return 0; } @@ -412,11 +398,19 @@ static inline void dpmi_get_entry_point(void) { } -static inline char *DPMI_show_state(cpuctx_t *scp) +static inline void dpmi_iret_unwind(sigcontext_t *scp) +{ +} + +static inline char *DPMI_show_state(sigcontext_t *scp) { return ""; } +static inline void dpmi_iret_setup(sigcontext_t *scp) +{ +} + static inline void dpmi_return_request(void) { } diff --git a/src/dosext/dpmi/memory.c b/src/dosext/dpmi/memory.c index 98e342b..f794f3e 100644 --- a/src/dosext/dpmi/memory.c +++ b/src/dosext/dpmi/memory.c @@ -15,7 +15,7 @@ * assert(size1 > size2 || addr2 >= addr1); * * This last assumption is not always true with the recent linux kernels - * (2.6.7-mm2 here). That's why we have to allocate the pool and manage + * (2.6.7-mm2 here). Thats why we have to allocate the pool and manage * the memory ourselves. */ @@ -30,7 +30,6 @@ #include /* for MREMAP_MAYMOVE */ #include #include "utilities.h" -#include "shlock.h" #include "mapping.h" #include "smalloc.h" #include "emudpmi.h" @@ -49,9 +48,44 @@ static unsigned int mem_allocd; /* how many bytes memory client */ unsigned int pm_block_handle_used; /* tracking handle */ static smpool mem_pool; -static unsigned char *dpmi_lin_rsv_base; -static unsigned char *dpmi_base; +static smpool lin_pool; +static void *dpmi_lin_rsv_base; +static void *dpmi_base; static const int dpmi_reserved_space = 4 * 1024 * 1024; // reserve 4Mb +static int extra_mf; + +void dpmi_set_map_flags(int cap) +{ + extra_mf = cap; +} + +static int in_rsv_pool(dosaddr_t base, unsigned int size) +{ + if (!dpmi_lin_rsv_base) + return 0; + if (base >= DOSADDR_REL(dpmi_lin_rsv_base) && + base < DOSADDR_REL(dpmi_lin_rsv_base) + + dpmi_lin_mem_rsv()) { + if (base + size <= DOSADDR_REL(dpmi_lin_rsv_base) + + dpmi_lin_mem_rsv()) + return 1; + return -1; + } + return 0; +} + +void dpmi_set_mem_bases(void *rsv_base, void *main_base) +{ + dpmi_lin_rsv_base = rsv_base; + dpmi_base = main_base; + /* Elite First Encounters setup.exe insists on reserve + * area being writable... */ + if (config.no_null_checks && rsv_base) + mprotect_mapping(MAPPING_DPMI, DOSADDR_REL(rsv_base), + dpmi_lin_mem_rsv(), PROT_READ | PROT_WRITE); + c_printf("DPMI memory mapped to %p (reserve) and to %p (main)\n", + rsv_base, main_base); +} /* utility routines */ @@ -71,7 +105,6 @@ static dpmi_pm_block * alloc_pm_block(dpmi_pm_block_root *root, unsigned long si } p->next = root->first_pm_block; /* add it to list */ root->first_pm_block = p; - p->mapped = 1; return p; } @@ -100,7 +133,6 @@ static int free_pm_block(dpmi_pm_block_root *root, dpmi_pm_block *p) free(p->attrs); free(p->shmname); free(p->rshmname); - free(p->shm_dir); free(p); if (tmp) tmp->next = next; @@ -125,7 +157,7 @@ dpmi_pm_block *lookup_pm_block_by_addr(dpmi_pm_block_root *root, { dpmi_pm_block *tmp; for(tmp = root->first_pm_block; tmp; tmp = tmp->next) { - if (tmp->mapped && addr >= tmp->base && addr < tmp->base + tmp->size) + if (addr >= tmp->base && addr < tmp->base + tmp->size) return tmp; } return NULL; @@ -142,19 +174,24 @@ dpmi_pm_block *lookup_pm_block_by_shmname(dpmi_pm_block_root *root, return NULL; } +int count_shm_blocks(dpmi_pm_block_root *root, const char *sname) +{ + int cnt = 0; + dpmi_pm_block *tmp; + for(tmp = root->first_pm_block; tmp; tmp = tmp->next) { + if (!tmp->shmname) + continue; + if (strcmp(tmp->shmname, sname) == 0) + cnt++; + } + return cnt; +} + static int commit(void *ptr, size_t size) { -#if HAVE_DECL_MADV_POPULATE_WRITE - int err; -#endif if (mprotect_mapping(MAPPING_DPMI, DOSADDR_REL(ptr), size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) return 0; -#if HAVE_DECL_MADV_POPULATE_WRITE - err = madvise(ptr, size, MADV_POPULATE_WRITE); - if (err) - perror("madvise()"); -#endif return 1; } @@ -188,35 +225,26 @@ void dump_maps(void) int dpmi_lin_mem_rsv(void) { - if (!config.dpmi) - return 0; - return PAGE_ALIGN(config.dpmi_base - (LOWMEM_SIZE + HMASIZE)); -} - -int dpmi_lin_mem_size(void) -{ - if (!config.dpmi) - return 0; - return dpmi_lin_mem_rsv() - (EXTMEM_SIZE + XMS_SIZE); + assert(dpmi_lin_rsv_base || !config.dpmi_lin_rsv_size); + return config.dpmi_lin_rsv_size * 1024; } int dpmi_lin_mem_free(void) { if (!dpmi_lin_rsv_base) return 0; - return smget_free_space_upto(&main_pool, - &dpmi_lin_rsv_base[dpmi_lin_mem_rsv()]); + return smget_free_space(&lin_pool); } int dpmi_alloc_pool(void) { uint32_t memsize = dpmi_mem_size(); - - dpmi_lin_rsv_base = MEM_BASE32(LOWMEM_SIZE + HMASIZE); - dpmi_base = MEM_BASE32(config.dpmi_base); c_printf("DPMI: mem init, mpool is %d bytes at %p\n", memsize, dpmi_base); /* Create DPMI pool */ sminit_com(&mem_pool, dpmi_base, memsize, commit, uncommit); + if (dpmi_lin_rsv_base) + sminit_com(&lin_pool, dpmi_lin_rsv_base, dpmi_lin_mem_rsv(), + commit, uncommit); dpmi_total_memory = config.dpmi * 1024; D_printf("DPMI: dpmi_free_memory available 0x%x\n", dpmi_total_memory); @@ -228,11 +256,16 @@ void dpmi_free_pool(void) int leak = smdestroy(&mem_pool); if (leak) error("DPMI: leaked %i bytes (main pool)\n", leak); + if (dpmi_lin_rsv_base) { + leak = smdestroy(&lin_pool); + if (leak) + error("DPMI: leaked %i bytes (lin pool)\n", leak); + } } -static int SetAttribsForPage(unsigned int ptr, uint16_t attr, uint16_t *old_attr_p) +static int SetAttribsForPage(unsigned int ptr, us attr, us *old_attr_p) { - uint16_t old_attr = *old_attr_p; + us old_attr = *old_attr_p; int prot, change = 0, com = attr & 3, old_com = old_attr & 1; switch (com) { @@ -358,7 +391,7 @@ static int SetAttribsForPage(unsigned int ptr, uint16_t attr, uint16_t *old_attr return 1; } -static int SetPageAttributes(dpmi_pm_block *block, int offs, uint16_t attrs[], int count) +static int SetPageAttributes(dpmi_pm_block *block, int offs, us attrs[], int count) { u_short *attr; int i; @@ -384,7 +417,7 @@ static void restore_page_protection(dpmi_pm_block *block) { int i; for (i = 0; i < block->size >> PAGE_SHIFT; i++) { - if ((block->attrs[i] & 1) == 0) { + if ((block->attrs[i] & 7) == 0) { mprotect_mapping(MAPPING_DPMI, block->base + (i << PAGE_SHIFT), PAGE_SIZE, PROT_NONE); } @@ -425,6 +458,8 @@ dpmi_pm_block * DPMI_mallocLinear(dpmi_pm_block_root *root, dpmi_pm_block *block; unsigned char *realbase; int i; + int inp = 0; + int cap = MAPPING_DPMI | MAPPING_SCRATCH; /* aligned size to PAGE size */ size = PAGE_ALIGN(size); @@ -434,35 +469,43 @@ dpmi_pm_block * DPMI_mallocLinear(dpmi_pm_block_root *root, base = -1; else { /* fixed allocation */ - if (base < DOSADDR_REL(dpmi_lin_rsv_base)) { + if (base < LOWMEM_SIZE + HMASIZE) { D_printf("DPMI: failing lin alloc to lowmem %x, size %x\n", base, size); return NULL; } - if ((uint64_t)base + size > DOSADDR_REL(dpmi_lin_rsv_base) + - dpmi_lin_mem_rsv()) { + /* disallow last page allocs as our code is full of potential + * integer overflows, plus MAP_FAILED should be invalid ptr */ + if ((uint64_t)base + size > (uint32_t)PAGE_MASK) { D_printf("DPMI: failing lin alloc to %x, size %x\n", base, size); return NULL; } + inp = in_rsv_pool(base, size); + if (inp == -1) + return NULL; + if (!inp) + cap |= MAPPING_NOOVERLAP; } if (committed && size > dpmi_free_memory()) return NULL; if ((block = alloc_pm_block(root, size)) == NULL) return NULL; - if (base == -1) - realbase = smalloc_aligned_topdown(&main_pool, - &dpmi_lin_rsv_base[dpmi_lin_mem_rsv()], - PAGE_SIZE, size); - else - realbase = smalloc_fixed(&main_pool, MEM_BASE32(base), size); - if (realbase == NULL) { - free_pm_block(root, block); - return NULL; + if (inp) { + realbase = smalloc_fixed(&lin_pool, MEM_BASE32(base), size); + if (realbase == NULL) { + free_pm_block(root, block); + return NULL; + } + } else { + realbase = mmap_mapping(cap | extra_mf, + base, size, committed ? PROT_READ | PROT_WRITE | PROT_EXEC : PROT_NONE); + if (realbase == MAP_FAILED) { + free_pm_block(root, block); + return NULL; + } } block->base = DOSADDR_REL(realbase); - mprotect_mapping(MAPPING_DPMI, block->base, size, committed ? - PROT_READ | PROT_WRITE | PROT_EXEC : PROT_NONE); block->linear = 1; for (i = 0; i < size >> PAGE_SHIFT; i++) block->attrs[i] = committed ? 9 : 8; @@ -501,31 +544,12 @@ static void do_unmap_hwram(dpmi_pm_block_root *root, dpmi_pm_block *block) free_pm_block(root, block); } -static void do_unmap_shm(dpmi_pm_block *block) -{ - int err = restore_mapping(MAPPING_DPMI, block->base, block->size); - if (err) - error("restore_mapping() failed\n"); - smfree(&mem_pool, MEM_BASE32(block->base)); - block->mapped = 0; -} - int DPMI_unmapHWRam(dpmi_pm_block_root *root, dosaddr_t vbase) { dpmi_pm_block *block = lookup_pm_block_by_addr(root, vbase); if (!block) return -1; - if (block->hwram) { - do_unmap_hwram(root, block); - } else if (block->shm) { - /* extension: allow unmap shared block as hwram */ - do_unmap_shm(block); - if (!block->shmname) - free_pm_block(root, block); - } else { - error("DPMI: wrong free hwram, %i\n", block->hwram); - return -1; - } + do_unmap_hwram(root, block); return 0; } @@ -536,32 +560,23 @@ int DPMI_free(dpmi_pm_block_root *root, unsigned int handle) if ((block = lookup_pm_block(root, handle)) == NULL) return -1; - if (block->hwram) { - error("DPMI: wrong free hwram, %i\n", block->hwram); - return -1; - } - if (block->shmname) { - error("DPMI: wrong free smem, %s\n", block->shmname); + if (block->hwram || block->shmname) { + error("DPMI: wrong free, %i\n", block->hwram); return -1; } e_invalidate_full(block->base, block->size); - if (block->shm) { - if (block->mapped) - do_unmap_shm(block); - } else if (block->linear) { - for (i = 0; i < block->size >> PAGE_SHIFT; i++) { - if ((block->attrs[i] & 3) == 2) // mapped - restore_mapping(MAPPING_DPMI, block->base + i * PAGE_SIZE, - PAGE_SIZE); - } - mprotect_mapping(MAPPING_DPMI, block->base, block->size, - PROT_READ | PROT_WRITE); - smfree(&main_pool, MEM_BASE32(block->base)); + if (block->linear) { + int inp = in_rsv_pool(block->base, block->size); + assert(inp != -1); + if (inp) + smfree(&lin_pool, MEM_BASE32(block->base)); + else + munmap(MEM_BASE32(block->base), block->size); } else { smfree(&mem_pool, MEM_BASE32(block->base)); } for (i = 0; i < block->size >> PAGE_SHIFT; i++) { - if ((block->attrs[i] & 7) == 1) { // if committed priv page, account it + if ((block->attrs[i] & 7) == 1) { // if committed page, account it assert(mem_allocd >= PAGE_SIZE); mem_allocd -= PAGE_SIZE; } @@ -570,362 +585,85 @@ int DPMI_free(dpmi_pm_block_root *root, unsigned int handle) return 0; } -#define EXLOCK_DIR "dosemu2_shmex" -#define SHLOCK_DIR "dosemu2_shmsh" - dpmi_pm_block *DPMI_mallocShared(dpmi_pm_block_root *root, - const char *name, unsigned int size, int flags) + char *name, unsigned int size, unsigned int shmsize, int flags) { #ifdef HAVE_SHM_OPEN - int i, err; - int fd = -1; + int i; + int fd; dpmi_pm_block *ptr; - void *addr, *addr2; + void *addr; char *shmname; - struct stat st; - void *exlock, *shlock; - int oflags = O_RDWR | O_CREAT; + int init = 0; + int oflags = O_RDWR; int prot = PROT_READ | PROT_WRITE; if (!size) // DPMI spec says this is allowed - no thanks return NULL; - - exlock = shlock_open(EXLOCK_DIR, name, 1, 1); - if (!exlock) { - error("exlock failed\n"); - return NULL; - } - if (flags & SHM_EXCL) - oflags |= O_EXCL; - shlock = shlock_open(SHLOCK_DIR, name, 0, 1); - if (!shlock) { - error("lock failed for %s\n", name); - goto err0; + size = PAGE_ALIGN(size); + if (shmsize) { + assert(!(shmsize & (PAGE_SIZE - 1))); + if (size > shmsize) + size = shmsize; + } else { + init = 1; + shmsize = size; } - asprintf(&shmname, "/dosemu_%s", name); + asprintf(&shmname, "/dosemu_dpmishm_%d_%s", getpid(), name); + if (init) + oflags |= O_CREAT; fd = shm_open(shmname, oflags, S_IRUSR | S_IWUSR); - if (fd == -1 && (flags & SHM_EXCL) && errno == EEXIST) { - error("shm object %s already exists\n", shmname); - /* SHM_EXCL should provide the exclusive name (with pid), - * so the object might be orphaned */ - shm_unlink(shmname); - fd = shm_open(shmname, oflags, S_IRUSR | S_IWUSR); - } if (fd == -1) { perror("shm_open()"); error("shared memory unavailable, exiting\n"); - goto err1; - } - - err = fstat(fd, &st); - assert(!err); - if (st.st_size) { - if (size > st.st_size) { - error("DPMI: reducing %s size from %i to %zi\n", - shmname, size, st.st_size); - size = st.st_size; - } - } else { - err = ftruncate(fd, size); - if (err) { - error("unable to ftruncate to %x for shm %s\n", size, name); - goto err2; - } - } - shlock_close(exlock); - exlock = NULL; - - addr = smalloc(&mem_pool, size); - if (!addr) { - error("unable to alloc %x for shm %s\n", size, name); - goto err2; + leavedos(2); + return NULL; } + if (init) + ftruncate(fd, shmsize); if (!(flags & SHM_NOEXEC)) prot |= PROT_EXEC; - /* this mem is already mapped to KVM so we use plain mmap() */ - addr2 = mmap(addr, size, prot, MAP_SHARED | MAP_FIXED, fd, 0); + addr = mmap_file_ux(MAPPING_DPMI | extra_mf, + NULL, size, prot, MAP_SHARED | MAP_32BIT, fd); close(fd); - fd = -1; - if (addr2 != addr) { + if (addr == MAP_FAILED) { perror("mmap()"); - error("shared memory map failed %p %p\n", addr2, addr); - goto err3; + error("shared memory map failed, exiting\n"); + leavedos(2); + return NULL; } ptr = alloc_pm_block(root, size); - if (!ptr) { - error("pm block alloc failed, exiting\n"); - goto err4; - } + if (!ptr) + return NULL; for (i = 0; i < (size >> PAGE_SHIFT); i++) ptr->attrs[i] = 0x09 | ATTR_SHR; // RW, shared, present ptr->base = DOSADDR_REL(addr); ptr->size = size; - ptr->shm = 1; + ptr->shmsize = shmsize; ptr->linear = 1; ptr->handle = pm_block_handle_used++; ptr->shmname = strdup(name); ptr->rshmname = shmname; - ptr->shlock = shlock; D_printf("DPMI: map shm %s\n", ptr->shmname); return ptr; - -err4: - munmap(addr2, size); -err3: - smfree(&mem_pool, addr); -err2: - if (fd != -1) - close(fd); -err1: - free(shmname); - shlock_close(shlock); -err0: - if (exlock) - shlock_close(exlock); -// leavedos(2); - return NULL; #else return NULL; #endif } -static dpmi_pm_block *DPMI_mallocSharedNS_common(dpmi_pm_block_root *root, - const char *dname, const char *name, unsigned int size, int flags, - int fd) +int DPMI_freeShared(dpmi_pm_block_root *root, uint32_t handle, int unlnk) { - int i, err; - dpmi_pm_block *ptr; - void *addr, *addr2; - void *shlock, *dlock; - char *ddname = strrchr(dname, '/') + 1; - char shlock_dir[256]; - int prot = PROT_READ | PROT_WRITE; - - dlock = shlock_open(SHLOCK_DIR, ddname, 0, 1); - if (!dlock) { - error("dlock failed for %s\n", ddname); - goto err11; - } - snprintf(shlock_dir, sizeof(shlock_dir), SHLOCK_DIR "_%s", ddname); - shlock = shlock_open(shlock_dir, name, 0, 1); - if (!shlock) { - error("lock failed for %s\n", name); - goto err12; - } - err = ftruncate(fd, size); - if (err) { - error("unable to ftruncate to %x for shm %s\n", size, name); - goto err2; - } - - addr = smalloc(&mem_pool, size); - if (!addr) { - error("unable to alloc %x for shm %s\n", size, name); - goto err2; - } - if (!(flags & SHM_NOEXEC)) - prot |= PROT_EXEC; - /* this mem is already mapped to KVM so we use plain mmap() */ - addr2 = mmap(addr, size, prot, MAP_SHARED | MAP_FIXED, fd, 0); - close(fd); - fd = -1; - if (addr2 != addr) { - perror("mmap()"); - error("shared memory map failed %p %p\n", addr2, addr); - goto err3; - } - ptr = alloc_pm_block(root, size); - if (!ptr) { - error("pm block alloc failed, exiting\n"); - goto err4; - } - for (i = 0; i < (size >> PAGE_SHIFT); i++) - ptr->attrs[i] = 0x09 | ATTR_SHR; // RW, shared, present - ptr->base = DOSADDR_REL(addr); - ptr->size = size; - ptr->shm = 1; - ptr->linear = 1; - ptr->handle = pm_block_handle_used++; - ptr->shmname = strdup(name); - ptr->shm_dir = strdup(dname); - ptr->shlock = shlock; - ptr->dlock = dlock; - D_printf("DPMI: map shm %s\n", ptr->shmname); - return ptr; - -err4: - munmap(addr2, size); -err3: - smfree(&mem_pool, addr); -err2: - shlock_close(shlock); -err12: - shlock_close(dlock); -err11: - if (fd != -1) - close(fd); - return NULL; -} - -dpmi_pm_block *DPMI_mallocSharedNewNS(dpmi_pm_block_root *root, - const char *name, unsigned int size, int flags) -{ - int fd = -1; - dpmi_pm_block *ptr; - char *shmname, *fname; - char dname[] = "/tmp/dosemu2_pshm_XXXXXX"; - - if (!size) // DPMI spec says this is allowed - no thanks - return NULL; - - asprintf(&shmname, "/dosemu_%s", name); - fd = mktmp_in(dname, shmname, S_IRWXU); - if (fd == -1) { - error("shared memory unavailable, exiting\n"); - goto err1; - } - ptr = DPMI_mallocSharedNS_common(root, dname, name, size, flags, fd); - if (!ptr) - goto err2; - ptr->rshmname = shmname; - return ptr; - -err2: - fname = assemble_path(dname, shmname); - unlink(fname); - free(fname); -err1: - free(shmname); - return NULL; -} - -dpmi_pm_block *DPMI_mallocSharedNS(dpmi_pm_block_root *root, - const char *dname, const char *name, unsigned int size, int flags) -{ - int fd = -1; - dpmi_pm_block *ptr; - char *shmname, *fname; - int oflags = O_RDWR | O_CREAT; - - if (!size) // DPMI spec says this is allowed - no thanks - return NULL; - - asprintf(&shmname, "/dosemu_%s", name); - if (flags & SHM_EXCL) - oflags |= O_EXCL; - fname = assemble_path(dname, shmname); - fd = open(fname, oflags, S_IRWXU); - if (fd == -1) { - error("shared memory unavailable, exiting\n"); - goto err1; - } - ptr = DPMI_mallocSharedNS_common(root, dname, name, size, flags, fd); - if (!ptr) - goto err2; - free(fname); - ptr->rshmname = shmname; - return ptr; - -err2: - unlink(fname); -err1: - free(fname); - free(shmname); - return NULL; -} - -int DPMI_freeShared(dpmi_pm_block_root *root, uint32_t handle) -{ -#ifdef HAVE_SHM_OPEN - void *exlock; - int rc; dpmi_pm_block *ptr = lookup_pm_block(root, handle); - if (!ptr || !ptr->shmname) + if (!ptr || !(ptr->attrs[0] & ATTR_SHR)) return -1; - if (ptr->mapped) - do_unmap_shm(ptr); - - exlock = shlock_open(EXLOCK_DIR, ptr->shmname, 1, 1); - assert(exlock); - rc = shlock_close(ptr->shlock); - ptr->shlock = NULL; - if (rc > 0) { + munmap_mapping(MAPPING_DPMI | MAPPING_IMMEDIATE, ptr->base, ptr->size); + if (unlnk) { D_printf("DPMI: unlink shm %s\n", ptr->rshmname); shm_unlink(ptr->rshmname); } - shlock_close(exlock); - free_pm_block(root, ptr); return 0; -#else - return -1; -#endif -} - -int DPMI_freeSharedNS(dpmi_pm_block_root *root, uint32_t handle) -{ - int rc; - dpmi_pm_block *ptr = lookup_pm_block(root, handle); - if (!ptr || !ptr->shmname) - return -1; - if (ptr->mapped) - do_unmap_shm(ptr); - - rc = shlock_close(ptr->shlock); - ptr->shlock = NULL; - if (rc > 0) { - char *fname = assemble_path(ptr->shm_dir, ptr->rshmname); - D_printf("DPMI: unlink shm %s\n", fname); - unlink(fname); - free(fname); - } - - rc = shlock_close(ptr->dlock); - ptr->dlock = NULL; - if (rc > 0) { - D_printf("DPMI: unlink dir %s\n", ptr->shm_dir); - rc = rmdir(ptr->shm_dir); - if (rc) - error("rmdir(%s) failed: %s\n", ptr->shm_dir, strerror(errno)); - } - - free_pm_block(root, ptr); - return 0; -} - -int DPMI_freeShPartial(dpmi_pm_block_root *root, uint32_t handle) -{ -#ifdef HAVE_SHM_OPEN - void *exlock; - int rc; - dpmi_pm_block *ptr = lookup_pm_block(root, handle); - if (!ptr || !ptr->shmname) - return -1; - - exlock = shlock_open(EXLOCK_DIR, ptr->shmname, 1, 1); - assert(exlock); - rc = 1; - if (ptr->shlock) - rc = shlock_close(ptr->shlock); - if (rc > 0) { - D_printf("DPMI: unlink shm %s\n", ptr->rshmname); - shm_unlink(ptr->rshmname); - } - shlock_close(exlock); - - if (ptr->mapped) { - free(ptr->shmname); - ptr->shmname = NULL; - free(ptr->rshmname); - ptr->rshmname = NULL; - } else { - free_pm_block(root, ptr); - } - return 0; -#else - return -1; -#endif } static void finish_realloc(dpmi_pm_block *block, unsigned long newsize, @@ -996,6 +734,7 @@ dpmi_pm_block * DPMI_reallocLinear(dpmi_pm_block_root *root, { dpmi_pm_block *block; unsigned char *ptr; + int inp; if (!newsize) /* DPMI spec. says resize to 0 is an error */ return NULL; @@ -1024,39 +763,46 @@ dpmi_pm_block * DPMI_reallocLinear(dpmi_pm_block_root *root, e_invalidate_full(block->base, block->size); mprotect_mapping(MAPPING_DPMI, block->base, block->size, PROT_READ | PROT_WRITE | PROT_EXEC); - ptr = smrealloc(&main_pool, MEM_BASE32(block->base), newsize); - if (ptr == NULL) { - restore_page_protection(block); - return NULL; + inp = in_rsv_pool(block->base, block->size); + assert(inp != -1); + if (inp) { + ptr = smrealloc(&lin_pool, MEM_BASE32(block->base), newsize); + if (ptr == NULL) { + restore_page_protection(block); + return NULL; + } + } else { + ptr = mremap_mapping(MAPPING_DPMI, block->base, block->size, newsize); + if (ptr == MAP_FAILED) { + restore_page_protection(block); + return NULL; + } } finish_realloc(block, newsize, committed); block->base = DOSADDR_REL(ptr); block->size = newsize; - /* restore_page_protection() will set proper prots */ - mprotect_mapping(MAPPING_DPMI, block->base, block->size, - PROT_READ | PROT_WRITE | PROT_EXEC); restore_page_protection(block); return block; } -void DPMI_freeAll(dpmi_pm_block_root *root, dpmi_pm_block *p) +void DPMI_freeAll(dpmi_pm_block_root *root) { - if (p->hwram) - do_unmap_hwram(root, p); - else if (p->shmname && p->shm_dir) - DPMI_freeSharedNS(root, p->handle); - else if (p->shmname) - DPMI_freeShared(root, p->handle); - else - DPMI_free(root, p->handle); + dpmi_pm_block **p = &root->first_pm_block; + while(*p) { + if ((*p)->hwram) + do_unmap_hwram(root, *p); + else if ((*p)->shmname) + DPMI_freeShared(root, (*p)->handle, 1); + else + DPMI_free(root, (*p)->handle); + } } int DPMI_MapConventionalMemory(dpmi_pm_block_root *root, unsigned long handle, unsigned long offset, unsigned long low_addr, unsigned long cnt) { - int i; /* NOTE: * This DPMI function makes appear memory from below 1Meg to * address space allocated via DPMImalloc(). We use it only for @@ -1075,16 +821,11 @@ int DPMI_MapConventionalMemory(dpmi_pm_block_root *root, return -1; } - for (i = offset / PAGE_SIZE; i < cnt + offset / PAGE_SIZE; i++) { - block->attrs[i] &= ~3; - block->attrs[i] |= 2; // mapped - } - return 0; } int DPMI_SetPageAttributes(dpmi_pm_block_root *root, unsigned long handle, - int offs, uint16_t attrs[], int count) + int offs, us attrs[], int count) { dpmi_pm_block *block; @@ -1103,7 +844,7 @@ int DPMI_SetPageAttributes(dpmi_pm_block_root *root, unsigned long handle, } int DPMI_GetPageAttributes(dpmi_pm_block_root *root, unsigned long handle, - int offs, uint16_t attrs[], int count) + int offs, us attrs[], int count) { dpmi_pm_block *block; int i; @@ -1124,20 +865,3 @@ int dpmi_free_memory(void) return 0; return (dpmi_total_memory - mem_allocd); } - -int dpmi_alloced_memory(void) -{ - return mem_allocd; -} - -int dpmi_largest_memory_block(void) -{ - unsigned ret, fr; - if (!config.dpmi) - return 0; - ret = smget_largest_free_area(&mem_pool); - fr = dpmi_free_memory(); - if (ret > fr) - ret = fr; - return ret; -} diff --git a/src/dosext/dpmi/msdos/Makefile b/src/dosext/dpmi/msdos/Makefile index d22ae40..cfcbb2e 100644 --- a/src/dosext/dpmi/msdos/Makefile +++ b/src/dosext/dpmi/msdos/Makefile @@ -1,10 +1,9 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.conf -CFILES = msdos.c segreg.c msdos_ldt.c instr_dec.c callbacks.c emm.c lio.c \ - xms.c hlpmisc.c +CFILES = msdos.c segreg.c msdos_ldt.c instr_dec.c callbacks.c emm.c lio.c xms.c -all: lib +all: lib include $(REALTOPDIR)/src/Makefile.common ALL_CPPFLAGS += -DDOSEMU -I$(srcdir)/.. diff --git a/src/dosext/dpmi/msdos/callbacks.c b/src/dosext/dpmi/msdos/callbacks.c index ea59a30..1fbb035 100644 --- a/src/dosext/dpmi/msdos/callbacks.c +++ b/src/dosext/dpmi/msdos/callbacks.c @@ -43,13 +43,13 @@ static void do_retf(struct RealModeCallStructure *rmreg, int rmask) RMREG(sp) += 4; } -static void rmcb_ret_handler(cpuctx_t *scp, +static void rmcb_ret_handler(sigcontext_t *scp, struct RealModeCallStructure *rmreg, int is_32) { do_retf(rmreg, (1 << ss_INDEX) | (1 << esp_INDEX)); } -static void rmcb_ret_from_ps2(cpuctx_t *scp, +static void rmcb_ret_from_ps2(sigcontext_t *scp, struct RealModeCallStructure *rmreg, int is_32) { if (is_32) @@ -59,7 +59,7 @@ static void rmcb_ret_from_ps2(cpuctx_t *scp, do_retf(rmreg, (1 << ss_INDEX) | (1 << esp_INDEX)); } -static void rm_to_pm_regs(cpuctx_t *scp, +static void rm_to_pm_regs(sigcontext_t *scp, const struct RealModeCallStructure *rmreg, unsigned int mask) { @@ -83,7 +83,7 @@ static void rm_to_pm_regs(cpuctx_t *scp, _LWORD(ebp) = RMLWORD(bp); } -static void pm_to_rm_regs(const cpuctx_t *scp, +static void pm_to_rm_regs(const sigcontext_t *scp, struct RealModeCallStructure *rmreg, unsigned int mask) { @@ -105,7 +105,7 @@ static void pm_to_rm_regs(const cpuctx_t *scp, X_RMREG(ebp) = _LWORD_(ebp_); } -static void mouse_callback(cpuctx_t *scp, +static void mouse_callback(sigcontext_t *scp, const struct RealModeCallStructure *rmreg, int is_32, void *arg) { @@ -137,7 +137,7 @@ static void mouse_callback(cpuctx_t *scp, _eip = mouseCallBack->offset; } -static void ps2_mouse_callback(cpuctx_t *scp, +static void ps2_mouse_callback(sigcontext_t *scp, const struct RealModeCallStructure *rmreg, int is_32, void *arg) { @@ -185,7 +185,7 @@ static void ps2_mouse_callback(cpuctx_t *scp, _eip = PS2mouseCallBack->offset; } -struct pmrm_ret msdos_ext_call(cpuctx_t *scp, +struct pmrm_ret msdos_ext_call(sigcontext_t *scp, struct RealModeCallStructure *rmreg, unsigned short rm_seg, void *(*arg)(int), int off) { @@ -201,7 +201,7 @@ struct pmrm_ret msdos_ext_call(cpuctx_t *scp, return ret; } -struct pext_ret msdos_ext_ret(cpuctx_t *scp, +struct pext_ret msdos_ext_ret(sigcontext_t *scp, const struct RealModeCallStructure *rmreg, unsigned short rm_seg, int off) { @@ -214,7 +214,7 @@ struct pext_ret msdos_ext_ret(cpuctx_t *scp, return ret; } -void msdos_api_call(cpuctx_t *scp, void *arg) +void msdos_api_call(sigcontext_t *scp, void *arg) { u_short *(*cb)(void) = arg; const u_short *ldt_alias = cb(); @@ -233,7 +233,7 @@ void msdos_api_call(cpuctx_t *scp, void *arg) } } -void msdos_api_winos2_call(cpuctx_t *scp, void *arg) +void msdos_api_winos2_call(sigcontext_t *scp, void *arg) { u_short *(*cb)(void) = arg; const u_short *ldt_alias_winos2 = cb(); @@ -252,14 +252,14 @@ void msdos_api_winos2_call(cpuctx_t *scp, void *arg) } } -static void (*rmcb_handlers[])(cpuctx_t *scp, +static void (*rmcb_handlers[])(sigcontext_t *scp, const struct RealModeCallStructure *rmreg, int is_32, void *arg) = { [RMCB_MS] = mouse_callback, [RMCB_PS2MS] = ps2_mouse_callback, }; -static void (*rmcb_ret_handlers[])(cpuctx_t *scp, +static void (*rmcb_ret_handlers[])(sigcontext_t *scp, struct RealModeCallStructure *rmreg, int is_32) = { [RMCB_MS] = rmcb_ret_handler, [RMCB_PS2MS] = rmcb_ret_from_ps2, diff --git a/src/dosext/dpmi/msdos/callbacks.h b/src/dosext/dpmi/msdos/callbacks.h index 0536db5..b771d1e 100644 --- a/src/dosext/dpmi/msdos/callbacks.h +++ b/src/dosext/dpmi/msdos/callbacks.h @@ -3,13 +3,13 @@ #include -void msdos_api_call(cpuctx_t *scp, void *arg); -void msdos_api_winos2_call(cpuctx_t *scp, void *arg); +void msdos_api_call(sigcontext_t *scp, void *arg); +void msdos_api_winos2_call(sigcontext_t *scp, void *arg); -struct pmrm_ret msdos_ext_call(cpuctx_t *scp, +struct pmrm_ret msdos_ext_call(sigcontext_t *scp, struct RealModeCallStructure *rmreg, unsigned short rm_seg, void *(*arg)(int), int off); -struct pext_ret msdos_ext_ret(cpuctx_t *scp, +struct pext_ret msdos_ext_ret(sigcontext_t *scp, const struct RealModeCallStructure *rmreg, unsigned short rm_seg, int off); diff --git a/src/dosext/dpmi/msdos/emm.c b/src/dosext/dpmi/msdos/emm.c index 16bc5e6..48e26ff 100644 --- a/src/dosext/dpmi/msdos/emm.c +++ b/src/dosext/dpmi/msdos/emm.c @@ -34,7 +34,7 @@ #define EMM_INT 0x67 -int emm_allocate_handle(cpuctx_t *scp, int is_32, int pages_needed) +int emm_allocate_handle(sigcontext_t *scp, int is_32, int pages_needed) { __dpmi_regs regs = {0}; regs.h.ah = ALLOCATE_PAGES; @@ -45,7 +45,7 @@ int emm_allocate_handle(cpuctx_t *scp, int is_32, int pages_needed) return regs.x.dx; } -int emm_save_handle_state(cpuctx_t *scp, int is_32, int handle) +int emm_save_handle_state(sigcontext_t *scp, int is_32, int handle) { __dpmi_regs regs = {0}; regs.h.ah = SAVE_PAGE_MAP; @@ -56,7 +56,7 @@ int emm_save_handle_state(cpuctx_t *scp, int is_32, int handle) return 0; } -int emm_restore_handle_state(cpuctx_t *scp, int is_32, int handle) +int emm_restore_handle_state(sigcontext_t *scp, int is_32, int handle) { __dpmi_regs regs = {0}; regs.h.ah = RESTORE_PAGE_MAP; @@ -67,7 +67,7 @@ int emm_restore_handle_state(cpuctx_t *scp, int is_32, int handle) return 0; } -int emm_map_unmap_multi(cpuctx_t *scp, int is_32, const u_short *array, +int emm_map_unmap_multi(sigcontext_t *scp, int is_32, const u_short *array, int handle, int map_len) { uint16_t buf_seg = get_scratch_seg(); @@ -89,7 +89,7 @@ int emm_map_unmap_multi(cpuctx_t *scp, int is_32, const u_short *array, return 0; } -int emm_get_mpa_len(cpuctx_t *scp, int is_32) +int emm_get_mpa_len(sigcontext_t *scp, int is_32) { __dpmi_regs regs = {0}; regs.h.ah = GET_MPA_ARRAY; @@ -100,7 +100,7 @@ int emm_get_mpa_len(cpuctx_t *scp, int is_32) return regs.x.cx; } -int emm_get_mpa_array(cpuctx_t *scp, int is_32, +int emm_get_mpa_array(sigcontext_t *scp, int is_32, struct emm_phys_page_desc *array, int max_len) { uint16_t buf_seg = get_scratch_seg(); diff --git a/src/dosext/dpmi/msdos/emm_msdos.h b/src/dosext/dpmi/msdos/emm_msdos.h index 589062c..372a1c8 100644 --- a/src/dosext/dpmi/msdos/emm_msdos.h +++ b/src/dosext/dpmi/msdos/emm_msdos.h @@ -2,19 +2,19 @@ #ifndef EMM_MSDOS_H #define EMM_MSDOS_H -int emm_allocate_handle(cpuctx_t *scp, int is_32, int pages_needed); -int emm_deallocate_handle(cpuctx_t *scp, int is_32, int handle); -int emm_save_handle_state(cpuctx_t *scp, int is_32, int handle); -int emm_restore_handle_state(cpuctx_t *scp, int is_32, int handle); -int emm_map_unmap_multi(cpuctx_t *scp, int is_32, const u_short *array, +int emm_allocate_handle(sigcontext_t *scp, int is_32, int pages_needed); +int emm_deallocate_handle(sigcontext_t *scp, int is_32, int handle); +int emm_save_handle_state(sigcontext_t *scp, int is_32, int handle); +int emm_restore_handle_state(sigcontext_t *scp, int is_32, int handle); +int emm_map_unmap_multi(sigcontext_t *scp, int is_32, const u_short *array, int handle, int map_len); -int emm_get_mpa_len(cpuctx_t *scp, int is_32); +int emm_get_mpa_len(sigcontext_t *scp, int is_32); struct emm_phys_page_desc { uint16_t seg; uint16_t num; }; -int emm_get_mpa_array(cpuctx_t *scp, int is_32, +int emm_get_mpa_array(sigcontext_t *scp, int is_32, struct emm_phys_page_desc *array, int max_len); #endif diff --git a/src/dosext/dpmi/msdos/hlpmisc.c b/src/dosext/dpmi/msdos/hlpmisc.c deleted file mode 100644 index 446d54d..0000000 --- a/src/dosext/dpmi/msdos/hlpmisc.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "dpmi_api.h" -#include "hlpmisc.h" - -void do_call_to(cpuctx_t *scp, int is_32, far_t dst, __dpmi_regs *rmreg) -{ - RMREG(ss) = 0; - RMREG(sp) = 0; - RMREG(cs) = dst.segment; - RMREG(ip) = dst.offset; - _dpmi_simulate_real_mode_procedure_retf(scp, is_32, rmreg); -} diff --git a/src/dosext/dpmi/msdos/hlpmisc.h b/src/dosext/dpmi/msdos/hlpmisc.h index ca10b87..3fd632e 100644 --- a/src/dosext/dpmi/msdos/hlpmisc.h +++ b/src/dosext/dpmi/msdos/hlpmisc.h @@ -1,17 +1,10 @@ -#ifndef HLPMISC_H -#define HLPMISC_H - -#include "cpu.h" -#include "djdpmi.h" -#include "emudpmi.h" - #ifdef DOSEMU #define RMREG(r) (rmreg->x.r) #define RMLWORD(r) (rmreg->x.r) #define X_RMREG(r) (rmreg->d.r) #endif -static inline void pm_to_rm_regs(const cpuctx_t *scp, +static inline void pm_to_rm_regs(const sigcontext_t *scp, __dpmi_regs *rmreg, unsigned int mask) { if (mask & (1 << eflags_INDEX)) @@ -32,7 +25,7 @@ static inline void pm_to_rm_regs(const cpuctx_t *scp, X_RMREG(ebp) = _LWORD_(ebp_); } -static inline void rm_to_pm_regs(cpuctx_t *scp, +static inline void rm_to_pm_regs(sigcontext_t *scp, const __dpmi_regs *rmreg, unsigned int mask) { /* WARNING - realmode flags can contain the dreadful NT flag @@ -60,7 +53,3 @@ static inline void rm_to_pm_regs(cpuctx_t *scp, #define RMPRESERVE2(rg1, rg2) (rm_mask |= ((1 << rg1##_INDEX) | (1 << rg2##_INDEX))) #define SET_RMREG(rg, val) (RMPRESERVE1(rg), RMREG(rg) = (val)) #define SET_RMLWORD(rg, val) (E_RMPRESERVE1(rg), RMREG(rg) = (val)) - -void do_call_to(cpuctx_t *scp, int is_32, far_t dst, __dpmi_regs *rmreg); - -#endif diff --git a/src/dosext/dpmi/msdos/instr_dec.c b/src/dosext/dpmi/msdos/instr_dec.c index d5e2f93..6118043 100644 --- a/src/dosext/dpmi/msdos/instr_dec.c +++ b/src/dosext/dpmi/msdos/instr_dec.c @@ -27,20 +27,18 @@ #include "cpu.h" #include "dosemu_debug.h" #include "memory.h" -#include "dos2linux.h" #include "emudpmi.h" +#include "instremu.h" #include "instr_dec.h" typedef struct x86_ins { - unsigned _32bit:1; /* 16/32 bit code */ + int _32bit:1; /* 16/32 bit code */ unsigned address_size; /* in bytes so either 4 or 2 */ unsigned operand_size; int rep; - unsigned ds:1, es:1, fs:1, gs:1, cs:1, ss:1; + int ds:1, es:1, fs:1, gs:1, cs:1, ss:1; } x86_ins; -static unsigned short patch_cs; - #define R_WORD(a) LO_WORD(a) #define SP (R_WORD(_esp)) #define sreg_idx(reg) (es_INDEX+((reg)&0x7)) @@ -48,333 +46,18 @@ static unsigned short patch_cs; enum {REP_NONE, REPZ, REPNZ}; static unsigned wordmask[5] = {0,0xff,0xffff,0xffffff,0xffffffff}; -static unsigned char it[0x100] = { - 7, 7, 7, 7, 2, 3, 1, 1, 7, 7, 7, 7, 2, 3, 1, 0, - 7, 7, 7, 7, 2, 3, 1, 1, 7, 7, 7, 7, 2, 3, 1, 1, - 7, 7, 7, 7, 2, 3, 0, 1, 7, 7, 7, 7, 2, 3, 0, 1, - 7, 7, 7, 7, 2, 3, 0, 1, 7, 7, 7, 7, 2, 3, 0, 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, 7, 7, 0, 0, 0, 0, 3, 9, 2, 8, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - - 8, 9, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1, - 4, 4, 4, 4, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - - 8, 8, 3, 1, 7, 7, 8, 9, 5, 1, 3, 1, 1, 2, 1, 1, - 7, 7, 7, 7, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 6, 2, 1, 1, 1, 1, - 0, 1, 0, 0, 1, 1, 7, 7, 1, 1, 1, 1, 1, 1, 7, 7 -}; - -static unsigned arg_len(unsigned char *p, int asp) -{ - unsigned u = 0, m, s = 0; - - m = *p & 0xc7; - if(asp) { - if(m == 5) { - u = 5; - } - else { - if((m >> 6) < 3 && (m & 7) == 4) s = 1; - switch(m >> 6) { - case 1: - u = 2; break; - case 2: - u = 5; break; - default: - u = 1; - } - u += s; - } - } - else { - if(m == 6) - u = 3; - else - switch(m >> 6) { - case 1: - u = 2; break; - case 2: - u = 3; break; - default: - u = 1; - } - } - - return u; -} - -static int _instr_len(unsigned char *p, int is_32) -{ - unsigned u, osp, asp; - unsigned char *p0 = p; - - osp = asp = is_32; - - for(u = 1; u && p - p0 < 17;) switch(*p++) { /* get prefixes */ - case 0x26: /* es: */ -// seg = 1; - break; - case 0x2e: /* cs: */ -// seg = 2; - break; - case 0x36: /* ss: */ -// seg = 3; - break; - case 0x3e: /* ds: */ -// seg = 4; - break; - case 0x64: /* fs: */ -// seg = 5; - break; - case 0x65: /* gs: */ -// seg = 6; - break; - case 0x66: /* operand size */ - osp ^= 1; break; - case 0x67: /* address size */ - asp ^= 1; break; - case 0xf0: /* lock */ -// lock = 1; - break; - case 0xf2: /* repnz */ -// rep = 2; - break; - case 0xf3: /* rep(z) */ -// rep = 1; - break; - default: /* no prefix */ - u = 0; - } - p--; - - if(p - p0 >= 16) return 0; - - if(*p == 0x0f) { - p++; - switch (*p) { - case 0xba: - p += 4; - return p - p0; - case 0xb2: // lss - case 0xb4: // lfs - case 0xb5: // lgs - p++; - p += (u = arg_len(p, asp)); - if(!u) p = p0; - return p - p0; - default: - /* not yet */ - error("unsupported instr_len %x %x\n", p[0], p[1]); - return 0; - } - } - - switch(it[*p]) { - case 1: /* op-code */ - p += 1; break; - - case 2: /* op-code + byte */ - p += 2; break; - - case 3: /* op-code + word/dword */ - p += osp ? 5 : 3; break; - - case 4: /* op-code + [word/dword] */ - p += asp ? 5 : 3; break; - - case 5: /* op-code + word/dword + byte */ - p += osp ? 6 : 4; break; - - case 6: /* op-code + [word/dword] + word */ - p += asp ? 7 : 5; break; - - case 7: /* op-code + mod + ... */ - p++; - p += (u = arg_len(p, asp)); - if(!u) p = p0; - break; - - case 8: /* op-code + mod + ... + byte */ - p++; - p += (u = arg_len(p, asp)) + 1; - if(!u) p = p0; - break; - - case 9: /* op-code + mod + ... + word/dword */ - p++; - p += (u = arg_len(p, asp)) + (osp ? 4 : 2); - if(!u) p = p0; - break; - - default: - p = p0; - } - - return p - p0; -} - -static unsigned char parity[256] = - { PF, 0, 0, PF, 0, PF, PF, 0, 0, PF, PF, 0, PF, 0, 0, PF, - 0, PF, PF, 0, PF, 0, 0, PF, PF, 0, 0, PF, 0, PF, PF, 0, - 0, PF, PF, 0, PF, 0, 0, PF, PF, 0, 0, PF, 0, PF, PF, 0, - PF, 0, 0, PF, 0, PF, PF, 0, 0, PF, PF, 0, PF, 0, 0, PF, - 0, PF, PF, 0, PF, 0, 0, PF, PF, 0, 0, PF, 0, PF, PF, 0, - PF, 0, 0, PF, 0, PF, PF, 0, 0, PF, PF, 0, PF, 0, 0, PF, - PF, 0, 0, PF, 0, PF, PF, 0, 0, PF, PF, 0, PF, 0, 0, PF, - 0, PF, PF, 0, PF, 0, 0, PF, PF, 0, 0, PF, 0, PF, PF, 0, - 0, PF, PF, 0, PF, 0, 0, PF, PF, 0, 0, PF, 0, PF, PF, 0, - PF, 0, 0, PF, 0, PF, PF, 0, 0, PF, PF, 0, PF, 0, 0, PF, - PF, 0, 0, PF, 0, PF, PF, 0, 0, PF, PF, 0, PF, 0, 0, PF, - 0, PF, PF, 0, PF, 0, 0, PF, PF, 0, 0, PF, 0, PF, PF, 0, - PF, 0, 0, PF, 0, PF, PF, 0, 0, PF, PF, 0, PF, 0, 0, PF, - 0, PF, PF, 0, PF, 0, 0, PF, PF, 0, 0, PF, 0, PF, PF, 0, - 0, PF, PF, 0, PF, 0, 0, PF, PF, 0, 0, PF, 0, PF, PF, 0, - PF, 0, 0, PF, 0, PF, PF, 0, 0, PF, PF, 0, PF, 0, 0, PF }; - - -// see http://www.emulators.com/docs/LazyOverflowDetect_Final.pdf -// same as used in codegen-sim.c: -// CF = cout bit 31, OF^CF = cout bit 30, AF = cout bit 3 -static void FlagSync(int res, unsigned cout, unsigned *eflags) -{ - unsigned nf; - - nf = parity[res & 0xff]; - nf |= (res == 0) << 6; // ZF - nf |= ((unsigned)res >> 24) & SF; - - nf |= (cout << 1) & AF; - nf |= (cout >> 31) & CF; - // 80000000->0800 ^ 40000000->0800 - nf |= ((cout >> 20) ^ (cout >> 19)) & OF; - - *eflags = (*eflags & ~(OF|ZF|SF|PF|AF|CF)) | nf; -} - -/* 6 logical and arithmetic "RISC" core functions - follow -*/ -static unsigned char instr_binary_byte(unsigned char op, unsigned char op1, unsigned char op2, unsigned *eflags) -{ - unsigned char res = 0; - unsigned cout = (*eflags & AF) ? 8 : 0; - - switch (op&0x7){ - case 1: /* or */ - res = op1 | op2; - break; - case 4: /* and */ - res = op1 & op2; - break; - case 6: /* xor */ - res = op1 ^ op2; - break; - case 0: /* add */ - *eflags &= ~CF; /* Fall through */ - case 2: /* adc */ - res = op1 + op2 + (*eflags & CF); - cout = (op1 & op2) | ((op1 | op2) & ~res); - break; - case 5: /* sub */ - case 7: /* cmp */ - *eflags &= ~CF; /* Fall through */ - case 3: /* sbb */ - res = op1 - op2 - (*eflags & CF); - cout = (~op1 & op2) | ((~op1 ^ op2) & res); - break; - } - cout = ((cout >> 6) << 30) | (cout & 8); - FlagSync((int32_t)(int8_t)res, cout, eflags); - return res; -} - -static unsigned instr_binary_word(unsigned op, unsigned op1, unsigned op2, unsigned *eflags) -{ - unsigned short opw1 = op1; - unsigned short opw2 = op2; - unsigned short res = 0; - unsigned cout = (*eflags & AF) ? 8 : 0; - - switch (op&0x7){ - case 1: /* or */ - res = opw1 | opw2; - break; - case 4: /* and */ - res = opw1 & opw2; - break; - case 6: /* xor */ - res = opw1 ^ opw2; - break; - case 0: /* add */ - *eflags &= ~CF; /* Fall through */ - case 2: /* adc */ - res = opw1 + opw2 + (*eflags & CF); - cout = (opw1 & opw2) | ((opw1 | opw2) & ~res); - break; - case 5: /* sub */ - case 7: /* cmp */ - *eflags &= ~CF; /* Fall through */ - case 3: /* sbb */ - res = opw1 - opw2 - (*eflags & CF); - cout = (~opw1 & opw2) | ((~opw1 ^ opw2) & res); - break; - } - cout = ((cout >> 14) << 30) | (cout & 8); - FlagSync((int32_t)(int16_t)res, cout, eflags); - return res; -} - -static unsigned instr_binary_dword(unsigned op, unsigned op1, unsigned op2, unsigned *eflags) -{ - unsigned res = 0; - unsigned cout = (*eflags & AF) ? 8 : 0; - - switch (op&0x7){ - case 1: /* or */ - res = op1 | op2; - break; - case 4: /* and */ - res = op1 & op2; - break; - case 6: /* xor */ - res = op1 ^ op2; - break; - case 0: /* add */ - *eflags &= ~CF; /* Fall through */ - case 2: /* adc */ - res = op1 + op2 + (*eflags & CF); - cout = (op1 & op2) | ((op1 | op2) & ~res); - break; - case 5: /* sub */ - case 7: /* cmp */ - *eflags &= ~CF; /* Fall through */ - case 3: /* sbb */ - res = op1 - op2 - (*eflags & CF); - cout = (~op1 & op2) | ((~op1 ^ op2) & res); - break; - } - FlagSync((int32_t)res, cout, eflags); - return res; -} - -static uint32_t x86_pop(cpuctx_t *scp, x86_ins *x86) +static uint32_t x86_pop(sigcontext_t *scp, x86_ins *x86) { unsigned ss_base = GetSegmentBase(_ss); unsigned char *mem = MEM_BASE32(ss_base + (_esp & wordmask[(x86->_32bit+1)*2])); if (x86->_32bit) _esp += x86->operand_size; else - _LWORD(esp) += x86->operand_size; + SP += x86->operand_size; return (x86->operand_size == 4 ? READ_DWORDP(mem) : READ_WORDP(mem)); } -static int x86_handle_prefixes(cpuctx_t *scp, unsigned cs_base, +static int x86_handle_prefixes(sigcontext_t *scp, unsigned cs_base, x86_ins *x86) { unsigned eip = _eip; @@ -438,54 +121,13 @@ static int x86_handle_prefixes(cpuctx_t *scp, unsigned cs_base, return prefix; } -static void make_retf_frame(cpuctx_t *scp, void *sp, - uint32_t cs, uint32_t eip, int is_32) -{ - if (is_32) { - unsigned int *ssp = sp; - *--ssp = cs; - *--ssp = eip; - _esp -= 8; - } else { - unsigned short *ssp = sp; - *--ssp = cs; - *--ssp = eip; - _LWORD(esp) -= 4; - } -} +#if DEBUG_INSTR >= 2 +#define instr_deb2(x...) v_printf("VGAEmu: " x) +#else +#define instr_deb2(x...) +#endif -#define PATCH_SIZE 8 -#define STACK_SIZE (PATCH_SIZE + 8) - -static void lxx_patch(cpuctx_t *scp, unsigned char *csp, int len, int is_32) -{ - unsigned char *sp; - unsigned int lp[LDT_ENTRY_SIZE / 4], esp, base; - unsigned char retf[] = { 0xca, PATCH_SIZE, 0 }; - - if (_LWORD(esp) < STACK_SIZE) { - error("asm patch failure\n"); - return; - } - assert(len + sizeof(retf) <= PATCH_SIZE); - _esp -= PATCH_SIZE; - sp = SEL_ADR(_ss, _esp); - esp = (dpmi_segment_is32(_ss) ? _esp : _LWORD(esp)); - make_retf_frame(scp, sp, _cs, _eip, is_32); - /* prepare the patch */ - memcpy(sp, csp, len); - sp[0] = 0x8b; // replace lXX with mov - memcpy(sp + len, retf, sizeof(retf)); - GetDescriptor(_cs, lp); - SetDescriptor(patch_cs, lp); - base = GetSegmentBase(_ss); - SetSegmentBaseAddress(patch_cs, base + esp); - SetSegmentLimit(patch_cs, PATCH_SIZE - 1); - _cs = patch_cs; - _eip = 0; -} - -int decode_segreg(cpuctx_t *scp) +int decode_segreg(sigcontext_t *scp) { unsigned cs, eip; unsigned char *csp, *orig_csp; @@ -501,7 +143,7 @@ int decode_segreg(cpuctx_t *scp) switch(*csp) { case 0x8e: /* mov segreg,r/m16 */ ret = sreg_idx(*(unsigned char *)MEM_BASE32(cs + eip + 1) >> 3); - _eip += _instr_len(orig_csp, x86._32bit); + _eip += instr_len(orig_csp, x86._32bit); break; case 0xca: /*retf imm 16*/ @@ -533,23 +175,15 @@ int decode_segreg(cpuctx_t *scp) } break; - case 0xc4: { /* les */ - int len = _instr_len(orig_csp, x86._32bit); - _eip += len; - assert(len > 0); - lxx_patch(scp, MEM_BASE32(cs + eip), len, x86._32bit); + case 0xc4: /* les */ ret = es_INDEX; + _eip += instr_len(orig_csp, x86._32bit); break; - } - case 0xc5: { /* lds */ - int len = _instr_len(orig_csp, x86._32bit); - _eip += len; - assert(len > 0); - lxx_patch(scp, MEM_BASE32(cs + eip), len, x86._32bit); + case 0xc5: /* lds */ ret = ds_INDEX; + _eip += instr_len(orig_csp, x86._32bit); break; - } case 0x07: /* pop es */ case 0x17: /* pop ss */ @@ -570,27 +204,19 @@ int decode_segreg(cpuctx_t *scp) break; case 0xb2: /* lss */ - error("LSS unsopported\n"); ret = ss_INDEX; + _eip += instr_len(orig_csp, x86._32bit); break; - case 0xb4: { /* lfs */ - int len = _instr_len(orig_csp, x86._32bit); - _eip += len; - assert(len > 1); - lxx_patch(scp, MEM_BASE32(cs + eip), len - 1, x86._32bit); + case 0xb4: /* lfs */ ret = fs_INDEX; + _eip += instr_len(orig_csp, x86._32bit); break; - } - case 0xb5: { /* lgs */ - int len = _instr_len(orig_csp, x86._32bit); - _eip += len; - assert(len > 1); - lxx_patch(scp, MEM_BASE32(cs + eip), len - 1, x86._32bit); + case 0xb5: /* lgs */ ret = gs_INDEX; + _eip += instr_len(orig_csp, x86._32bit); break; - } } break; } @@ -598,7 +224,7 @@ int decode_segreg(cpuctx_t *scp) return ret; } -uint16_t decode_selector(cpuctx_t *scp) +uint16_t decode_selector(sigcontext_t *scp) { unsigned cs; int pfx; @@ -621,7 +247,7 @@ uint16_t decode_selector(cpuctx_t *scp) return _ds; } -static uint8_t reg8(cpuctx_t *scp, int reg) +static uint8_t reg8(sigcontext_t *scp, int reg) { #define RG8(x, r) ((_e##x >> ((r & 4) << 1)) & 0xff) switch (reg & 3) { @@ -637,7 +263,7 @@ static uint8_t reg8(cpuctx_t *scp, int reg) return -1; } -static uint32_t reg(cpuctx_t *scp, int reg) +static uint32_t reg(sigcontext_t *scp, int reg) { switch (reg & 7) { case 0: @@ -660,7 +286,7 @@ static uint32_t reg(cpuctx_t *scp, int reg) return -1; } -int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2) +int decode_memop(sigcontext_t *scp, uint32_t *op, unsigned char *cr2) { unsigned cs, eip, seg_base; unsigned char *csp, *orig_csp; @@ -672,7 +298,7 @@ int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2) eip = _eip + x86_handle_prefixes(scp, cs, &x86); csp = (unsigned char *)MEM_BASE32(cs + eip); orig_csp = (unsigned char *)MEM_BASE32(cs + _eip); - inst_len = _instr_len(orig_csp, x86._32bit); + inst_len = instr_len(orig_csp, x86._32bit); loop_inc = (_eflags & DF) ? -1 : 1; if (x86.rep) { int cnt = 0; @@ -744,7 +370,7 @@ int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2) case 0x80: /* logical r/m8,imm8 */ case 0x82: - *op = instr_binary_byte(csp[1] >> 3, read_byte(cr2), + *op = instr_binary_byte(csp[1] >> 3, *cr2, orig_csp[inst_len - 1], (unsigned*)&_eflags); ret = 1; break; @@ -752,12 +378,12 @@ int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2) case 0x81: /* logical r/m,imm */ switch (x86.operand_size) { case 2: - *op = instr_binary_word(csp[1] >> 3, read_word(cr2), + *op = instr_binary_word(csp[1] >> 3, *(uint16_t *)cr2, *(uint16_t *)(orig_csp + inst_len - 2), (unsigned*)&_eflags); ret = 2; break; case 4: - *op = instr_binary_dword(csp[1] >> 3, read_dword(cr2), + *op = instr_binary_dword(csp[1] >> 3, *(uint32_t *)cr2, *(uint32_t *)(orig_csp + inst_len - 4), (unsigned*)&_eflags); ret = 4; break; @@ -767,12 +393,12 @@ int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2) case 0x83: /* logical r/m,imm8 */ switch (x86.operand_size) { case 2: - *op = instr_binary_word(csp[1] >> 3, read_word(cr2), + *op = instr_binary_word(csp[1] >> 3, *(uint16_t *)cr2, (short)*(signed char *)(orig_csp + inst_len - 1), (unsigned*)&_eflags); ret = 2; break; case 4: - *op = instr_binary_dword(csp[1] >> 3, read_dword(cr2), + *op = instr_binary_dword(csp[1] >> 3, *(uint32_t *)cr2, (int)*(signed char *)(orig_csp + inst_len - 1), (unsigned*)&_eflags); ret = 4; break; @@ -903,7 +529,7 @@ int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2) case 0x28: /* sub r/m8,reg8 */ case 0x30: /* xor r/m8,reg8 */ // case 0x38: /* cmp r/m8,reg8 */ - *op = instr_binary_byte(csp[0] >> 3, read_byte(cr2), + *op = instr_binary_byte(csp[0] >> 3, *cr2, reg8(scp, csp[1] >> 3), (unsigned*)&_eflags); ret = 1; break; @@ -918,12 +544,12 @@ int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2) // case 0x39: /* cmp r/m16,reg16 */ switch (x86.operand_size) { case 2: - *op = instr_binary_word(csp[0] >> 3, read_word(cr2), + *op = instr_binary_word(csp[0] >> 3, *(uint16_t *)cr2, reg(scp, csp[1] >> 3), (unsigned*)&_eflags); ret = 2; break; case 4: - *op = instr_binary_dword(csp[0] >> 3, read_dword(cr2), + *op = instr_binary_dword(csp[0] >> 3, *(uint32_t *)cr2, reg(scp, csp[1] >> 3), (unsigned*)&_eflags); ret = 4; break; @@ -931,7 +557,7 @@ int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2) break; case 0xfe: /* inc/dec mem */ - *op = read_byte(cr2); + *op = *cr2; switch (csp[1] & 0x38) { case 0: /* inc */ (*op)++; @@ -951,11 +577,11 @@ int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2) uint32_t mask = 1 << (csp[4] & 0x1f); switch (x86.operand_size) { case 2: - *op = read_word(cr2); + *op = *(uint16_t *)cr2; ret = 2; break; case 4: - *op = read_dword(cr2); + *op = *(uint32_t *)cr2; ret = 4; break; } @@ -988,13 +614,3 @@ int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2) _eip += inst_len; return ret; } - -void instrdec_init(void) -{ - patch_cs = AllocateDescriptors(1); -} - -void instrdec_done(void) -{ - FreeDescriptor(patch_cs); -} diff --git a/src/dosext/dpmi/msdos/instr_dec.h b/src/dosext/dpmi/msdos/instr_dec.h index b54d53a..6f929bf 100644 --- a/src/dosext/dpmi/msdos/instr_dec.h +++ b/src/dosext/dpmi/msdos/instr_dec.h @@ -1,11 +1,8 @@ #ifndef INSTR_DEC_H #define INSTR_DEC_H -int decode_segreg(cpuctx_t *scp); -uint16_t decode_selector(cpuctx_t *scp); -int decode_memop(cpuctx_t *scp, uint32_t *op, dosaddr_t cr2); - -void instrdec_init(void); -void instrdec_done(void); +int decode_segreg(sigcontext_t *scp); +uint16_t decode_selector(sigcontext_t *scp); +int decode_memop(sigcontext_t *scp, uint32_t *op, unsigned char *cr2); #endif diff --git a/src/dosext/dpmi/msdos/lio.c b/src/dosext/dpmi/msdos/lio.c index 90e1fbc..ac9fc91 100644 --- a/src/dosext/dpmi/msdos/lio.c +++ b/src/dosext/dpmi/msdos/lio.c @@ -38,7 +38,7 @@ static struct dos_helper_s helpers[LIOHLP_MAX]; struct liohlp_priv { unsigned short rm_seg; - void (*post)(cpuctx_t *); + void (*post)(sigcontext_t *); int is_32; }; static struct liohlp_priv lio_priv[LIOHLP_MAX]; @@ -54,14 +54,14 @@ static const struct hlp_hndl hlp_thr[LIOHLP_MAX] = { { lwhlp_thr, "msdos lw thr" }, }; -static unsigned short lio_rmseg(cpuctx_t *scp, int off, void *arg) +static unsigned short lio_rmseg(sigcontext_t *scp, int off, void *arg) { struct liohlp_priv *h = arg; return h->rm_seg; } static void liohlp_setup(int hlp, int is_32, - unsigned short rm_seg, void (*post)(cpuctx_t *)) + unsigned short rm_seg, void (*post)(sigcontext_t *)) { struct liohlp_priv *h = &lio_priv[hlp]; @@ -70,7 +70,7 @@ static void liohlp_setup(int hlp, int is_32, h->is_32 = is_32; } -static void do_callf(cpuctx_t *scp, int is_32, struct pmaddr_s pma) +static void do_callf(sigcontext_t *scp, int is_32, struct pmaddr_s pma) { void *sp = SEL_ADR_CLNT(_ss, _esp, is_32); if (is_32) { @@ -88,21 +88,21 @@ static void do_callf(cpuctx_t *scp, int is_32, struct pmaddr_s pma) _eip = pma.offset; } -void msdos_lr_helper(cpuctx_t *scp, int is_32, - unsigned short rm_seg, void (*post)(cpuctx_t *)) +void msdos_lr_helper(sigcontext_t *scp, int is_32, + unsigned short rm_seg, void (*post)(sigcontext_t *)) { liohlp_setup(DOSHLP_LR, is_32, rm_seg, post); - do_callf(scp, is_32, doshlp_get_entry(helpers[DOSHLP_LR].entry)); + do_callf(scp, is_32, doshlp_get_entry(&helpers[DOSHLP_LR])); } -void msdos_lw_helper(cpuctx_t *scp, int is_32, - unsigned short rm_seg, void (*post)(cpuctx_t *)) +void msdos_lw_helper(sigcontext_t *scp, int is_32, + unsigned short rm_seg, void (*post)(sigcontext_t *)) { liohlp_setup(DOSHLP_LW, is_32, rm_seg, post); - do_callf(scp, is_32, doshlp_get_entry(helpers[DOSHLP_LW].entry)); + do_callf(scp, is_32, doshlp_get_entry(&helpers[DOSHLP_LW])); } -static void do_int_call(cpuctx_t *scp, int is_32, int num, +static void do_int_call(sigcontext_t *scp, int is_32, int num, __dpmi_regs *rmreg) { RMREG(ss) = 0; @@ -112,8 +112,8 @@ static void do_int_call(cpuctx_t *scp, int is_32, int num, static void lrhlp_thr(void *arg) { - cpuctx_t *scp = arg; - cpuctx_t sa = *scp; + sigcontext_t *scp = arg; + sigcontext_t sa = *scp; struct liohlp_priv *hlp = &lio_priv[DOSHLP_LR]; __dpmi_regs _rmreg = {}; __dpmi_regs *rmreg = &_rmreg; @@ -170,14 +170,13 @@ static void lrhlp_thr(void *arg) _eflags &= ~CF; _eax = done; } - if (lio_priv[DOSHLP_LR].post) - lio_priv[DOSHLP_LR].post(scp); + lio_priv[DOSHLP_LR].post(scp); } static void lwhlp_thr(void *arg) { - cpuctx_t *scp = arg; - cpuctx_t sa = *scp; + sigcontext_t *scp = arg; + sigcontext_t sa = *scp; struct liohlp_priv *hlp = &lio_priv[DOSHLP_LW]; __dpmi_regs _rmreg = {}; __dpmi_regs *rmreg = &_rmreg; @@ -234,8 +233,7 @@ static void lwhlp_thr(void *arg) _eflags &= ~CF; _eax = done; } - if (lio_priv[DOSHLP_LW].post) - lio_priv[DOSHLP_LW].post(scp); + lio_priv[DOSHLP_LW].post(scp); } void lio_init(void) diff --git a/src/dosext/dpmi/msdos/lio.h b/src/dosext/dpmi/msdos/lio.h index 8f13973..7827cb3 100644 --- a/src/dosext/dpmi/msdos/lio.h +++ b/src/dosext/dpmi/msdos/lio.h @@ -1,10 +1,10 @@ #ifndef LIO_H #define LIO_H -void msdos_lr_helper(cpuctx_t *scp, int is_32, - unsigned short rm_seg, void (*post)(cpuctx_t *)); -void msdos_lw_helper(cpuctx_t *scp, int is_32, - unsigned short rm_seg, void (*post)(cpuctx_t *)); +void msdos_lr_helper(sigcontext_t *scp, int is_32, + unsigned short rm_seg, void (*post)(sigcontext_t *)); +void msdos_lw_helper(sigcontext_t *scp, int is_32, + unsigned short rm_seg, void (*post)(sigcontext_t *)); void lio_init(void); #endif diff --git a/src/dosext/dpmi/msdos/msdos.c b/src/dosext/dpmi/msdos/msdos.c index bbe4a7a..1f36f74 100644 --- a/src/dosext/dpmi/msdos/msdos.c +++ b/src/dosext/dpmi/msdos/msdos.c @@ -4,7 +4,7 @@ * for details see file COPYING in the DOSEMU distribution */ -/* MS-DOS API translator for DOSEMU's DPMI Server +/* MS-DOS API translator for DOSEMU\'s DPMI Server * * DANG_BEGIN_MODULE msdos.c * @@ -37,7 +37,6 @@ #include "lio.h" #include "msdoshlp.h" #include "msdos_ldt.h" -#include "instr_dec.h" #include "callbacks.h" #include "segreg_priv.h" #include "msdos_priv.h" @@ -62,15 +61,14 @@ static unsigned short EMM_SEG; #define DTA_Para_SIZE 8 #define Scratch_Para_ADD (DTA_Para_ADD + DTA_Para_SIZE) #define EXEC_Para_SIZE 30 -#define Scratch_Para_SIZE 32 // 512 bytes -#define Scratch_SIZE (Scratch_Para_SIZE << 4) +#define Scratch_Para_SIZE 30 #define API_32(scp) (MSDOS_CLIENT.is_32 || (MSDOS_CLIENT.ext__thunk_16_32 && \ msdos_ldt_is32(_cs_))) #define API_16_32(x) (API_32(scp) ? (x) : (x) & 0xffff) #define SEL_ADR_X(s, a, u) SEL_ADR_CLNT(s, a, API_32(scp)) #define D_16_32(reg) API_16_32(reg) -#define MSDOS_CLIENT (msdos_client[msdos_client_num]) +#define MSDOS_CLIENT (msdos_client[msdos_client_num - 1]) #define CURRENT_PSP MSDOS_CLIENT.current_psp static const int ints[] = { 0x10, 0x15, 0x20, 0x21, 0x25, 0x26, 0x28, @@ -104,35 +102,21 @@ struct msdos_struct { unsigned short lowmem_seg; dpmi_pm_block mem_map[MSDOS_MAX_MEM_ALLOCS]; far_t rmcbs[MAX_RMCBS]; + unsigned short rmcb_sel; int rmcb_alloced; u_short ldt_alias; u_short ldt_alias_winos2; struct seg_sel seg_sel_map[MAX_CNVS]; int ext__thunk_16_32; - - DPMI_INTDESC int_head; - int int_offs[num_ints]; - int used; }; static struct msdos_struct msdos_client[DPMI_MAX_CLIENTS]; -static int msdos_client_num; -static int msdos_client_max; +static int msdos_client_num = 0; static int ems_frame_mapped; static int ems_handle; #define MSDOS_EMS_PAGES 4 -static unsigned short rmcb_sel; -static dosaddr_t rmcb_mem; -static struct dos_helper_s reinit_hlp; - -static unsigned short get_xbuf_seg(cpuctx_t *scp, int off, void *arg); -static void rsp_init(void); -static unsigned short msdos_get_lowmem_size(void); -static void msdos_init(int num, int is_32, unsigned short mseg, - unsigned short psp, int inherit_idt); -static void msdos_done(int prev); -static void msdos_set_client(int num); +static unsigned short get_xbuf_seg(sigcontext_t *scp, int off, void *arg); static void *cbk_args(int idx) { @@ -167,51 +151,17 @@ static unsigned short trans_buffer_seg(void) int msdos_is_32(void) { return MSDOS_CLIENT.is_32; } -static void reinit_thr(void *arg); - -static void do_retf16(cpuctx_t *scp) -{ - void *sp = SEL_ADR_CLNT(_ss, _esp, 0); - unsigned short *ssp = sp; - _LWORD(eip) = *ssp++; - _cs = *ssp++; - _LWORD(esp) += 4; -} - -static void do_retf32(cpuctx_t *scp) -{ - void *sp = SEL_ADR_CLNT(_ss, _esp, 1); - unsigned *ssp = sp; - _eip = *ssp++; - _cs = *ssp++; - _esp += 8; -} - void msdos_setup(void) { msdoshlp_init(msdos_is_32, num_ints); lio_init(); xmshlp_init(); - /* bitness may change on reinit so we specify particular retf version */ - doshlp_setup(&reinit_hlp, "msdos reinit thr", reinit_thr, - MSDOS_CLIENT.is_32 ? do_retf32 : do_retf16); } void msdos_reset(void) { - while (msdos_client_max > 0) { - int prev; - assert(msdos_client[msdos_client_max - 1].used); - msdos_client_num = msdos_client_max - 1; - prev = msdos_client_num - 1; - while (prev >= 0 && !msdos_client[prev].used) - prev--; - msdos_done(prev); - } ems_handle = -1; ems_frame_mapped = 0; - - rsp_init(); } static char *msdos_seg2lin(uint16_t seg) @@ -228,38 +178,67 @@ static void *get_prev_fault(void) { return &MSDOS_CLIENT.prev_fault; } static void *get_prev_pfault(void) { return &MSDOS_CLIENT.prev_pagefault; } static void *get_prev_ext(int off) { return &MSDOS_CLIENT.prev_ihandler[off]; } -static void setup_int_exc(int inherit_idt) +void msdos_init(int is_32, unsigned short mseg, unsigned short psp) { + unsigned short envp; struct pmaddr_s pma; DPMI_INTDESC desc; int i; + int int_offs[num_ints]; - if (!inherit_idt) { - int int_offs[num_ints]; + msdos_client_num++; + memset(&MSDOS_CLIENT, 0, sizeof(struct msdos_struct)); + MSDOS_CLIENT.is_32 = is_32; + MSDOS_CLIENT.lowmem_seg = mseg; + MSDOS_CLIENT.current_psp = psp; + /* convert environment pointer to a descriptor */ + envp = get_env_sel(); + if (envp) { + write_env_sel(ConvertSegmentToDescriptor(envp)); + D_printf("DPMI: env segment %#x converted to descriptor %#x\n", + envp, get_env_sel()); + } + if (msdos_client_num == 1 || + msdos_client[msdos_client_num - 2].is_32 != is_32) { + int len = sizeof(struct RealModeCallStructure); + dosaddr_t rmcb_mem = msdos_malloc(len); + MSDOS_CLIENT.rmcb_sel = AllocateDescriptors(1); + SetSegmentBaseAddress(MSDOS_CLIENT.rmcb_sel, rmcb_mem); + SetSegmentLimit(MSDOS_CLIENT.rmcb_sel, len - 1); + callbacks_init(MSDOS_CLIENT.rmcb_sel, cbk_args, MSDOS_CLIENT.rmcbs); + MSDOS_CLIENT.rmcb_alloced = 1; + for (i = 0; i < num_ints; i++) + MSDOS_CLIENT.prev_ihandler[i] = dpmi_get_interrupt_vector(ints[i]); pma = get_pmrm_handler_m(MSDOS_EXT_CALL, msdos_ext_call, get_prev_ext, msdos_ext_ret, get_xbuf_seg, NULL, num_ints, int_offs); desc.selector = pma.selector; desc.offset32 = pma.offset; - MSDOS_CLIENT.int_head = desc; - memcpy(MSDOS_CLIENT.int_offs, int_offs, sizeof(int_offs)); - for (i = 0; i < num_ints; i++) { DPMI_INTDESC desc2 = desc; - MSDOS_CLIENT.prev_ihandler[i] = dpmi_get_interrupt_vector(ints[i]); desc2.offset32 += int_offs[i]; dpmi_set_interrupt_vector(ints[i], desc2); } } else { - memcpy(MSDOS_CLIENT.prev_ihandler, - msdos_client[msdos_client_num - 1].prev_ihandler, - sizeof(MSDOS_CLIENT.prev_ihandler)); - MSDOS_CLIENT.int_head = msdos_client[msdos_client_num - 1].int_head; - memcpy(MSDOS_CLIENT.int_offs, - msdos_client[msdos_client_num - 1].int_offs, - sizeof(MSDOS_CLIENT.int_offs)); + assert(msdos_client_num >= 2); + MSDOS_CLIENT.rmcb_sel = msdos_client[msdos_client_num - 2].rmcb_sel; + memcpy(MSDOS_CLIENT.rmcbs, msdos_client[msdos_client_num - 2].rmcbs, + sizeof(MSDOS_CLIENT.rmcbs)); + + for (i = 0; i < num_ints; i++) + MSDOS_CLIENT.prev_ihandler[i] = + msdos_client[msdos_client_num - 2].prev_ihandler[i]; } + if (msdos_client_num == 1) + MSDOS_CLIENT.ldt_alias = msdos_ldt_init(); + else + MSDOS_CLIENT.ldt_alias = msdos_client[msdos_client_num - 2].ldt_alias; + MSDOS_CLIENT.ldt_alias_winos2 = CreateAliasDescriptor( + MSDOS_CLIENT.ldt_alias); + SetDescriptorAccessRights(MSDOS_CLIENT.ldt_alias_winos2, 0xf0); + SetSegmentLimit(MSDOS_CLIENT.ldt_alias_winos2, + LDT_ENTRIES * LDT_ENTRY_SIZE - 1); MSDOS_CLIENT.prev_fault = dpmi_get_pm_exc_addr(0xd); pma = get_pm_handler(MSDOS_FAULT, msdos_fault_handler, get_prev_fault); @@ -273,49 +252,6 @@ static void setup_int_exc(int inherit_idt) desc.selector = pma.selector; desc.offset32 = pma.offset; dpmi_set_pm_exc_addr(0xe, desc); -} - -static void msdos_init(int num, int is_32, unsigned short mseg, - unsigned short psp, int inherit_idt) -{ - int first = (msdos_client_num < 0 || - msdos_client_num >= DPMI_MAX_CLIENTS || - !msdos_client[msdos_client_num].used); - msdos_client_num = num; - memset(&MSDOS_CLIENT, 0, sizeof(struct msdos_struct)); - MSDOS_CLIENT.used = 1; - if (msdos_client_max <= msdos_client_num) - msdos_client_max = msdos_client_num + 1; - MSDOS_CLIENT.is_32 = is_32; - MSDOS_CLIENT.lowmem_seg = mseg; - MSDOS_CLIENT.current_psp = psp; - if (first) { - int len = sizeof(struct RealModeCallStructure); - rmcb_mem = msdos_malloc(len); - rmcb_sel = AllocateDescriptors(1); - SetSegmentBaseAddress(rmcb_sel, rmcb_mem); - SetSegmentLimit(rmcb_sel, len - 1); - - MSDOS_CLIENT.ldt_alias = msdos_ldt_init(); - instrdec_init(); - } else { - MSDOS_CLIENT.ldt_alias = msdos_client[msdos_client_num - 1].ldt_alias; - } - if (first || msdos_client[msdos_client_num - 1].is_32 != is_32) { - callbacks_init(rmcb_sel, cbk_args, MSDOS_CLIENT.rmcbs); - MSDOS_CLIENT.rmcb_alloced = 1; - } else { - assert(msdos_client_num >= 1); - memcpy(MSDOS_CLIENT.rmcbs, msdos_client[msdos_client_num - 1].rmcbs, - sizeof(MSDOS_CLIENT.rmcbs)); - } - MSDOS_CLIENT.ldt_alias_winos2 = CreateAliasDescriptor( - MSDOS_CLIENT.ldt_alias); - SetDescriptorAccessRights(MSDOS_CLIENT.ldt_alias_winos2, 0xf0); - SetSegmentLimit(MSDOS_CLIENT.ldt_alias_winos2, - LDT_ENTRIES * LDT_ENTRY_SIZE - 1); - - setup_int_exc(inherit_idt); D_printf("MSDOS: init %i, ldt_alias=0x%x winos2_alias=0x%x\n", msdos_client_num, MSDOS_CLIENT.ldt_alias, @@ -347,100 +283,32 @@ static void msdos_free_descriptors(void) FreeDescriptor(MSDOS_CLIENT.ldt_alias_winos2); } -static void msdos_done(int prev) +void msdos_done(void) { int i; for (i = 0; i < num_ints; i++) dpmi_set_interrupt_vector(ints[i], MSDOS_CLIENT.prev_ihandler[i]); - if (MSDOS_CLIENT.rmcb_alloced) + if (MSDOS_CLIENT.rmcb_alloced) { callbacks_done(MSDOS_CLIENT.rmcbs); - if (prev < 0 || prev >= DPMI_MAX_CLIENTS || !msdos_client[prev].used) { - msdos_ldt_done(); - FreeDescriptor(rmcb_sel); - msdos_free(rmcb_mem); - instrdec_done(); + FreeDescriptor(MSDOS_CLIENT.rmcb_sel); } + if (get_env_sel()) + write_env_sel(GetSegmentBase(get_env_sel()) >> 4); + if (msdos_client_num == 1) + msdos_ldt_done(); msdos_free_descriptors(); msdos_free_mem(); - MSDOS_CLIENT.used = 0; - while (msdos_client_max > 0 && !msdos_client[msdos_client_max - 1].used) - msdos_client_max--; - D_printf("MSDOS: done, %i --> %i\n", msdos_client_num, prev); - msdos_client_num = prev; + msdos_client_num--; + D_printf("MSDOS: done, %i\n", msdos_client_num); } -static void msdos_set_client(int num) +void msdos_set_client(int num) { - msdos_client_num = num; + msdos_client_num = num + 1; } -static void do_common_start(cpuctx_t *scp, int is_32) -{ - switch (_LWORD(eax)) { - case 0: - msdos_init(_LWORD(ebx), is_32, _LWORD(edx), _LWORD(esi), _LWORD(ecx)); - break; - case 1: - msdos_done(_LWORD(ecx)); - break; - case 2: - msdos_set_client(_LWORD(ebx)); - break; - default: - error("unsupported rsp %i\n", _LWORD(eax)); - break; - } -} - -static void do_start16(cpuctx_t *scp, void *arg) -{ - do_common_start(scp, 0); -} - -static void do_start32(cpuctx_t *scp, void *arg) -{ - do_common_start(scp, 1); -} - -static void rsp_init(void) -{ - struct pmaddr_s rsp16, rsp32; - struct RSPcall_s rsp = {}; - int err; - - rsp16 = get_pm_handler(MSDOS_RSP_CALL16, do_start16, NULL); - rsp32 = get_pm_handler(MSDOS_RSP_CALL32, do_start32, NULL); - err = GetDescriptor(rsp16.selector, (unsigned *)rsp.code16); - assert(!err); - rsp.ip = rsp16.offset; - err = GetDescriptor(rsp32.selector, (unsigned *)rsp.code32); - assert(!err); - rsp.eip = rsp32.offset; - /* FIXME: maybe fill data descs too? */ - rsp.flags = RSP_F_SW | RSP_F_LOWMEM; - rsp.para = msdos_get_lowmem_size(); - err = dpmi_install_rsp(&rsp); - assert(!err); -} - -static void reinit_thr(void *arg) -{ - cpuctx_t *scp = arg; - int is_32 = (_LWORD(eax) & 1); - - _eflags |= CF; - if (MSDOS_CLIENT.is_32 == is_32) - _eflags &= ~CF; - else if (MSDOS_CLIENT.is_32) - return; - doshlp_call_reinit(scp); - MSDOS_CLIENT.is_32 = is_32; - setup_int_exc(0); - _eflags &= ~CF; -} - -static unsigned short msdos_get_lowmem_size(void) +int msdos_get_lowmem_size(void) { return DTA_Para_SIZE + Scratch_Para_SIZE; } @@ -528,7 +396,7 @@ static unsigned int msdos_realloc(unsigned int addr, unsigned int new_size) return block.base; } -static int prepare_ems_frame(cpuctx_t *scp) +static int prepare_ems_frame(sigcontext_t *scp) { static const u_short ems_map_simple[MSDOS_EMS_PAGES * 2] = { 0, 0, 1, 1, 2, 2, 3, 3 }; @@ -543,10 +411,6 @@ static int prepare_ems_frame(cpuctx_t *scp) int phys_total, uma_total; int i; phys_total = emm_get_mpa_len(scp, MSDOS_CLIENT.is_32); - if (phys_total == -1) { - error("MSDOS: EMS is disabled\n"); - return -1; - } if (phys_total < 4 || phys_total > EMM_MAX_PHYS) { error("MSDOS: EMS has %i phys pages\n", phys_total); return -1; @@ -584,7 +448,7 @@ static int prepare_ems_frame(cpuctx_t *scp) return 0; } -static void restore_ems_frame(cpuctx_t *scp) +static void restore_ems_frame(sigcontext_t *scp) { if (!ems_frame_mapped) { dosemu_error("unmapping not mapped EMS frame\n"); @@ -596,10 +460,10 @@ static void restore_ems_frame(cpuctx_t *scp) D_printf("MSDOS: EMS frame unmapped\n"); } -static u_short *get_ldt_alias(void) { return &MSDOS_CLIENT.ldt_alias; } -static u_short *get_winos2_alias(void) { return &MSDOS_CLIENT.ldt_alias_winos2; } +static void *get_ldt_alias(void) { return &MSDOS_CLIENT.ldt_alias; } +static void *get_winos2_alias(void) { return &MSDOS_CLIENT.ldt_alias_winos2; } -static void get_ext_API(cpuctx_t *scp) +static void get_ext_API(sigcontext_t *scp) { struct pmaddr_s pma; char *ptr = SEL_ADR_CLNT(_ds, _esi, MSDOS_CLIENT.is_32); @@ -627,7 +491,7 @@ static void get_ext_API(cpuctx_t *scp) } } -static int need_copy_dseg(int intr, u_short ax, u_long cx) +static int need_copy_dseg(int intr, u_short ax, u_short cx) { switch (intr) { case 0x21: @@ -650,7 +514,7 @@ static int need_copy_dseg(int intr, u_short ax, u_long cx) break; case 0x25: /* Absolute Disk Read */ case 0x26: /* Absolute Disk write */ - return ((cx & 0xffff) != 0xffff); + return (cx != 0xffff); } return 0; @@ -712,7 +576,7 @@ static int need_copy_eseg(int intr, u_short ax) return 0; } -static int need_xbuf(int intr, u_short ax, u_long cx) +static int need_xbuf(int intr, u_short ax, u_short cx) { if (need_copy_dseg(intr, ax, cx) || need_copy_eseg(intr, ax)) return 1; @@ -739,12 +603,11 @@ static int need_xbuf(int intr, u_short ax, u_long cx) case 0x4e: /* find first */ case 0x5b: /* Create */ case 0x38: /* get country info */ + case 0x3f: /* dos read */ + case 0x40: /* DOS Write */ case 0x53: /* Generate Drive Parameter Table */ case 0x56: /* rename file */ return 1; - case 0x3f: /* dos read */ - case 0x40: /* dos write */ - return (cx > Scratch_SIZE); case 0x5d: /* share & misc */ return (LO_BYTE(ax) <= 0x05 || LO_BYTE(ax) == 0x0a); case 0x5f: /* redirection */ @@ -775,7 +638,7 @@ static int need_xbuf(int intr, u_short ax, u_long cx) case 0x4F: /* find next file */ case 0x47: /* get cur dir */ case 0x60: /* canonicalize filename */ - case 0x6c: /* extended open/creat */ + case 0x6c: /* extended open/create */ case 0xA0: /* get volume info */ return 1; } @@ -796,14 +659,6 @@ static int need_xbuf(int intr, u_short ax, u_long cx) case 0x26: /* Absolute Disk write */ return 1; - case 0x2f: - switch (ax) { - case 0x168a: /* DPMI extensions. Buffer required - * for a check. */ - return 1; - } - break; - case 0x33: switch (ax) { case 0x09: /* Set Mouse Graphics Cursor */ @@ -823,24 +678,18 @@ static int need_xbuf(int intr, u_short ax, u_long cx) return 0; } -static unsigned short get_xbuf_seg(cpuctx_t *scp, int off, void *arg) +static unsigned short get_xbuf_seg(sigcontext_t *scp, int off, void *arg) { int intr = ints[off]; - if (need_xbuf(intr, _LWORD(eax), D_16_32(_ecx))) { + if (need_xbuf(intr, _LWORD(eax), _LWORD(ecx))) { int err = prepare_ems_frame(scp); - if (err) { - if (intr == 0x2f && _LWORD(eax) == 0x168a) - return 0; + if (err) return (unsigned short)-1; - } return trans_buffer_seg(); } switch (intr) { case 0x21: switch (_HI(ax)) { - case 0x3f: /* small dos read */ - case 0x40: /* small dos write */ - return SCRATCH_SEG; case 0x4b: /* exec */ return EXEC_SEG; case 0x71: @@ -892,7 +741,7 @@ static int in_dos_space(unsigned short sel, unsigned long off) #define SET_RMREG(rg, val) (RMPRESERVE1(rg), RMREG(rg) = (val)) #define SET_RMLWORD(rg, val) (E_RMPRESERVE1(rg), X_RMREG(e##rg) = (val)) -static void old_dos_terminate(cpuctx_t *scp, int i, +static void old_dos_terminate(sigcontext_t *scp, int i, struct RealModeCallStructure *rmreg, int *rmask) { unsigned short psp_seg_sel, parent_psp = 0; @@ -954,7 +803,7 @@ static void old_dos_terminate(cpuctx_t *scp, int i, *rmask = rm_mask; } -static int do_abs_rw(cpuctx_t *scp, struct RealModeCallStructure *rmreg, +static int do_abs_rw(sigcontext_t *scp, struct RealModeCallStructure *rmreg, unsigned short rm_seg, int *r_mask, uint8_t *src, int is_w) { int rm_mask = *r_mask; @@ -996,7 +845,7 @@ static int do_abs_rw(cpuctx_t *scp, struct RealModeCallStructure *rmreg, * * DANG_END_FUNCTION */ -int msdos_pre_extender(cpuctx_t *scp, +int msdos_pre_extender(sigcontext_t *scp, struct RealModeCallStructure *rmreg, int intr, unsigned short rm_seg, int *r_mask, far_t *r_rma) @@ -1198,7 +1047,7 @@ int msdos_pre_extender(cpuctx_t *scp, case 0x21 ... 0x24: case 0x27: case 0x28: - error("MSDOS: Unsupported function 0x%x\n", _HI(ax)); + error("MS-DOS: Unsupported function 0x%x\n", _HI(ax)); _HI(ax) = 0xff; return MSDOS_DONE; case 0x11: @@ -1257,7 +1106,7 @@ int msdos_pre_extender(cpuctx_t *scp, par_seg = segment; segment += 2; #if 0 - /* now the environment segment */ + /* now the envrionment segment */ sel = READ_WORD(SEGOFF2LINEAR(par_seg, 0)); WRITE_WORD(SEGOFF2LINEAR(par_seg, 0), segment); MEMCPY_2DOS(SEGOFF2LINEAR(segment, 0), /* 4K envr. */ @@ -1285,7 +1134,7 @@ int msdos_pre_extender(cpuctx_t *scp, MEMSET_DOS(SEGOFF2LINEAR(segment, 0), 0, 0x30); segment += 3; - /* then the environment seg */ + /* then the enviroment seg */ if (get_env_sel()) write_env_sel(GetSegmentBase(get_env_sel()) >> 4); @@ -1382,11 +1231,11 @@ int msdos_pre_extender(cpuctx_t *scp, break; case 0x3f: /* dos read */ msdos_lr_helper(scp, MSDOS_CLIENT.is_32, - rm_seg, ems_frame_mapped ? restore_ems_frame : NULL); + rm_seg, restore_ems_frame); return MSDOS_DONE; case 0x40: /* dos write */ msdos_lw_helper(scp, MSDOS_CLIENT.is_32, - rm_seg, ems_frame_mapped ? restore_ems_frame : NULL); + rm_seg, restore_ems_frame); return MSDOS_DONE; case 0x53: /* Generate Drive Parameter Table */ { @@ -1560,7 +1409,7 @@ int msdos_pre_extender(cpuctx_t *scp, dst = msdos_seg2lin(rm_seg); snprintf(dst, MAX_DOS_PATH, "%s", src); break; - case 0x6c: /* extended open/creat */ + case 0x6c: /* extended open/create */ SET_RMREG(ds, rm_seg); SET_RMLWORD(si, 0); src = SEL_ADR_X(_ds, _esi, MSDOS_CLIENT.is_32); @@ -1656,34 +1505,11 @@ int msdos_pre_extender(cpuctx_t *scp, if (doshlp_idle()) _LO(ax) = 0; return MSDOS_DONE; - case 0x1687: { - struct pmaddr_s pma; - _LWORD(eax) = 0; - /* 32bit DPMI supported (0x1), - * entering from 16bit-PM supported (0x100), - * entering from 32bit-PM supported (0x200) */ - _LWORD(ebx) = 1 | 0x300; - _LWORD(ecx) = 4; - _HI(dx) = DPMI_VERSION; - _LO(dx) = DPMI_MINOR_VERSION; - _LWORD(esi) = 0; - pma = doshlp_get_entry(reinit_hlp.entry); - _es = pma.selector; - _LWORD(edi) = pma.offset; - return MSDOS_DONE; - } case 0x1688: _eax = 0; _ebx = MSDOS_CLIENT.ldt_alias; return MSDOS_DONE; case 0x168a: - /* we don't need EMS here so unmap */ - if (ems_frame_mapped) - restore_ems_frame(scp); - if (!rm_seg) { - _eflags |= CF; - return MSDOS_DONE; - } get_ext_API(scp); if (_eflags & CF) return MSDOS_PM; @@ -1815,7 +1641,7 @@ int msdos_pre_extender(cpuctx_t *scp, RMLWORD(reg)]) far_t get_xms_call(void) { return MSDOS_CLIENT.XMS_call; } -unsigned short scratch_seg(cpuctx_t *scp, int off, void *arg) +unsigned short scratch_seg(sigcontext_t *scp, int off, void *arg) { return SCRATCH_SEG; } @@ -1831,7 +1657,7 @@ unsigned short scratch_seg(cpuctx_t *scp, int off, void *arg) * DANG_END_FUNCTION */ -int msdos_post_extender(cpuctx_t *scp, +int msdos_post_extender(sigcontext_t *scp, const struct RealModeCallStructure *rmreg, int intr, unsigned short rm_seg, int *rmask, unsigned *arg) @@ -1885,7 +1711,7 @@ int msdos_post_extender(cpuctx_t *scp, switch (intr) { case 0x10: /* video */ if (ax == 0x1130) { - /* get current character generator info */ + /* get current character generator infor */ TRANSLATE_S(es); } break; @@ -2149,7 +1975,7 @@ int msdos_post_extender(cpuctx_t *scp, break; case 0x4E: PRESERVE1(edx); - /* fall through */ + /* fall thru */ case 0x4F: PRESERVE1(edi); if (RMREG(flags) & CF) @@ -2252,9 +2078,7 @@ int msdos_post_extender(cpuctx_t *scp, case 0x33: /* mouse */ switch (ax) { case 0x09: /* Set Mouse Graphics Cursor */ - case 0x0c: /* set call back */ - case 0x14: /* swap call back, results already set - * in pre_extender() so here only preserve */ + case 0x14: /* swap call back */ PRESERVE1(edx); break; case 0x19: /* Get User Alternate Interrupt Address */ @@ -2286,8 +2110,6 @@ const char *msdos_describe_selector(unsigned short sel) int i; struct seg_sel *m = NULL; - if (msdos_client_num == -1) - return NULL; if (sel == 0) return "NULL selector"; if (sel == MSDOS_CLIENT.ldt_alias) diff --git a/src/dosext/dpmi/msdos/msdos.h b/src/dosext/dpmi/msdos/msdos.h index d2167ba..a9c6fa1 100644 --- a/src/dosext/dpmi/msdos/msdos.h +++ b/src/dosext/dpmi/msdos/msdos.h @@ -1,4 +1,4 @@ -/* MS-DOS API translator for DOSEMU's DPMI Server +/* MS-DOS API translator for DOSEMU\'s DPMI Server * * DANG_BEGIN_MODULE msdos.h * @@ -18,5 +18,9 @@ void msdos_setup(void); void msdos_reset(void); +void msdos_init(int is_32, unsigned short mseg, unsigned short psp); +void msdos_done(void); +void msdos_set_client(int num); +int msdos_get_lowmem_size(void); #endif diff --git a/src/dosext/dpmi/msdos/msdos_ldt.c b/src/dosext/dpmi/msdos/msdos_ldt.c index dbd5095..be2e0a7 100644 --- a/src/dosext/dpmi/msdos/msdos_ldt.c +++ b/src/dosext/dpmi/msdos/msdos_ldt.c @@ -23,7 +23,6 @@ #include #include #include "cpu.h" -#include "utilities.h" #include "memory.h" #include "emudpmi.h" #include "instr_dec.h" @@ -36,8 +35,7 @@ #define LDT_UPDATE_LIM 1 static unsigned char *ldt_backbuf; -static dosaddr_t ldt_bb; -static dosaddr_t ldt_alias; +static unsigned char *ldt_alias; static uint32_t ldt_h; static uint32_t ldt_alias_h; static unsigned short dpmi_ldt_alias; @@ -54,14 +52,13 @@ static unsigned short d16, d32; static void msdos_ldt_update(int selector, int num); -static void msdos_ldt_handler(cpuctx_t *scp, void *arg) +static void msdos_ldt_handler(sigcontext_t *scp, void *arg) { msdos_ldt_update(_LWORD(ebx), _LWORD(ecx)); } unsigned short msdos_ldt_init(void) { - char tmpnm[] = "ldt_alias_%PXXXXXX"; unsigned lim; struct pmaddr_s pma; DPMI_INTDESC desc; @@ -77,34 +74,28 @@ unsigned short msdos_ldt_init(void) name_sel = AllocateDescriptors(1); name = msdos_malloc(name_len); - tempname(tmpnm, 6); - strcpy((char *)MEM_BASE32(name), tmpnm); + strcpy((char *)MEM_BASE32(name), "ldt_alias"); SetSegmentBaseAddress(name_sel, name); SetSegmentLimit(name_sel, name_len - 1); shm.name_selector = name_sel; shm.name_offset32 = 0; shm.req_len = PAGE_ALIGN(LDT_ENTRIES*LDT_ENTRY_SIZE); - shm.flags = SHM_NOEXEC | SHM_EXCL; + shm.flags = SHM_NOEXEC; err = DPMIAllocateShared(&shm); assert(!err); ldt_h = shm.handle; - ldt_bb = shm.addr; - ldt_backbuf = MEM_BASE32(ldt_bb); - - shm.flags = SHM_NOEXEC; + ldt_backbuf = MEM_BASE32(shm.addr); err = DPMIAllocateShared(&shm); assert(!err); ldt_alias_h = shm.handle; if (ldt_h == ldt_alias_h) error("DPMI: problems allocating shm\n"); - ldt_alias = shm.addr; + ldt_alias = MEM_BASE32(shm.addr); msdos_free(name); FreeDescriptor(name_sel); for (i = 0; i < npages; i++) attrs[i] = 0x83; // NX, RO - DPMISetPageAttributes(ldt_alias_h, 0, attrs, npages); - DPMIfree(ldt_alias_h); - DPMIfree(ldt_h); + DPMISetPageAttributes(shm.handle, 0, attrs, npages); alias_sel = AllocateDescriptors(1); assert(alias_sel); @@ -150,11 +141,11 @@ void msdos_ldt_done(void) FreeDescriptor(d16); FreeDescriptor(d32); ldt_backbuf = NULL; - DPMIUnmapHWRam(ldt_alias); - DPMIUnmapHWRam(ldt_bb); + DPMIFreeShared(ldt_alias_h); + DPMIFreeShared(ldt_h); } -int msdos_ldt_fault(cpuctx_t *scp, uint16_t sel) +int msdos_ldt_fault(sigcontext_t *scp, uint16_t sel) { unsigned limit; #if LDT_UPDATE_LIM @@ -208,7 +199,7 @@ static void msdos_ldt_update(int selector, int num) } } -static void direct_ldt_write(cpuctx_t *scp, int offset, +static void direct_ldt_write(sigcontext_t *scp, int offset, char *buffer, int length) { int ldt_entry = offset / LDT_ENTRY_SIZE; @@ -268,15 +259,13 @@ out: dpmi_ext_ldt_monitor_enable(1); } -int msdos_ldt_access(dosaddr_t cr2) +int msdos_ldt_access(unsigned char *cr2) { - if (!ldt_alias) - return 0; return cr2 >= ldt_alias && cr2 < ldt_alias + LDT_ENTRIES * LDT_ENTRY_SIZE; } -void msdos_ldt_write(cpuctx_t *scp, uint32_t op, int len, - dosaddr_t cr2) +void msdos_ldt_write(sigcontext_t *scp, uint32_t op, int len, + unsigned char *cr2) { if (!len) { /* 0-len shouldn't fault, so can't be here */ @@ -286,11 +275,11 @@ void msdos_ldt_write(cpuctx_t *scp, uint32_t op, int len, direct_ldt_write(scp, cr2 - ldt_alias, (char *)&op, len); } -int msdos_ldt_pagefault(cpuctx_t *scp) +int msdos_ldt_pagefault(sigcontext_t *scp) { uint32_t op; int len; - dosaddr_t cr2 = _cr2; + unsigned char *cr2 = MEM_BASE32(_cr2); if (!msdos_ldt_access(cr2)) return 0; diff --git a/src/dosext/dpmi/msdos/msdos_ldt.h b/src/dosext/dpmi/msdos/msdos_ldt.h index a84ab80..e3c301e 100644 --- a/src/dosext/dpmi/msdos/msdos_ldt.h +++ b/src/dosext/dpmi/msdos/msdos_ldt.h @@ -3,11 +3,11 @@ unsigned short msdos_ldt_init(void); void msdos_ldt_done(void); -int msdos_ldt_fault(cpuctx_t *scp, uint16_t sel); -int msdos_ldt_access(dosaddr_t cr2); -void msdos_ldt_write(cpuctx_t *scp, uint32_t op, int len, - dosaddr_t cr2); -int msdos_ldt_pagefault(cpuctx_t *scp); +int msdos_ldt_fault(sigcontext_t *scp, uint16_t sel); +int msdos_ldt_access(unsigned char *cr2); +void msdos_ldt_write(sigcontext_t *scp, uint32_t op, int len, + unsigned char *cr2); +int msdos_ldt_pagefault(sigcontext_t *scp); int msdos_ldt_is32(unsigned short selector); #endif diff --git a/src/dosext/dpmi/msdos/msdos_priv.h b/src/dosext/dpmi/msdos/msdos_priv.h index b3b1d93..844a352 100644 --- a/src/dosext/dpmi/msdos/msdos_priv.h +++ b/src/dosext/dpmi/msdos/msdos_priv.h @@ -9,18 +9,18 @@ unsigned short ConvertSegmentToDescriptor_lim(unsigned short segment, dosaddr_t msdos_malloc(unsigned long size); int msdos_free(unsigned int addr); -int msdos_pre_extender(cpuctx_t *scp, +int msdos_pre_extender(sigcontext_t *scp, struct RealModeCallStructure *rmreg, int intr, unsigned short rm_seg, int *r_mask, far_t *r_rma); -int msdos_post_extender(cpuctx_t *scp, +int msdos_post_extender(sigcontext_t *scp, const struct RealModeCallStructure *rmreg, int intr, unsigned short rm_seg, int *rmask, unsigned *arg); int msdos_get_int_num(int off); unsigned short get_scratch_seg(void); -unsigned short scratch_seg(cpuctx_t *scp, int off, void *arg); +unsigned short scratch_seg(sigcontext_t *scp, int off, void *arg); far_t get_xms_call(void); int msdos_is_32(void); diff --git a/src/dosext/dpmi/msdos/segreg.c b/src/dosext/dpmi/msdos/segreg.c index e697b59..4017106 100644 --- a/src/dosext/dpmi/msdos/segreg.c +++ b/src/dosext/dpmi/msdos/segreg.c @@ -38,9 +38,9 @@ #include "msdos_priv.h" #include "segreg_priv.h" -static enum MfRet msdos_sel_fault(cpuctx_t *scp) +static enum MfRet msdos_sel_fault(sigcontext_t *scp) { - cpuctx_t new_sct; + sigcontext_t new_sct; int reg; unsigned int segment; unsigned short desc; @@ -83,7 +83,7 @@ static enum MfRet msdos_sel_fault(cpuctx_t *scp) if (ValidAndUsedSelector(segment)) { /* * The selector itself is OK, but the descriptor (type) is not. - * We cannot fix this! So just give up immediately and don't + * We cannot fix this! So just give up immediately and dont * screw up the context. */ D_printf("MSDOS: msdos_fault: Illegal use of selector %#x\n", @@ -134,7 +134,7 @@ static enum MfRet msdos_sel_fault(cpuctx_t *scp) return MFR_HANDLED; } -static int msdos_fault(cpuctx_t *scp) +static int msdos_fault(sigcontext_t *scp) { enum MfRet ret; uint16_t sel; @@ -160,7 +160,7 @@ static int msdos_fault(cpuctx_t *scp) return 0; } -static void decode_exc(cpuctx_t *scp, const unsigned int *ssp) +static void decode_exc(sigcontext_t *scp, const unsigned int *ssp) { ssp += 8+2; // skip legacy frame and cs:eip _err = *ssp++; @@ -176,7 +176,7 @@ static void decode_exc(cpuctx_t *scp, const unsigned int *ssp) _cr2 = *ssp++; } -static void encode_exc(cpuctx_t *scp, unsigned int *ssp) +static void encode_exc(sigcontext_t *scp, unsigned int *ssp) { ssp += 8+2; // skip legacy frame and cs:eip ssp++; // err @@ -191,7 +191,7 @@ static void encode_exc(cpuctx_t *scp, unsigned int *ssp) *ssp++ = _gs; } -static void copy_gp(cpuctx_t *scp, cpuctx_t *src) +static void copy_gp(sigcontext_t *scp, sigcontext_t *src) { #define CP_R(r) _##r = get_##r(src) CP_R(eax); @@ -203,11 +203,11 @@ static void copy_gp(cpuctx_t *scp, cpuctx_t *src) CP_R(ebp); } -static void do_fault(cpuctx_t *scp, const DPMI_INTDESC *pma, - int (*cbk)(cpuctx_t *)) +static void do_fault(sigcontext_t *scp, const DPMI_INTDESC *pma, + int (*cbk)(sigcontext_t *)) { unsigned int *ssp; - cpuctx_t new_sct; + sigcontext_t new_sct; new_sct = *scp; ssp = SEL_ADR(_ss,_esp); @@ -232,13 +232,13 @@ static void do_fault(cpuctx_t *scp, const DPMI_INTDESC *pma, _esp += 0x20; // skip legacy frame } -void msdos_fault_handler(cpuctx_t *scp, void *arg) +void msdos_fault_handler(sigcontext_t *scp, void *arg) { void *(*cb)(void) = arg; do_fault(scp, cb(), msdos_fault); } -void msdos_pagefault_handler(cpuctx_t *scp, void *arg) +void msdos_pagefault_handler(sigcontext_t *scp, void *arg) { void *(*cb)(void) = arg; do_fault(scp, cb(), msdos_ldt_pagefault); diff --git a/src/dosext/dpmi/msdos/segreg_priv.h b/src/dosext/dpmi/msdos/segreg_priv.h index ecf27b3..3d7aebc 100644 --- a/src/dosext/dpmi/msdos/segreg_priv.h +++ b/src/dosext/dpmi/msdos/segreg_priv.h @@ -3,7 +3,7 @@ enum MfRet { MFR_HANDLED, MFR_NOT_HANDLED, MFR_ERROR }; -void msdos_fault_handler(cpuctx_t *scp, void *arg); -void msdos_pagefault_handler(cpuctx_t *scp, void *arg); +void msdos_fault_handler(sigcontext_t *scp, void *arg); +void msdos_pagefault_handler(sigcontext_t *scp, void *arg); #endif diff --git a/src/dosext/dpmi/msdos/xms.c b/src/dosext/dpmi/msdos/xms.c index 250de44..61fd3be 100644 --- a/src/dosext/dpmi/msdos/xms.c +++ b/src/dosext/dpmi/msdos/xms.c @@ -29,7 +29,7 @@ static struct dos_helper_s helper; -static void msdos_pre_xms(const cpuctx_t *scp, +static void msdos_pre_xms(const sigcontext_t *scp, __dpmi_regs *rmreg, unsigned short rm_seg, int *r_mask) { int rm_mask = *r_mask; @@ -52,7 +52,7 @@ static void msdos_pre_xms(const cpuctx_t *scp, *r_mask = rm_mask; } -static void msdos_post_xms(cpuctx_t *scp, +static void msdos_post_xms(sigcontext_t *scp, const __dpmi_regs *rmreg, int *r_mask) { int rm_mask = *r_mask; @@ -73,16 +73,20 @@ static void msdos_post_xms(cpuctx_t *scp, *r_mask = rm_mask; } -static void xms_call(const cpuctx_t *scp, +static far_t xms_call(const sigcontext_t *scp, __dpmi_regs *rmreg, unsigned short rm_seg) { + far_t XMS_call = get_xms_call(); int rmask = (1 << cs_INDEX) | (1 << eip_INDEX) | (1 << ss_INDEX) | (1 << esp_INDEX); + D_printf("MSDOS: XMS call to 0x%x:0x%x\n", + XMS_call.segment, XMS_call.offset); msdos_pre_xms(scp, rmreg, rm_seg, &rmask); pm_to_rm_regs(scp, rmreg, ~rmask); + return XMS_call; } -static void xms_ret(cpuctx_t *scp, const __dpmi_regs *rmreg) +static void xms_ret(sigcontext_t *scp, const __dpmi_regs *rmreg) { int rmask = 0; msdos_post_xms(scp, rmreg, &rmask); @@ -90,121 +94,34 @@ static void xms_ret(cpuctx_t *scp, const __dpmi_regs *rmreg) D_printf("MSDOS: XMS call return\n"); } -struct __attribute__ ((__packed__)) EMM { - unsigned int Length; - unsigned short SourceHandle; - unsigned int SourceOffset; - unsigned short DestHandle; - unsigned int DestOffset; -}; - -static void do_xms_call(cpuctx_t *scp) +static void do_call_to(sigcontext_t *scp, int is_32, far_t dst, + __dpmi_regs *rmreg) { - cpuctx_t sa = *scp; - __dpmi_regs rmreg = {}; - int is_32 = msdos_is_32(); - unsigned short rm_seg = helper.rm_seg(scp, 0, helper.rm_arg); - xms_call(scp, &rmreg, rm_seg); - do_call_to(scp, is_32, get_xms_call(), &rmreg); - *scp = sa; - xms_ret(scp, &rmreg); -} - -static dosaddr_t xms_map(cpuctx_t *scp, unsigned handle, unsigned len) -{ - cpuctx_t sa = *scp; - dosaddr_t ret = -1; - unsigned pa, sz; - - _LWORD(eax) = 0x0e00; // get emb info - _LWORD(edx) = handle; - do_xms_call(scp); - if (_LWORD(eax) != 1) - goto out; - sz = _LWORD(edx) * 1024; - if (len > sz) - goto out; - _LWORD(eax) = 0x0c00; // lock - _LWORD(edx) = handle; - do_xms_call(scp); - if (_LWORD(eax) != 1) - goto out; - pa = (_LWORD(edx) << 16) | _LWORD(ebx); - ret = DPMIMapHWRam(pa & _PAGE_MASK, PAGE_ALIGN(sz)); - if (ret == (dosaddr_t)-1 || (ret & (PAGE_SIZE - 1))) - goto out; - ret += pa & (PAGE_SIZE - 1); -out: - *scp = sa; - return ret; -} - -static void xms_unmap(cpuctx_t *scp, unsigned handle, dosaddr_t va) -{ - int err; - cpuctx_t sa = *scp; - err = DPMIUnmapHWRam(va & _PAGE_MASK); - if (err) - error("error unmapping hwram\n"); - _LWORD(eax) = 0x0d00; // unlock - _LWORD(edx) = handle; - do_xms_call(scp); - if (_LWORD(eax) != 1) - error("error unlocking emb\n"); - *scp = sa; + RMREG(ss) = 0; + RMREG(sp) = 0; + RMREG(cs) = dst.segment; + RMREG(ip) = dst.offset; + _dpmi_simulate_real_mode_procedure_retf(scp, is_32, rmreg); } static void xmshlp_thr(void *arg) { - cpuctx_t *scp = arg; + sigcontext_t *scp = arg; + sigcontext_t sa = *scp; + __dpmi_regs rmreg = {}; + unsigned short rm_seg = helper.rm_seg(scp, 0, helper.rm_arg); int is_32 = msdos_is_32(); + far_t XMS_call; - if (_HI_(ax) == 0x0b) { - struct EMM *e = SEL_ADR_CLNT(_ds_, _esi_, is_32); - if (e->SourceHandle == 0 || e->DestHandle == 0) { - dosaddr_t src = -1, dst = -1; - unsigned char *s = NULL, *d = NULL; - if (e->SourceHandle != 0) { - src = xms_map(scp, e->SourceHandle, - e->SourceOffset + e->Length); - if (src != (dosaddr_t)-1) - s = MEM_BASE32(src + e->SourceOffset); - } else { - s = SEL_ADR_CLNT(_ds_, e->SourceOffset, is_32); - } - if (!s) { - _LWORD(eax) = 0; - _LWORD(ebx) = 0xa7; - return; - } - if (e->DestHandle != 0) { - dst = xms_map(scp, e->DestHandle, e->DestOffset + e->Length); - if (dst != (dosaddr_t)-1) - d = MEM_BASE32(dst + e->DestOffset); - } else { - d = SEL_ADR_CLNT(_ds_, e->DestOffset, is_32); - } - if (!d) { - _LWORD(eax) = 0; - _LWORD(ebx) = 0xa7; - return; - } - memcpy(d, s, e->Length); - if (e->SourceHandle != 0) - xms_unmap(scp, e->SourceHandle, src); - if (e->DestHandle != 0) - xms_unmap(scp, e->DestHandle, dst); - _LWORD(eax) = 1; - return; - } - } - - do_xms_call(scp); + XMS_call = xms_call(scp, &rmreg, rm_seg); + do_call_to(scp, is_32, XMS_call, &rmreg); + *scp = sa; + xms_ret(scp, &rmreg); } struct pmaddr_s get_xms_handler(void) { - return doshlp_get_entry(helper.entry); + return doshlp_get_entry(&helper); } void xmshlp_init(void) diff --git a/src/dosext/dpmi/msdoshlp.c b/src/dosext/dpmi/msdoshlp.c index 99f1a07..1e56fd2 100644 --- a/src/dosext/dpmi/msdoshlp.c +++ b/src/dosext/dpmi/msdoshlp.c @@ -46,29 +46,27 @@ #define MAX_CBKS 3 struct msdos_ops { - void (*fault)(cpuctx_t *scp, void *arg); + void (*fault)(sigcontext_t *scp, void *arg); void *fault_arg; - void (*pagefault)(cpuctx_t *scp, void *arg); + void (*pagefault)(sigcontext_t *scp, void *arg); void *pagefault_arg; - void (*api_call)(cpuctx_t *scp, void *arg); + void (*api_call)(sigcontext_t *scp, void *arg); void *api_arg; - void (*api_winos2_call)(cpuctx_t *scp, void *arg); + void (*api_winos2_call)(sigcontext_t *scp, void *arg); void *api_winos2_arg; - void (*ldt_update_call16)(cpuctx_t *scp, void *arg); - void (*ldt_update_call32)(cpuctx_t *scp, void *arg); - void (*rsp_call16)(cpuctx_t *scp, void *arg); - void (*rsp_call32)(cpuctx_t *scp, void *arg); - struct pmrm_ret (*ext_call)(cpuctx_t *scp, + void (*ldt_update_call16)(sigcontext_t *scp, void *arg); + void (*ldt_update_call32)(sigcontext_t *scp, void *arg); + struct pmrm_ret (*ext_call)(sigcontext_t *scp, struct RealModeCallStructure *rmreg, unsigned short rm_seg, void *(*arg)(int), int off); void *(*ext_arg)(int); - struct pext_ret (*ext_ret)(cpuctx_t *scp, + struct pext_ret (*ext_ret)(sigcontext_t *scp, const struct RealModeCallStructure *rmreg, unsigned short rm_seg, int off); - void (*rmcb_handler[MAX_CBKS])(cpuctx_t *scp, + void (*rmcb_handler[MAX_CBKS])(sigcontext_t *scp, const struct RealModeCallStructure *rmreg, int is_32, void *arg); void *rmcb_arg[MAX_CBKS]; - void (*rmcb_ret_handler[MAX_CBKS])(cpuctx_t *scp, + void (*rmcb_ret_handler[MAX_CBKS])(sigcontext_t *scp, struct RealModeCallStructure *rmreg, int is_32); int (*is_32)(void); u_short cb_es; @@ -91,10 +89,10 @@ static struct rm_helper_s term_helper; static void *hlt_state; -static void do_retf(cpuctx_t *scp) +static void do_retf(sigcontext_t *scp) { int is_32 = msdos.is_32(); - void *sp = SEL_ADR(_ss, _esp); + void *sp = SEL_ADR_CLNT(_ss, _esp, is_32); if (is_32) { unsigned int *ssp = sp; _eip = *ssp++; @@ -108,10 +106,10 @@ static void do_retf(cpuctx_t *scp) } } -static void do_dpmi_iret(cpuctx_t *scp) +static void do_iret(sigcontext_t *scp) { int is_32 = msdos.is_32(); - void *sp = SEL_ADR(_ss, _esp); + void *sp = SEL_ADR_CLNT(_ss, _esp, is_32); if (is_32) { unsigned int *ssp = sp; _eip = *ssp++; @@ -130,41 +128,23 @@ static void do_dpmi_iret(cpuctx_t *scp) } static void hlp_fill_rest(struct dos_helper_s *h, - unsigned short (*rm_seg)(cpuctx_t *, int, void *), void *rm_arg) + unsigned short (*rm_seg)(sigcontext_t *, int, void *), void *rm_arg) { h->rm_seg = rm_seg; h->rm_arg = rm_arg; } -struct pmaddr_s doshlp_get_entry(unsigned entry) +struct pmaddr_s doshlp_get_entry(struct dos_helper_s *h) { struct pmaddr_s ret = { - .offset = entry, + .offset = h->entry, .selector = dpmi_sel(), }; return ret; } -struct pmaddr_s doshlp_get_entry16(unsigned entry) -{ - struct pmaddr_s ret = { - .offset = entry, - .selector = dpmi_sel16(), - }; - return ret; -} - -struct pmaddr_s doshlp_get_entry32(unsigned entry) -{ - struct pmaddr_s ret = { - .offset = entry, - .selector = dpmi_sel32(), - }; - return ret; -} - -void doshlp_setup(struct dos_helper_s *h, const char *name, - void (*thr)(void *), void (*post)(cpuctx_t *)) +static void doshlp_setup(struct dos_helper_s *h, const char *name, + void (*thr)(void *), void (*post)(sigcontext_t *)) { #ifdef DOSEMU h->tid = coopth_create_pm(name, thr, post, hlt_state, @@ -175,17 +155,17 @@ void doshlp_setup(struct dos_helper_s *h, const char *name, void doshlp_setup_retf(struct dos_helper_s *h, const char *name, void (*thr)(void *), - unsigned short (*rm_seg)(cpuctx_t *, int, void *), + unsigned short (*rm_seg)(sigcontext_t *, int, void *), void *rm_arg) { doshlp_setup(h, name, thr, do_retf); hlp_fill_rest(h, rm_seg, rm_arg); } -static void do_callf(cpuctx_t *scp, struct pmaddr_s pma) +static void do_callf(sigcontext_t *scp, struct pmaddr_s pma) { int is_32 = msdos.is_32(); - void *sp = SEL_ADR(_ss, _esp); + void *sp = SEL_ADR_CLNT(_ss, _esp, is_32); if (is_32) { unsigned int *ssp = sp; *--ssp = _cs; @@ -204,23 +184,23 @@ static void do_callf(cpuctx_t *scp, struct pmaddr_s pma) #ifdef DOSEMU static void iret2far(int tid, void *arg, void *arg2) { - cpuctx_t *scp = arg2; + sigcontext_t *scp = arg2; struct pmaddr_s pma; pma.selector = _cs; pma.offset = _eip; coopth_push_user_data(tid, (void *)(uintptr_t)_eflags); - do_dpmi_iret(scp); + do_iret(scp); do_callf(scp, pma); if (debug_level('M') >= 9) D_printf("iret2far %s\n", DPMI_show_state(scp)); } #endif -static void make_iret_frame(cpuctx_t *scp, struct pmaddr_s pma) +static void make_iret_frame(sigcontext_t *scp, struct pmaddr_s pma) { int is_32 = msdos.is_32(); - void *sp = SEL_ADR(_ss, _esp); + void *sp = SEL_ADR_CLNT(_ss, _esp, is_32); if (is_32) { unsigned int *ssp = sp; @@ -242,7 +222,7 @@ static void make_iret_frame(cpuctx_t *scp, struct pmaddr_s pma) #ifdef DOSEMU static void far2iret(int tid, void *arg, void *arg2) { - cpuctx_t *scp = arg2; + sigcontext_t *scp = arg2; void *udata = coopth_pop_user_data(tid); struct pmaddr_s pma; @@ -257,7 +237,7 @@ static void far2iret(int tid, void *arg, void *arg2) #endif static void doshlp_setup_m(struct dos_helper_s *h, const char *name, - void (*thr)(void *), void (*post)(cpuctx_t *), int len) + void (*thr)(void *), void (*post)(sigcontext_t *), int len) { #ifdef DOSEMU h->tid = coopth_create_pm_multi(name, thr, post, hlt_state, @@ -338,10 +318,10 @@ static int get_cb(int num) return 0; } -struct pmaddr_s get_pmcb_handler(void (*handler)(cpuctx_t *, +struct pmaddr_s get_pmcb_handler(void (*handler)(sigcontext_t *, const struct RealModeCallStructure *, int, void *), void *arg, - void (*ret_handler)(cpuctx_t *, + void (*ret_handler)(sigcontext_t *, struct RealModeCallStructure *, int), int num) { @@ -356,7 +336,7 @@ struct pmaddr_s get_pmcb_handler(void (*handler)(cpuctx_t *, } struct pmaddr_s get_pm_handler(enum MsdOpIds id, - void (*handler)(cpuctx_t *, void *), void *arg) + void (*handler)(sigcontext_t *, void *), void *arg) { struct pmaddr_s ret; switch (id) { @@ -394,16 +374,6 @@ struct pmaddr_s get_pm_handler(enum MsdOpIds id, ret.selector = dpmi_sel32(); ret.offset = DPMI_SEL_OFF(MSDOS_LDT_call32); break; - case MSDOS_RSP_CALL16: - msdos.rsp_call16 = handler; - ret.selector = dpmi_sel16(); - ret.offset = DPMI_SEL_OFF(MSDOS_RSP_call16); - break; - case MSDOS_RSP_CALL32: - msdos.rsp_call32 = handler; - ret.selector = dpmi_sel32(); - ret.offset = DPMI_SEL_OFF(MSDOS_RSP_call32); - break; default: dosemu_error("unknown pm handler\n"); ret = (struct pmaddr_s){ 0, 0 }; @@ -414,13 +384,13 @@ struct pmaddr_s get_pm_handler(enum MsdOpIds id, struct pmaddr_s get_pmrm_handler_m(enum MsdOpIds id, struct pmrm_ret (*handler)( - cpuctx_t *, struct RealModeCallStructure *, + sigcontext_t *, struct RealModeCallStructure *, unsigned short, void *(*)(int), int), void *(*arg)(int), struct pext_ret (*ret_handler)( - cpuctx_t *, const struct RealModeCallStructure *, + sigcontext_t *, const struct RealModeCallStructure *, unsigned short, int), - unsigned short (*rm_seg)(cpuctx_t *, int, void *), + unsigned short (*rm_seg)(sigcontext_t *, int, void *), void *rm_arg, int len, int r_offs[]) { struct dos_helper_s *h; @@ -434,7 +404,7 @@ struct pmaddr_s get_pmrm_handler_m(enum MsdOpIds id, h = &ext_helper; hlp_fill_rest(h, rm_seg, rm_arg); memcpy(r_offs, h->e_offs, len * sizeof(r_offs[0])); - ret = doshlp_get_entry(h->entry); + ret = doshlp_get_entry(h); break; default: dosemu_error("unknown pmrm handler\n"); @@ -457,7 +427,7 @@ far_t get_term_helper(void) } #ifdef DOSEMU -static void run_call_handler(int idx, cpuctx_t *scp) +static void run_call_handler(int idx, sigcontext_t *scp) { int is_32 = msdos.is_32(); struct RealModeCallStructure *rmreg = @@ -467,7 +437,7 @@ static void run_call_handler(int idx, cpuctx_t *scp) msdos.rmcb_handler[idx](scp, rmreg, is_32, msdos.rmcb_arg[idx]); } -static void run_ret_handler(int idx, cpuctx_t *scp) +static void run_ret_handler(int idx, sigcontext_t *scp) { int is_32 = msdos.is_32(); struct RealModeCallStructure *rmreg = @@ -477,7 +447,7 @@ static void run_ret_handler(int idx, cpuctx_t *scp) _edi = msdos.cb_edi; } -void msdos_pm_call(cpuctx_t *scp) +void msdos_pm_call(sigcontext_t *scp) { if (_eip == 1 + DPMI_SEL_OFF(MSDOS_fault)) { msdos.fault(scp, msdos.fault_arg); @@ -491,10 +461,6 @@ void msdos_pm_call(cpuctx_t *scp) msdos.ldt_update_call16(scp, NULL); } else if (_eip == 1 + DPMI_SEL_OFF(MSDOS_LDT_call32)) { msdos.ldt_update_call32(scp, NULL); - } else if (_eip == 1 + DPMI_SEL_OFF(MSDOS_RSP_call16)) { - msdos.rsp_call16(scp, NULL); - } else if (_eip == 1 + DPMI_SEL_OFF(MSDOS_RSP_call32)) { - msdos.rsp_call32(scp, NULL); } else if (_eip >= 1 + DPMI_SEL_OFF(MSDOS_rmcb_call_start) && _eip < 1 + DPMI_SEL_OFF(MSDOS_rmcb_call_end)) { int idx, ret; @@ -534,7 +500,7 @@ void msdos_pm_call(cpuctx_t *scp) } #endif -static void do_int_call(cpuctx_t *scp, int is_32, int num, +static void do_int_call(sigcontext_t *scp, int is_32, int num, struct RealModeCallStructure *rmreg) { RMREG(ss) = 0; @@ -542,7 +508,7 @@ static void do_int_call(cpuctx_t *scp, int is_32, int num, _dpmi_simulate_real_mode_interrupt(scp, is_32, num, (__dpmi_regs *)rmreg); } -static void copy_rest(cpuctx_t *scp, cpuctx_t *src) +static void copy_rest(sigcontext_t *scp, sigcontext_t *src) { #define CP_R(r) _##r = get_##r(src) CP_R(eax); @@ -554,7 +520,7 @@ static void copy_rest(cpuctx_t *scp, cpuctx_t *src) CP_R(es); } -static void do_restore(cpuctx_t *scp, cpuctx_t *sa) +static void do_restore(sigcontext_t *scp, sigcontext_t *sa) { /* make sure most things did not change */ #define _CHK(r) assert(_##r == get_##r(sa)) @@ -571,37 +537,19 @@ static void do_restore(cpuctx_t *scp, cpuctx_t *sa) copy_rest(scp, sa); } -void doshlp_quit_dpmi(cpuctx_t *scp) +void doshlp_quit_dpmi(sigcontext_t *scp) { struct pmaddr_s pma = { .offset = DPMI_SEL_OFF(DPMI_msdos), .selector = dpmi_sel(), }; - coopth_leave_pm(scp); + coopth_leave(); + do_iret(scp); _eax = 0x4c01; do_callf(scp, pma); } -struct pmaddr_s doshlp_get_abort_helper(void) -{ - return (struct pmaddr_s){ - .offset = DPMI_SEL_OFF(DPMI_abort), - .selector = dpmi_sel(), - }; -} - -void doshlp_call_reinit(cpuctx_t *scp) -{ - struct pmaddr_s pma = { - .offset = DPMI_SEL_OFF(DPMI_reinit), - .selector = dpmi_sel(), - }; - - do_callf(scp, pma); - coopth_sched(); -} - -static void do_int_to(cpuctx_t *scp, int is_32, far_t dst, +static void do_int_to(sigcontext_t *scp, int is_32, far_t dst, struct RealModeCallStructure *rmreg) { RMREG(ss) = 0; @@ -612,7 +560,7 @@ static void do_int_to(cpuctx_t *scp, int is_32, far_t dst, } struct postext_args { - cpuctx_t *scp; + sigcontext_t *scp; unsigned arg; }; @@ -621,7 +569,7 @@ static struct postext_args pargs; static void do_post_push(void *arg) { struct postext_args *args = arg; - cpuctx_t *scp = args->scp; + sigcontext_t *scp = args->scp; int is_32 = msdos.is_32(); if (is_32) { _esp -= 4; @@ -637,8 +585,8 @@ static void do_post_push(void *arg) #ifdef DOSEMU static void exthlp_thr(void *arg) { - cpuctx_t *scp = arg; - cpuctx_t sa = *scp; + sigcontext_t *scp = arg; + sigcontext_t sa = *scp; struct dos_helper_s *hlp = &ext_helper; struct RealModeCallStructure rmreg = {}; int off = coopth_get_tid() - hlp->tid; @@ -691,7 +639,7 @@ void msdoshlp_init(int (*is_32)(void), int len) #ifdef DOSEMU hlt_state = hlt_init(DPMI_SEL_OFF(MSDOS_hlt_end) - DPMI_SEL_OFF(MSDOS_hlt_start)); - doshlp_setup_m(&ext_helper, "msdos ext thr", exthlp_thr, do_dpmi_iret, + doshlp_setup_m(&ext_helper, "msdos ext thr", exthlp_thr, do_iret, len); exechlp_setup(); termhlp_setup(); @@ -701,15 +649,9 @@ void msdoshlp_init(int (*is_32)(void), int len) int doshlp_idle(void) { #ifdef DOSEMU - idle_enable(100, 0, "int2f_idle_dpmi"); + idle_enable(0, 100, 0, "int2f_idle_dpmi"); return config.hogthreshold; #else return 0; #endif } - -Bit16u hlt_register_handler_pm(emu_hlt_t handler) -{ - return hlt_register_handler(hlt_state, handler) + - DPMI_SEL_OFF(MSDOS_hlt_start); -} diff --git a/src/dosext/dpmi/msdoshlp.h b/src/dosext/dpmi/msdoshlp.h index 7a90cf6..73cd635 100644 --- a/src/dosext/dpmi/msdoshlp.h +++ b/src/dosext/dpmi/msdoshlp.h @@ -5,27 +5,24 @@ #include "sig.h" #endif #include "cpu.h" -#include "hlt.h" #include "emudpmi.h" enum MsdOpIds { MSDOS_FAULT, MSDOS_PAGEFAULT, API_CALL, API_WINOS2_CALL, - MSDOS_LDT_CALL16, MSDOS_LDT_CALL32, - MSDOS_RSP_CALL16, MSDOS_RSP_CALL32, - MSDOS_EXT_CALL }; + MSDOS_LDT_CALL16, MSDOS_LDT_CALL32, MSDOS_EXT_CALL }; enum { MSDOS_NONE, MSDOS_RMINT, MSDOS_RM, MSDOS_PM, MSDOS_DONE }; enum { POSTEXT_NONE, POSTEXT_PUSH }; -void msdos_pm_call(cpuctx_t *scp); +void msdos_pm_call(sigcontext_t *scp); -struct pmaddr_s get_pmcb_handler(void (*handler)(cpuctx_t *, +struct pmaddr_s get_pmcb_handler(void (*handler)(sigcontext_t *, const struct RealModeCallStructure *, int, void *), void *arg, - void (*ret_handler)(cpuctx_t *, + void (*ret_handler)(sigcontext_t *, struct RealModeCallStructure *, int), int num); struct pmaddr_s get_pm_handler(enum MsdOpIds id, - void (*handler)(cpuctx_t *, void *), void *arg); + void (*handler)(sigcontext_t *, void *), void *arg); struct pmrm_ret { int ret; far_t faddr; @@ -38,13 +35,13 @@ struct pext_ret { }; struct pmaddr_s get_pmrm_handler_m(enum MsdOpIds id, struct pmrm_ret (*handler)( - cpuctx_t *, struct RealModeCallStructure *, + sigcontext_t *, struct RealModeCallStructure *, unsigned short, void *(*)(int), int), void *(*arg)(int), struct pext_ret (*ret_handler)( - cpuctx_t *, const struct RealModeCallStructure *, + sigcontext_t *, const struct RealModeCallStructure *, unsigned short, int), - unsigned short (*rm_seg)(cpuctx_t *, int, void *), + unsigned short (*rm_seg)(sigcontext_t *, int, void *), void *rm_arg, int len, int r_offs[]); far_t get_exec_helper(void); far_t get_term_helper(void); @@ -54,27 +51,18 @@ void msdoshlp_init(int (*is_32)(void), int len); struct dos_helper_s { int tid; unsigned entry; - unsigned short (*rm_seg)(cpuctx_t *, int, void *); + unsigned short (*rm_seg)(sigcontext_t *, int, void *); void *rm_arg; int e_offs[256]; }; void doshlp_setup_retf(struct dos_helper_s *h, const char *name, void (*thr)(void *), - unsigned short (*rm_seg)(cpuctx_t *, int, void *), + unsigned short (*rm_seg)(sigcontext_t *, int, void *), void *rm_arg); -void doshlp_setup(struct dos_helper_s *h, - const char *name, void (*thr)(void *), - void (*post)(cpuctx_t *)); -struct pmaddr_s doshlp_get_entry(unsigned entry); -struct pmaddr_s doshlp_get_entry16(unsigned entry); -struct pmaddr_s doshlp_get_entry32(unsigned entry); +struct pmaddr_s doshlp_get_entry(struct dos_helper_s *h); -void doshlp_quit_dpmi(cpuctx_t *scp); -struct pmaddr_s doshlp_get_abort_helper(void); -void doshlp_call_reinit(cpuctx_t *scp); +void doshlp_quit_dpmi(sigcontext_t *scp); int doshlp_idle(void); -Bit16u hlt_register_handler_pm(emu_hlt_t handler); - #endif diff --git a/src/dosext/dpmi/stub/dpmi.h b/src/dosext/dpmi/stub/dpmi.h new file mode 100644 index 0000000..2883659 --- /dev/null +++ b/src/dosext/dpmi/stub/dpmi.h @@ -0,0 +1,360 @@ +/* Copyright (C) 2012 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_dpmi_h_ +#define __dj_include_dpmi_h_ + +#include +#define LONG int32_t +#define ULONG uint32_t + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \ + || !defined(__STRICT_ANSI__) || defined(__cplusplus) + +#endif /* (__STDC_VERSION__ >= 199901L) || !__STRICT_ANSI__ */ + +#ifndef __STRICT_ANSI__ + +//#ifndef _POSIX_SOURCE + +extern unsigned short __dpmi_error; + +typedef struct { + unsigned short offset16; + unsigned short segment; +} __dpmi_raddr; + +typedef struct { + ULONG offset32; + unsigned short selector; +} __dpmi_paddr; + +typedef struct { + ULONG handle; /* 0, 2 */ + ULONG size; /* or count */ /* 4, 6 */ + ULONG address; /* 8, 10 */ +} __dpmi_meminfo; + +typedef union { + struct { + ULONG edi; + ULONG esi; + ULONG ebp; + ULONG res; + ULONG ebx; + ULONG edx; + ULONG ecx; + ULONG eax; + } d; + struct { + unsigned short di, di_hi; + unsigned short si, si_hi; + unsigned short bp, bp_hi; + unsigned short res, res_hi; + unsigned short bx, bx_hi; + unsigned short dx, dx_hi; + unsigned short cx, cx_hi; + unsigned short ax, ax_hi; + unsigned short flags; + unsigned short es; + unsigned short ds; + unsigned short fs; + unsigned short gs; + unsigned short ip; + unsigned short cs; + unsigned short sp; + unsigned short ss; + } x; + struct { + unsigned char edi[4]; + unsigned char esi[4]; + unsigned char ebp[4]; + unsigned char res[4]; + unsigned char bl, bh, ebx_b2, ebx_b3; + unsigned char dl, dh, edx_b2, edx_b3; + unsigned char cl, ch, ecx_b2, ecx_b3; + unsigned char al, ah, eax_b2, eax_b3; + } h; +} __attribute__((packed)) __dpmi_regs; + +typedef struct { + unsigned char major; + unsigned char minor; + unsigned short flags; + unsigned char cpu; + unsigned char master_pic; + unsigned char slave_pic; +} __dpmi_version_ret; + +typedef struct { + ULONG largest_available_free_block_in_bytes; + ULONG maximum_unlocked_page_allocation_in_pages; + ULONG maximum_locked_page_allocation_in_pages; + ULONG linear_address_space_size_in_pages; + ULONG total_number_of_unlocked_pages; + ULONG total_number_of_free_pages; + ULONG total_number_of_physical_pages; + ULONG free_linear_address_space_in_pages; + ULONG size_of_paging_file_partition_in_pages; + ULONG reserved[3]; +} __dpmi_free_mem_info; + +typedef struct { + ULONG total_allocated_bytes_of_physical_memory_host; + ULONG total_allocated_bytes_of_virtual_memory_host; + ULONG total_available_bytes_of_virtual_memory_host; + ULONG total_allocated_bytes_of_virtual_memory_vcpu; + ULONG total_available_bytes_of_virtual_memory_vcpu; + ULONG total_allocated_bytes_of_virtual_memory_client; + ULONG total_available_bytes_of_virtual_memory_client; + ULONG total_locked_bytes_of_memory_client; + ULONG max_locked_bytes_of_memory_client; + ULONG highest_linear_address_available_to_client; + ULONG size_in_bytes_of_largest_free_memory_block; + ULONG size_of_minimum_allocation_unit_in_bytes; + ULONG size_of_allocation_alignment_unit_in_bytes; + ULONG reserved[19]; +} __dpmi_memory_info; + +typedef struct { + ULONG data16[2]; + ULONG code16[2]; + unsigned short ip; + unsigned short reserved; + ULONG data32[2]; + ULONG code32[2]; + ULONG eip; +} __dpmi_callback_info; + +typedef struct { + ULONG size_requested; + ULONG size; + ULONG handle; + ULONG address; + ULONG name_offset; + unsigned short name_selector; + unsigned short reserved1; + ULONG reserved2; +} __dpmi_shminfo; + +/* Unless otherwise noted, all functions return -1 on error, setting __dpmi_error to the DPMI error code */ + +void __dpmi_yield(void); /* INT 0x2F AX=1680 */ + +int __dpmi_allocate_ldt_descriptors(int _count); /* DPMI 0.9 AX=0000 */ +int __dpmi_free_ldt_descriptor(int _descriptor); /* DPMI 0.9 AX=0001 */ +int __dpmi_segment_to_descriptor(int _segment); /* DPMI 0.9 AX=0002 */ +int __dpmi_get_selector_increment_value(void); /* DPMI 0.9 AX=0003 */ +int __dpmi_get_segment_base_address(int _selector, ULONG *_addr); /* DPMI 0.9 AX=0006 */ +int __dpmi_set_segment_base_address(int _selector, ULONG _address); /* DPMI 0.9 AX=0007 */ +ULONG __dpmi_get_segment_limit(int _selector); /* LSL instruction */ +int __dpmi_set_segment_limit(int _selector, ULONG _limit); /* DPMI 0.9 AX=0008 */ +int __dpmi_get_descriptor_access_rights(int _selector); /* LAR instruction */ +int __dpmi_set_descriptor_access_rights(int _selector, int _rights); /* DPMI 0.9 AX=0009 */ +int __dpmi_create_alias_descriptor(int _selector); /* DPMI 0.9 AX=000a */ +int __dpmi_get_descriptor(int _selector, void *_buffer); /* DPMI 0.9 AX=000b */ +int __dpmi_set_descriptor(int _selector, void *_buffer); /* DPMI 0.9 AX=000c */ +int __dpmi_allocate_specific_ldt_descriptor(int _selector); /* DPMI 0.9 AX=000d */ + +int __dpmi_get_multiple_descriptors(int _count, void *_buffer); /* DPMI 1.0 AX=000e */ +int __dpmi_set_multiple_descriptors(int _count, void *_buffer); /* DPMI 1.0 AX=000f */ + +int __dpmi_allocate_dos_memory(int _paragraphs, int *_ret_selector_or_max); /* DPMI 0.9 AX=0100 */ +int __dpmi_free_dos_memory(int _selector); /* DPMI 0.9 AX=0101 */ +int __dpmi_resize_dos_memory(int _selector, int _newpara, int *_ret_max); /* DPMI 0.9 AX=0102 */ + +int __dpmi_get_real_mode_interrupt_vector(int _vector, __dpmi_raddr *_address); /* DPMI 0.9 AX=0200 */ +int __dpmi_set_real_mode_interrupt_vector(int _vector, __dpmi_raddr *_address); /* DPMI 0.9 AX=0201 */ +int __dpmi_get_processor_exception_handler_vector(int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0202 */ +int __dpmi_set_processor_exception_handler_vector(int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0203 */ +int __dpmi_get_protected_mode_interrupt_vector(int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0204 */ +int __dpmi_set_protected_mode_interrupt_vector(int _vector, __dpmi_paddr *_address); /* DPMI 0.9 AX=0205 */ + +int __dpmi_get_extended_exception_handler_vector_pm(int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0210 */ +int __dpmi_get_extended_exception_handler_vector_rm(int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0211 */ +int __dpmi_set_extended_exception_handler_vector_pm(int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0212 */ +int __dpmi_set_extended_exception_handler_vector_rm(int _vector, __dpmi_paddr *_address); /* DPMI 1.0 AX=0213 */ + +int __dpmi_simulate_real_mode_interrupt(int _vector, __dpmi_regs *_regs); /* DPMI 0.9 AX=0300 */ +int __dpmi_int(int _vector, __dpmi_regs *_regs); /* like above, but sets ss sp fl */ /* DPMI 0.9 AX=0300 */ +extern short __dpmi_int_ss, __dpmi_int_sp, __dpmi_int_flags; /* default to zero */ +int __dpmi_simulate_real_mode_procedure_retf(__dpmi_regs *_regs); /* DPMI 0.9 AX=0301 */ +int __dpmi_simulate_real_mode_procedure_retf_stack(__dpmi_regs *_regs, int stack_words_to_copy, const void *stack_data); /* DPMI 0.9 AX=0301 */ +int __dpmi_simulate_real_mode_procedure_iret(__dpmi_regs *_regs); /* DPMI 0.9 AX=0302 */ +int __dpmi_allocate_real_mode_callback(void (*_handler)(void), __dpmi_regs *_regs, __dpmi_raddr *_ret); /* DPMI 0.9 AX=0303 */ +int __dpmi_free_real_mode_callback(__dpmi_raddr *_addr); /* DPMI 0.9 AX=0304 */ +int __dpmi_get_state_save_restore_addr(__dpmi_raddr *_rm, __dpmi_paddr *_pm); /* DPMI 0.9 AX=0305 */ +int __dpmi_get_raw_mode_switch_addr(__dpmi_raddr *_rm, __dpmi_paddr *_pm); /* DPMI 0.9 AX=0306 */ + +int __dpmi_get_version(__dpmi_version_ret *_ret); /* DPMI 0.9 AX=0400 */ + +int __dpmi_get_capabilities(int *_flags, char *vendor_info); /* DPMI 1.0 AX=0401 */ + +int __dpmi_get_free_memory_information(__dpmi_free_mem_info *_info); /* DPMI 0.9 AX=0500 */ +int __dpmi_allocate_memory(__dpmi_meminfo *_info); /* DPMI 0.9 AX=0501 */ +int __dpmi_free_memory(ULONG _handle); /* DPMI 0.9 AX=0502 */ +int __dpmi_resize_memory(__dpmi_meminfo *_info); /* DPMI 0.9 AX=0503 */ + +int __dpmi_allocate_linear_memory(__dpmi_meminfo *_info, int _commit); /* DPMI 1.0 AX=0504 */ +int __dpmi_resize_linear_memory(__dpmi_meminfo *_info, int _commit); /* DPMI 1.0 AX=0505 */ +int __dpmi_get_page_attributes(__dpmi_meminfo *_info, short *_buffer); /* DPMI 1.0 AX=0506 */ +int __dpmi_set_page_attributes(__dpmi_meminfo *_info, short *_buffer); /* DPMI 1.0 AX=0507 */ +int __dpmi_map_device_in_memory_block(__dpmi_meminfo *_info, ULONG _physaddr); /* DPMI 1.0 AX=0508 */ +int __dpmi_map_conventional_memory_in_memory_block(__dpmi_meminfo *_info, ULONG _physaddr); /* DPMI 1.0 AX=0509 */ +int __dpmi_get_memory_block_size_and_base(__dpmi_meminfo *_info); /* DPMI 1.0 AX=050a */ +int __dpmi_get_memory_information(__dpmi_memory_info *_buffer); /* DPMI 1.0 AX=050b */ + +int __dpmi_lock_linear_region(__dpmi_meminfo *_info); /* DPMI 0.9 AX=0600 */ +int __dpmi_unlock_linear_region(__dpmi_meminfo *_info); /* DPMI 0.9 AX=0601 */ +int __dpmi_mark_real_mode_region_as_pageable(__dpmi_meminfo *_info); /* DPMI 0.9 AX=0602 */ +int __dpmi_relock_real_mode_region(__dpmi_meminfo *_info); /* DPMI 0.9 AX=0603 */ +int __dpmi_get_page_size(ULONG *_size); /* DPMI 0.9 AX=0604 */ + +int __dpmi_mark_page_as_demand_paging_candidate(__dpmi_meminfo *_info); /* DPMI 0.9 AX=0702 */ +int __dpmi_discard_page_contents(__dpmi_meminfo *_info); /* DPMI 0.9 AX=0703 */ + +int __dpmi_physical_address_mapping(__dpmi_meminfo *_info); /* DPMI 0.9 AX=0800 */ +int __dpmi_free_physical_address_mapping(__dpmi_meminfo *_info); /* DPMI 0.9 AX=0801 */ + +/* These next four functions return the old state */ +int __dpmi_get_and_disable_virtual_interrupt_state(void); /* DPMI 0.9 AX=0900 */ +int __dpmi_get_and_enable_virtual_interrupt_state(void); /* DPMI 0.9 AX=0901 */ +int __dpmi_get_and_set_virtual_interrupt_state(int _old_state); /* DPMI 0.9 AH=09 */ +int __dpmi_get_virtual_interrupt_state(void); /* DPMI 0.9 AX=0902 */ + +int __dpmi_get_vendor_specific_api_entry_point(char *_id, __dpmi_paddr *_api); /* DPMI 0.9 AX=0a00 */ + +int __dpmi_set_debug_watchpoint(__dpmi_meminfo *_info, int _type); /* DPMI 0.9 AX=0b00 */ +int __dpmi_clear_debug_watchpoint(ULONG _handle); /* DPMI 0.9 AX=0b01 */ +int __dpmi_get_state_of_debug_watchpoint(ULONG _handle, int *_status); /* DPMI 0.9 AX=0b02 */ +int __dpmi_reset_debug_watchpoint(ULONG _handle); /* DPMI 0.9 AX=0b03 */ + +int __dpmi_install_resident_service_provider_callback(__dpmi_callback_info *_info); /* DPMI 1.0 AX=0c00 */ +int __dpmi_terminate_and_stay_resident(int return_code, int paragraphs_to_keep); /* DPMI 1.0 AX=0c01 */ + +int __dpmi_allocate_shared_memory(__dpmi_shminfo *_info); /* DPMI 1.0 AX=0d00 */ +int __dpmi_free_shared_memory(ULONG _handle); /* DPMI 1.0 AX=0d01 */ +int __dpmi_serialize_on_shared_memory(ULONG _handle, int _flags); /* DPMI 1.0 AX=0d02 */ +int __dpmi_free_serialization_on_shared_memory(ULONG _handle, int _flags); /* DPMI 1.0 AX=0d03 */ + +int __dpmi_get_coprocessor_status(void); /* DPMI 1.0 AX=0e00 */ +int __dpmi_set_coprocessor_emulation(int _flags); /* DPMI 1.0 AX=0e01 */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Backwards compatibility stuff */ + +#define _go32_dpmi_registers __dpmi_regs + +typedef struct { + ULONG available_memory; + ULONG available_pages; + ULONG available_lockable_pages; + ULONG linear_space; + ULONG unlocked_pages; + ULONG available_physical_pages; + ULONG total_physical_pages; + ULONG free_linear_space; + ULONG max_pages_in_paging_file; + ULONG reserved[3]; +} _go32_dpmi_meminfo; + +#define _go32_dpmi_get_free_memory_information(x) __dpmi_get_free_memory_information((__dpmi_free_mem_info *)(void *)(x)) + +#define _go32_dpmi_simulate_int __dpmi_simulate_real_mode_interrupt +#define _go32_dpmi_simulate_fcall __dpmi_simulate_real_mode_procedure_retf +#define _go32_dpmi_simulate_fcall_iret __dpmi_simulate_real_mode_procedure_iret + +typedef struct { + ULONG size; + ULONG pm_offset; + unsigned short pm_selector; + unsigned short rm_offset; + unsigned short rm_segment; +} _go32_dpmi_seginfo; + +/* returns zero if success, else dpmi error and info->size is max size */ +int _go32_dpmi_allocate_dos_memory(_go32_dpmi_seginfo *info); + /* set size to bytes/16, call, use rm_segment. Do not + change anthing but size until the memory is freed. + If error, max size is returned in size as bytes/16. */ +int _go32_dpmi_free_dos_memory(_go32_dpmi_seginfo *info); + /* set new size to bytes/16, call. If error, max size + is returned in size as bytes/16 */ +int _go32_dpmi_resize_dos_memory(_go32_dpmi_seginfo *info); + /* uses pm_selector to free memory */ + +/* These both use the rm_segment:rm_offset fields only */ +int _go32_dpmi_get_real_mode_interrupt_vector(int vector, _go32_dpmi_seginfo *info); +int _go32_dpmi_set_real_mode_interrupt_vector(int vector, _go32_dpmi_seginfo *info); + +/* These do NOT wrap the function in pm_offset in an iret handler. + You must provide an assembler interface yourself, or alloc one below. + You may NOT LONGjmp out of an interrupt handler. */ +int _go32_dpmi_get_protected_mode_interrupt_vector(int vector, _go32_dpmi_seginfo *info); + /* puts vector in pm_selector:pm_offset. */ +int _go32_dpmi_set_protected_mode_interrupt_vector(int vector, _go32_dpmi_seginfo *info); + /* sets vector from pm_offset and pm_selector */ + +/********** HELPER FUNCTIONS **********/ + +int _go32_dpmi_chain_protected_mode_interrupt_vector(int vector, _go32_dpmi_seginfo *info); + /* sets up wrapper that calls function in pm_offset, chaining to old + handler when it returns */ + +/* These generate assember IRET-style wrappers for functions and set up stack */ +int _go32_dpmi_allocate_iret_wrapper(_go32_dpmi_seginfo *info); + /* Put function ptr in pm_offset, call, returns wrapper entry in pm_offset. */ +int _go32_dpmi_free_iret_wrapper(_go32_dpmi_seginfo *info); + /* assumes pm_offset points to wrapper, frees it */ + +/* RMCB functions, automatically restructure the real-mode stack for the + proper return type and set up correct PM stack. The callback + (info->pm_offset) is called as (*pmcb)(_go32_dpmi_registers *regs); */ +int _go32_dpmi_allocate_real_mode_callback_retf(_go32_dpmi_seginfo *info, _go32_dpmi_registers *regs); + /* points callback at pm_offset, returns seg:ofs of callback addr + in rm_segment:rm_offset. Do not change any fields until freed. + Interface is added to simulate far return */ +int _go32_dpmi_allocate_real_mode_callback_iret(_go32_dpmi_seginfo *info, _go32_dpmi_registers *regs); + /* same, but simulates iret */ +int _go32_dpmi_free_real_mode_callback(_go32_dpmi_seginfo *info); + /* frees callback */ + +/* The following two variables may be used to change the default stack size + for interrupts and rmcb wrappers to a user defined size from the default + of 32Kbytes. Each RMCB and chain/iret wrapper gets its own stack. */ + +extern ULONG _go32_interrupt_stack_size; +extern ULONG _go32_rmcb_stack_size; + +/* Convenience functions, the return value is *bytes* */ +ULONG _go32_dpmi_remaining_physical_memory(void); +ULONG _go32_dpmi_remaining_virtual_memory(void); + +/* locks memory from a specified offset within the code/data selector */ +int _go32_dpmi_lock_code( void *_lockaddr, ULONG _locksize); +int _go32_dpmi_lock_data( void *_lockaddr, ULONG _locksize); + +int __djgpp_set_page_attributes(void *our_addr, ULONG num_bytes, + unsigned short attributes); +int __djgpp_map_physical_memory(void *our_addr, ULONG num_bytes, + ULONG phys_addr); + +//#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* !__dj_include_dpmi_h_ */ diff --git a/src/dosext/dpmi/vxd.c b/src/dosext/dpmi/vxd.c index 69b402b..473bf6e 100644 --- a/src/dosext/dpmi/vxd.c +++ b/src/dosext/dpmi/vxd.c @@ -36,7 +36,7 @@ static UINT W32S_offset = 0; -void get_VXD_entry(cpuctx_t *scp ) +void get_VXD_entry( sigcontext_t *scp ) { switch (_LWORD(ebx)) { case 0x01: @@ -677,7 +677,7 @@ static BOOL WINAPI VirtualUnlock(LPVOID a,SIZE_T b) * This means especially that the flat code/data selectors get actually * allocated with base 0x0, so that flat offsets and (real) linear addresses * do again agree! In fact, every call e.g. of a Win32s VxD service now - * has all pointer arguments (which are offsets in the flat data segment) + * has all pointer arguments (which are offsets in the flat data segement) * first reduced by 0x10000 by the W32SKRNL glue code, and then again * increased by 0x10000 by *our* code. * @@ -761,7 +761,7 @@ static void WINAPI VXD_Win32s( CONTEXT86 *scp ) * and StackLinearToSegmented for the byte sequence '0F 01 04' * (this is the opcode of 'sgdt [si]'). We then search backwards * from this address for the last occurrence of 'CB' (retf) that marks - * the end of the preceding function. The following byte (which + * the end of the preceeding function. The following byte (which * should now be the first byte of the function we are looking for) * will be replaced by 'CB' (retf). * @@ -1819,7 +1819,7 @@ static void WINAPI VXD_Win32s( CONTEXT86 *scp ) } #endif -void vxd_call(cpuctx_t *scp) +void vxd_call(sigcontext_t *scp) { if (_eip==1+DPMI_SEL_OFF(DPMI_VXD_VMM)) { D_printf("DPMI: VMM VxD called, ax=%#x\n", _LWORD(eax)); diff --git a/src/dosext/dpmi/vxd.h b/src/dosext/dpmi/vxd.h index e60c659..fe70ca9 100644 --- a/src/dosext/dpmi/vxd.h +++ b/src/dosext/dpmi/vxd.h @@ -4,5 +4,5 @@ * for details see file COPYING in the DOSEMU distribution */ -void get_VXD_entry(cpuctx_t *scp ); -void vxd_call(cpuctx_t *scp); +void get_VXD_entry( sigcontext_t *scp ); +void vxd_call(sigcontext_t *scp); diff --git a/src/dosext/dpmi/windefs.h b/src/dosext/dpmi/windefs.h index 8c6fb11..48de367 100644 --- a/src/dosext/dpmi/windefs.h +++ b/src/dosext/dpmi/windefs.h @@ -293,7 +293,7 @@ typedef struct _IMAGE_NT_HEADERS { #define W32S_APP2WINE(addr) ((addr)? (uintptr_t)(addr) + W32S_offset : 0) #define W32S_WINE2APP(addr) ((addr)? (uintptr_t)(addr) - W32S_offset : 0) -#define CONTEXT86 cpuctx_t +#define CONTEXT86 sigcontext_t #define GetTickCount() GETtickTIME(0) diff --git a/src/dosext/drivers/aspi.c b/src/dosext/drivers/aspi.c index 6a7a254..ead9a8a 100644 --- a/src/dosext/drivers/aspi.c +++ b/src/dosext/drivers/aspi.c @@ -25,7 +25,7 @@ * - No posting routine possible - reentrancy needed for posting, since the * posting routine may call ASPI services * - Blocking read/write to/from /dev/sg? used - * - Too few sense bytes returned (16 instead of 18). This is a limitation + * - Too few sense bytes returned (16 instead of 18). This is a limitiation * from the sg driver. * - SCSI timeout may need to be increased - formatting a DAT tape may take some time * set to 5 minutes for now. @@ -781,7 +781,7 @@ static Bit16u ASPI_Inquiry(SRB_HaInquiry16 *p) if (p->SRB_55AASignature == 0xAA55) { /* we got an Extended Host Adapter Inquiry command */ p->SRB_55AASignature = 0x55AA; /* reverse the order to indicate we are - * we've set the extension */ + * we've set the extention */ if (p->SRB_ExtBufferSize < 2) { /* oops, that shouldn't happen */ p->SRB_ExtBufferSize = 0; diff --git a/src/dosext/drivers/cdrom.c b/src/dosext/drivers/cdrom.c index c4ba678..efb4c96 100644 --- a/src/dosext/drivers/cdrom.c +++ b/src/dosext/drivers/cdrom.c @@ -509,7 +509,7 @@ void cdrom_helper(unsigned char *req_buf, unsigned char *transfer_buf, = cdrom_subchnl.cdsc_absaddr.msf.minute * 60 * 75 + cdrom_subchnl.cdsc_absaddr.msf.second * 75 + cdrom_subchnl.cdsc_absaddr.msf.frame - 150; - } else { /* red book addressing */ + } else { /* red book adressing */ *CALC_PTR(req_buf, MSCD_LOCH_LOCATION + 3, u_char) = 0; *CALC_PTR(req_buf, MSCD_LOCH_LOCATION + 2, u_char) = cdrom_subchnl.cdsc_absaddr.msf.minute; @@ -553,8 +553,12 @@ void cdrom_helper(unsigned char *req_buf, unsigned char *transfer_buf, LO(ax) = 0; if (eject_allowed) { if (ioctl(cdrom_fd, CDROMSUBCHNL, &cdrom_subchnl)) { - audio_status.status &= 0x100; // no subchannel control + if (ioctl(cdrom_fd, CDROMSUBCHNL, &cdrom_subchnl)) { /* no disk in drive */ + LWORD(ebx) = audio_status.status | 0x800; C_printf("CDROM: subch failed: %s\n", strerror(errno)); + break; + } else + cdrom_reset(); } } /* disk in drive */ diff --git a/src/dosext/mfs/Makefile b/src/dosext/mfs/Makefile index 7658873..861d754 100644 --- a/src/dosext/mfs/Makefile +++ b/src/dosext/mfs/Makefile @@ -3,14 +3,8 @@ top_builddir=../../.. include $(top_builddir)/Makefile.conf -CFILES = mfs.c mangle.c share.c util.c lfn.c mscdex.c -ifeq ($(USE_OFD_LOCKS),1) -CFILES += rlocks.c -endif -ifeq ($(USE_XATTRS),1) -CFILES += xattr.c -endif -HFILES = mfs.h mangle.h share.h xattr.h rlocks.h +CFILES=mfs.c mangle.c util.c lfn.c mscdex.c +HFILES=mfs.h mangle.h ALL=$(CFILES) $(HFILES) ALL_CPPFLAGS += -DDOSEMU=1 -DMANGLE=1 -DMANGLED_STACK=50 diff --git a/src/dosext/mfs/lfn.c b/src/dosext/mfs/lfn.c index 1080ff3..37eca08 100644 --- a/src/dosext/mfs/lfn.c +++ b/src/dosext/mfs/lfn.c @@ -100,38 +100,39 @@ void close_dirhandles(unsigned psp) } } -void lfn_reset(void) -{ - int dirhandle; - for (dirhandle = 0; dirhandle < MAX_OPEN_DIRS; dirhandle++) { - struct lfndir *dir = lfndirs[dirhandle]; - if (dir) - close_dirhandle(dirhandle); - } -} - -static int vfat_search(char *dest, const char *src, const char *path, int alias) +static int vfat_search(char *dest, const char *src, const char *_path, int alias) { struct mfs_dir *dir; struct mfs_dirent *de; + char *path, *slash; int ret = 0; - d_printf("LFN: vfat_search src=%s path=%s alias=%d\n", src, path, alias); + d_printf("LFN: vfat_search src=%s path=%s alias=%d\n", src, _path, alias); + + path = strdup(_path); + if (!path) + return 0; + + slash = strrchr(path, '/'); + if (!slash) { + free(path); + return 0; + } + *slash = '\0'; dir = dos_opendir(path); + free(path); if (dir == NULL) return 0; if (dir->dir == NULL) while ((de = dos_readdir(dir)) != NULL) { - d_printf("LFN: vfat_search (short='%s', long='%s')", de->d_name, de->d_long_name); + d_printf("LFN: vfat_search %s %s\n", de->d_name, de->d_long_name); if ((strcasecmp(de->d_long_name, src) == 0) || (strcasecmp(de->d_name, src) == 0)) { strlcpy(dest, alias ? de->d_name : de->d_long_name, 260); ret = 1; - d_printf(" matched\n"); break; } - d_printf("\n"); } else d_printf("LFN: vfat_search (not VFAT)\n"); @@ -151,13 +152,8 @@ static int make_unmake_dos_mangled_path(char *dest, const char *fpath, char *src; char *fpath2; char root[MAX_RESOURCE_LENGTH_EXT]; - int root_len; - - d_printf("LFN: make_unmake_dos_mangled_path fpath='%s', drive='%c', alias='%d'\n", - fpath, current_drive + 'A', alias); - + int root_len = get_redirection_root1(current_drive, root, sizeof(root)); /* root ends with / and fpath may not, so -1 */ - root_len = get_redirection_root1(current_drive, root, sizeof(root)); if (root_len <= 0 || strncmp(fpath, root, root_len - 1) != 0) return -1; *dest++ = current_drive + 'A'; @@ -170,11 +166,10 @@ static int make_unmake_dos_mangled_path(char *dest, const char *fpath, fpath2 = strdup(fpath); src = fpath2 + root_len; if (*src == '/') src++; - while (src != NULL && *src != '\0') { char *src2 = strchr(src, '/'); if (src2 == src) break; - if (src - 1 > fpath2) + if (src - 1 > fpath) src[-1] = '\0'; if (src2 != NULL) *src2++ = '\0'; @@ -190,7 +185,7 @@ static int make_unmake_dos_mangled_path(char *dest, const char *fpath, } dest += strlen(dest); *dest = '\\'; - if (src - 1 > fpath2) + if (src - 1 > fpath) src[-1] = '/'; src = src2; } @@ -222,7 +217,7 @@ static const char *get_root(const char * fname) register unsigned length = strlen(fname); char c; - /* now back up to first path separator or start */ + /* now back up to first path seperator or start */ fname += length; while (length) { length--; @@ -458,7 +453,7 @@ static int truename(char *dest, const char *src, int allowwildcards, /* MS DOS preserves a trailing '\\', so an access to "C:\\DOS\\" or "CDS.C\\" fails. */ /* But don't add the separator, if the last component was ".." */ - /* we must also add a separator if dest = "c:" */ + /* we must also add a seperator if dest = "c:" */ addChar('\\'); } @@ -482,7 +477,7 @@ static inline void build_ufs_path(char *ufs, const char *path, int drive) static int lfn_error(int errorcode) { _AX = errorcode; - WRITE_WORDP((unsigned char *)&_sda_error_code(sda), errorcode); + WRITE_WORDP((unsigned char *)&sda_error_code(sda), errorcode); CARRY; return 1; } @@ -492,15 +487,16 @@ static int build_truename(char *dest, const char *src, int mode) int dd = -1; int err; - d_printf("LFN: build_truename: %s\n", src); + d_printf("LFN: build_posix_path: %s\n", src); err = truename(dest, src, mode, &dd); switch (err) { case 0: break; case -DISK_DRIVE_INVALID: - if (dd >= 0 && get_redirection_root1(dd, NULL, 0) <= 0) - return -2; // valid but not our drive + assert(dd >= 0); + if (get_redirection_root1(dd, NULL, 0) <= 0) + return -2; /* no break */ default: lfn_error(-err); @@ -534,7 +530,7 @@ static int build_posix_path(char *dest, const char *src, int allowwildcards) } -/* wildcard match routine, loosely based upon the GLIBC fnmatch +/* wildcard match routine, losely based upon the GLIBC fnmatch routine */ static int recur_match(const char *pattern, const char *string) { @@ -900,7 +896,7 @@ static int mfs_lfn_(void) _CX = get_dos_attr(fpath, st.st_mode); break; case 1: /* set attributes */ - if (!(st.st_mode & S_IWUSR)) + if (!(st.st_mode & S_IWGRP)) return lfn_error(ACCESS_DENIED); /* allow changing attrs only on files, not dirs */ if (!S_ISREG(st.st_mode)) @@ -972,8 +968,7 @@ static int mfs_lfn_(void) if (lfndirs[dirhandle] == NULL) break; if (dirhandle == MAX_OPEN_DIRS) { - error("LFN: too many dirs open\n"); - leavedos(3); + d_printf("LFN: too many dirs open\n"); return lfn_error(NO_MORE_FILES); } dir = malloc(sizeof *dir); @@ -1072,7 +1067,7 @@ static int mfs_lfn_(void) char filename[PATH_MAX]; src = MK_FP32(_DS, _SI); - d_printf("LFN: truename cl=%d '%s'\n", _CL, src); + d_printf("LFN: truename %s, cl=%d\n", src, _CL); i = 0; if (src[0] && src[1] == ':') i = 2; for (; src[i]; i++) { @@ -1086,20 +1081,17 @@ static int mfs_lfn_(void) if (drive < 0) return drive + 2; + d_printf("LFN: %s\n", fpath); + if (_CL == 1 || _CL == 2) { build_ufs_path(fpath, filename, drive); if (!find_file(fpath, &st, get_redirection_root1(drive, NULL, 0), &doserrno)) return lfn_error(doserrno); make_unmake_dos_mangled_path(filename, fpath, drive, 2 - _CL); } else { - char *lastslash = strrchr(filename, '\\'); - if (lastslash) { /* Upcase but preserve the final component */ - strnupperDOS(filename, lastslash - filename); - } else if (filename[2] == '/') { /* Is a device name */ - strupperDOS(filename); - } + strupperDOS(filename); } - d_printf("LFN: truename result '%s'\n", filename); + d_printf("LFN: %s\n", filename); MEMCPY_2DOS(dest, filename, strlen(filename) + 1); break; } @@ -1168,7 +1160,7 @@ static int mfs_lfn_(void) case 0xa8: /* generate short filename */ { src = MK_FP32(_DS, _SI); - strlcpy(fpath, src, sizeof(fpath)); + StrnCpy(fpath, src, sizeof(fpath) - 1); name_convert(fpath, MANGLE); strupperDOS(fpath); if (_DH == 0) { diff --git a/src/dosext/mfs/lfn.h b/src/dosext/mfs/lfn.h index 32a8990..1d56b32 100644 --- a/src/dosext/mfs/lfn.h +++ b/src/dosext/mfs/lfn.h @@ -9,4 +9,3 @@ extern char lfn_create_fpath[PATH_MAX]; void close_dirhandles(unsigned psp); -void lfn_reset(void); diff --git a/src/dosext/mfs/mangle.c b/src/dosext/mfs/mangle.c index 304073b..645939a 100644 --- a/src/dosext/mfs/mangle.c +++ b/src/dosext/mfs/mangle.c @@ -73,13 +73,13 @@ dosaddr_t is_dos_device(const char *path) int i; int cnt; - fname = path; /* C:\DEV notation is allowed */ - if (path[1] == ':') { - fname += 2; - if (fname[0] == '\\' || fname[0] == '/') - fname++; - } + fname = strrchr(path, '\\'); + if (fname) + fname++; + else + fname = path; + /* * LPTx e.t.c. is reserved no matter the path (e.g. .\LPT1 _is_ reserved), * but mfs.c sends an entire path. @@ -173,7 +173,7 @@ static BOOL is_8_3(char *fname) This Translation may be more or less relaxed depending the Windows application. */ - /* %%% A nice improvement to name mangling would be to translate + /* %%% A nice improvment to name mangling would be to translate filename to ANSI charset on the smb server host */ { @@ -312,7 +312,7 @@ BOOL check_mangled_stack(char *s, char *MangledMap) if (p) { check_extension = True; - strlcpy(extension, p, sizeof(extension)); + StrnCpy(extension,p,4); } for (i=0;i #include #endif +#include #include #include #include +#include #include #include #include @@ -174,6 +176,12 @@ TODO: #include #include // types used for seek/size +#if !DOSEMU +#include +#include + +#include "dos.h" +#else #include #include #ifdef HAVE_LIBBSD @@ -182,6 +190,7 @@ TODO: #include #include "emu.h" #include "int.h" +#include "mfs.h" #include "lfn.h" #include "dos2linux.h" #include "doshelpers.h" @@ -193,15 +202,13 @@ TODO: #include "utilities.h" #include "coopth.h" #include "lpt.h" -#include "share.h" -#include "xattr.h" -#include "rlocks.h" -#include "mfs.h" +#endif #ifdef __linux__ #include #endif +#define Addr_8086(x,y) MK_FP32((x),(y) & 0xffff) #define Addr(s,x,y) Addr_8086(((s)->x), ((s)->y)) /* vfat_ioctl to use is short for int2f/ax=11xx, both for int21/ax=71xx */ #ifdef __linux__ @@ -246,11 +253,8 @@ static int emufs_loaded = FALSE; #define PRINTER_MODE 0x25 /* Used in DOS 3.1+ */ #define EXTENDED_ATTRIBUTES 0x2d /* Used in DOS 4.x */ #define MULTIPURPOSE_OPEN 0x2e /* Used in DOS 4.0+ */ - -#define GET_LARGE_DISK_SPACE 0xa3 /* extension */ +#define LONG_SEEK 0x42 /* extension */ #define GET_LARGE_FILE_INFO 0xa6 /* extension */ -#define LONG_SEEK 0xc2 /* extension */ - #define EOS '\0' #define SLASH '/' @@ -268,6 +272,20 @@ static int emufs_loaded = FALSE; enum {DRV_NOT_FOUND, DRV_FOUND, DRV_NOT_ASSOCIATED}; enum { TYPE_NONE, TYPE_DISK, TYPE_PRINTER }; +struct file_fd +{ + char *name; + int idx; + int fd; + int type; + int dir_fd; + struct stat st; + int is_writable; + int write_allowed; + uint64_t seek; + uint64_t size; + int lock_cnt; +}; /* Need to know how many drives are redirected */ static u_char redirected_drives = 0; @@ -284,16 +302,18 @@ static void path_to_ufs(char *ufs, size_t ufs_offset, const char *path, int PreserveEnvVar, int lowercase); static int dos_would_allow(char *fpath, const char *op, int equal); static void RemoveRedirection(int drive, cds_t cds); +static int get_dos_xattr(const char *fname); +static int set_dos_xattr(const char *fname, int attr); static int drives_initialized = FALSE; -struct file_fd open_files[MAX_OPENED_FILES]; +#define MAX_OPENED_FILES 256 +static struct file_fd open_files[MAX_OPENED_FILES]; static int num_drives = 0; lol_t lol = 0; sda_t sda; -static uint16_t lol_segment, lol_offset, sda_segment, sda_offset; -static int dosds_seg31; +static uint16_t lol_segment, lol_offset; int lol_dpbfarptr_off, lol_cdsfarptr_off, lol_last_drive_off, lol_nuldev_off, lol_njoined_off; @@ -335,6 +355,540 @@ int sdb_drive_letter_off, sdb_template_name_off, sdb_template_ext_off, sdb_file_ext_off, sdb_file_attr_off, sdb_file_time_off, sdb_file_date_off, sdb_file_st_cluster_off, sdb_file_size_off; +static int lock_set(int fd, struct flock *fl) +{ + int ret; + fl->l_pid = 0; // needed for OFD locks + fl->l_whence = SEEK_SET; + ret = fcntl(fd, F_OFD_SETLK, fl); + if (ret) { + int err = errno; + if (err != EAGAIN) + error("OFD_SETLK failed, %s\n", strerror(err)); + } + return ret; +} + +static void lock_get(int fd, struct flock *fl) +{ + int ret; + fl->l_pid = 0; // needed for OFD locks + fl->l_whence = SEEK_SET; + ret = fcntl(fd, F_OFD_GETLK, fl); + if (ret) { + error("OFD_GETLK failed, %s\n", strerror(errno)); + /* pretend nothing is locked */ + fl->l_type = F_UNLCK; + } +} + +static int downgrade_dir_lock(int dir_fd, int fd, off_t start) +{ + struct flock fl; + int err; + + fl.l_type = F_RDLCK; + fl.l_start = start; + fl.l_len = 1; + /* set read lock and remove exclusive lock */ + err = lock_set(dir_fd, &fl); + /* read lock should never fail (we put no write locks) */ + if (err) + error("MFS: read lock failed\n"); + err |= flock(dir_fd, LOCK_UN); + return err; +} + +static int do_open_dir(const char *dname, int *locked) +{ + int err; + int dir_fd = open(dname, O_RDONLY | O_DIRECTORY | O_CLOEXEC); + if (dir_fd == -1) { + error("MFS: failed to open %s: %s\n", dname, strerror(errno)); + return -1; + } + *locked = 0; + /* lock directory (OFD) to avoid races */ + err = flock(dir_fd, LOCK_EX); + if (err) + error("MFS: exclusive lock failed: %s\n", strerror(errno)); + else + *locked = 1; + return dir_fd; +} + +static struct file_fd *do_claim_fd(const char *name) +{ + int i; + struct file_fd *ret = NULL; + + for (i = 0; i < MAX_OPENED_FILES; i++) { + struct file_fd *f = &open_files[i]; + if (!f->name) { + f->name = strdup(name); + f->idx = i; + ret = f; + break; + } + } + if (!ret) { + error("MFS: too many open files\n"); + leavedos(1); + return NULL; + } + ret->dir_fd = -1; + ret->seek = 0; + ret->size = 0; + return ret; +} + +static struct file_fd *do_find_fd(const char *name) +{ + int i; + struct file_fd *ret = NULL; + + for (i = 0; i < MAX_OPENED_FILES; i++) { + struct file_fd *f = &open_files[i]; + if (f->name && strcmp(name, f->name) == 0) { + ret = f; + break; + } + } + return ret; +} + +static int file_is_opened(int dir_fd, const char *name, int *r_err) +{ + struct stat st; + struct flock fl; + int err; + + err = fstatat(dir_fd, name, &st, 0); + if (err) { + *r_err = FILE_NOT_FOUND; + return -1; + } + fl.l_type = F_WRLCK; + fl.l_start = st.st_ino; + fl.l_len = 1; + lock_get(dir_fd, &fl); + return (fl.l_type == F_UNLCK ? 0 : 1); +} + +static int do_mfs_creat(struct file_fd *f, const char *dname, + const char *fname, mode_t mode) +{ + int fd, dir_fd, err; + int locked = 0; + + dir_fd = do_open_dir(dname, &locked); + if (dir_fd == -1) + return -1; + fd = openat(dir_fd, fname, O_RDWR | O_CLOEXEC | O_CREAT | O_TRUNC, + mode); + if (fd == -1) + goto err; + err = fstat(fd, &f->st); + if (err) + goto err2; + if (locked) { + err = downgrade_dir_lock(dir_fd, fd, f->st.st_ino); + if (err) + goto err2; + } + + f->fd = fd; + f->dir_fd = dir_fd; + f->write_allowed = 1; + f->is_writable = 1; + return 0; + +err2: + unlinkat(dir_fd, fname, 0); + close(fd); +err: + close(dir_fd); + return -1; +} + +static struct file_fd *mfs_creat(char *name, mode_t mode) +{ + char *slash = strrchr(name, '/'); + struct file_fd *f; + char *fname; + int err; + if (!slash) + return NULL; + f = do_claim_fd(name); + if (!f) + return NULL; + fname = slash + 1; + *slash = '\0'; + err = do_mfs_creat(f, name, fname, mode); + *slash = '/'; + if (err) { + free(f->name); + f->name = NULL; + return NULL; + } + return f; +} + +enum { compat_lk_off = 0x100000000LL, noncompat_lk_off, denyR_lk_off, + denyW_lk_off, R_lk_off, W_lk_off }; + +static int open_compat(int fd) +{ + struct flock fl; + fl.l_type = F_WRLCK; + fl.l_start = noncompat_lk_off; + fl.l_len = 1; + lock_get(fd, &fl); + if (fl.l_type != F_UNLCK) + return -1; + fl.l_type = F_RDLCK; + fl.l_start = compat_lk_off; + fl.l_len = 1; + return lock_set(fd, &fl); +} + +static int open_share(int fd, int open_mode, int share_mode) +{ + int err; + struct flock fl; + int denyR = (share_mode == DENY_READ || share_mode == DENY_ALL); + int denyW = (share_mode == DENY_WRITE || share_mode == DENY_ALL); + /* inhibit compat mode */ + fl.l_type = F_WRLCK; + fl.l_start = compat_lk_off; + fl.l_len = 1; + lock_get(fd, &fl); + if (fl.l_type != F_UNLCK) + return -1; + if (open_mode != O_WRONLY) { + /* read mode allowed? */ + fl.l_type = F_WRLCK; + fl.l_start = denyR_lk_off; + fl.l_len = 1; + lock_get(fd, &fl); + if (fl.l_type != F_UNLCK) + return -1; + } + if (open_mode == O_WRONLY || open_mode == O_RDWR) { + /* write mode allowed? */ + fl.l_type = F_WRLCK; + fl.l_start = denyW_lk_off; + fl.l_len = 1; + lock_get(fd, &fl); + if (fl.l_type != F_UNLCK) + return -1; + } + if (denyR) { + /* denyR allowed? */ + fl.l_type = F_WRLCK; + fl.l_start = R_lk_off; + fl.l_len = 1; + lock_get(fd, &fl); + if (fl.l_type != F_UNLCK) + return -1; + } + if (denyW) { + /* denyW allowed? */ + fl.l_type = F_WRLCK; + fl.l_start = W_lk_off; + fl.l_len = 1; + lock_get(fd, &fl); + if (fl.l_type != F_UNLCK) + return -1; + } + + /* all checks passed, claim our locks */ + fl.l_type = F_RDLCK; + fl.l_start = noncompat_lk_off; + fl.l_len = 1; + err = lock_set(fd, &fl); + if (err) + return err; + if (open_mode != O_WRONLY) { + fl.l_type = F_RDLCK; + fl.l_start = R_lk_off; + fl.l_len = 1; + err = lock_set(fd, &fl); + if (err) + return err; + } + if (open_mode == O_WRONLY || open_mode == O_RDWR) { + fl.l_type = F_RDLCK; + fl.l_start = W_lk_off; + fl.l_len = 1; + err = lock_set(fd, &fl); + if (err) + return err; + } + if (denyR) { + fl.l_type = F_RDLCK; + fl.l_start = denyR_lk_off; + fl.l_len = 1; + err = lock_set(fd, &fl); + if (err) + return err; + } + if (denyW) { + fl.l_type = F_RDLCK; + fl.l_start = denyW_lk_off; + fl.l_len = 1; + err = lock_set(fd, &fl); + if (err) + return err; + } + return 0; +} + +static int file_is_ro(const char *fname, mode_t mode) +{ + int attr = get_dos_xattr(fname); + if (attr == -1) + return 0; + return !!(attr & READ_ONLY_FILE); +} + +static int do_mfs_open(struct file_fd *f, const char *dname, + const char *fname, int flags, struct stat *st, int share_mode, + int *r_err) +{ + int fd, dir_fd, err; + int is_writable = 1; + int write_requested = (flags == O_WRONLY || flags == O_RDWR); + int locked = 0; + + *r_err = ACCESS_DENIED; + dir_fd = do_open_dir(dname, &locked); + if (dir_fd == -1) + return -1; + /* try O_RDWR first, as needed by an OFD locks */ + fd = openat(dir_fd, fname, O_RDWR | O_CLOEXEC); + /* inadequate mode may return EACCES, EROFS, maybe something else, + * so don't check errno. */ + if (fd == -1 && !(st->st_mode & S_IWUSR)) { + /* if we are the file owner, we can try chmod() */ + fchmodat(dir_fd, fname, st->st_mode | S_IWUSR, 0); + fd = openat(dir_fd, fname, O_RDWR | O_CLOEXEC); + } + if (fd == -1 && !write_requested) { + /* retry with O_RDONLY, but OFD locks won't work */ + is_writable = 0; + fd = openat(dir_fd, fname, O_RDONLY | O_CLOEXEC); + } + if (fd == -1) + goto err; + if (!share_mode) + err = open_compat(fd); + else + err = open_share(fd, flags, share_mode); + if (err) { + *r_err = SHARING_VIOLATION; + goto err2; + } + if (locked) { + err = downgrade_dir_lock(dir_fd, fd, st->st_ino); + if (err) + goto err2; + } + + f->st = *st; + f->fd = fd; + f->dir_fd = dir_fd; + assert(is_writable >= write_requested); + f->write_allowed = write_requested; + f->is_writable = is_writable; + return 0; + +err2: + close(fd); +err: + close(dir_fd); + return -1; +} + +static struct file_fd *mfs_open(char *name, int flags, struct stat *st, + int share_mode, int *r_err) +{ + char *slash = strrchr(name, '/'); + struct file_fd *f; + char *fname; + int err; + if (!slash) + return NULL; + f = do_claim_fd(name); + if (!f) + return NULL; + fname = slash + 1; + *slash = '\0'; + err = do_mfs_open(f, name, fname, flags, st, share_mode, r_err); + *slash = '/'; + if (err) { + free(f->name); + f->name = NULL; + return NULL; + } + return f; +} + +static int do_mfs_unlink(const char *dname, const char *fname) +{ + int dir_fd, err, rc; + int locked = 0; + + dir_fd = do_open_dir(dname, &locked); + if (dir_fd == -1) + return -1; + rc = file_is_opened(dir_fd, fname, &err); + switch (rc) { + case -1: + close(dir_fd); + return err; + case 0: + break; + case 1: + close(dir_fd); + return ACCESS_DENIED; + } + err = unlinkat(dir_fd, fname, 0); + close(dir_fd); + if (err) + return FILE_NOT_FOUND; + return 0; +} + +static int mfs_unlink(char *name) +{ + char *slash = strrchr(name, '/'); + struct file_fd *f; + char *fname; + int err; + if (!slash) + return FILE_NOT_FOUND; + f = do_find_fd(name); + if (f) + return ACCESS_DENIED; + fname = slash + 1; + *slash = '\0'; + err = do_mfs_unlink(name, fname); + *slash = '/'; + return err; +} + +static int do_mfs_setattr(const char *dname, const char *fname, + const char *fullname, int attr) +{ + int dir_fd, err, rc; + int locked = 0; + + dir_fd = do_open_dir(dname, &locked); + if (dir_fd == -1) + return -1; + rc = file_is_opened(dir_fd, fname, &err); + switch (rc) { + case -1: + close(dir_fd); + return err; + case 0: + break; + case 1: + close(dir_fd); + return ACCESS_DENIED; + } + err = set_dos_xattr(fullname, attr); + close(dir_fd); + return err; +} + +static int mfs_setattr(char *name, int attr) +{ + char *slash = strrchr(name, '/'); + struct file_fd *f; + char *fname; + char *fullname; + int err; + if (!slash) + return FILE_NOT_FOUND; + f = do_find_fd(name); + if (f) + return ACCESS_DENIED; + fname = slash + 1; + fullname = strdup(name); + *slash = '\0'; + err = do_mfs_setattr(name, fname, fullname, attr); + *slash = '/'; + free(fullname); + return err; +} + +static int do_mfs_rename(const char *dname, const char *fname, + const char *fname2) +{ + int dir_fd, err, rc; + int locked = 0; + + dir_fd = do_open_dir(dname, &locked); + if (dir_fd == -1) + return -1; + rc = file_is_opened(dir_fd, fname, &err); + switch (rc) { + case -1: + close(dir_fd); + return err; + case 0: + break; + case 1: + close(dir_fd); + return ACCESS_DENIED; + } +#ifdef HAVE_RENAMEAT2 + err = renameat2(dir_fd, fname, -1, fname2, RENAME_NOREPLACE); + if (err && errno == EINVAL) { + error("MFS: RENAME_NOREPLACE unsupported here\n"); + err = access(fname2, F_OK); + if (err) // err means no file + err = renameat(dir_fd, fname, -1, fname2); + } +#else + err = access(fname2, F_OK); + if (err) // err means no file + err = renameat(dir_fd, fname, -1, fname2); +#endif + close(dir_fd); + if (err) + return (errno == EEXIST ? ACCESS_DENIED : FILE_NOT_FOUND); + return 0; +} + +static int mfs_rename(char *name, char *name2) +{ + char *slash = strrchr(name, '/'); + struct file_fd *f; + char *fname; + int err; + if (!slash) + return FILE_NOT_FOUND; + f = do_find_fd(name); + if (f) + return ACCESS_DENIED; + fname = slash + 1; + *slash = '\0'; + err = do_mfs_rename(name, fname, name2); + *slash = '/'; + return err; +} + +static void mfs_close(struct file_fd *f) +{ + close(f->fd); + close(f->dir_fd); + free(f->name); + f->name = NULL; +} + static char *cds_flags_to_str(uint16_t flags) { static char s[5 * 8 + 1]; // 5 names * maxstrlen + terminator; int len = 0; @@ -413,8 +967,6 @@ static const char *redirector_op_to_str(uint8_t op) { if (op == LONG_SEEK) return "Long seek (extension)"; - else if (op == GET_LARGE_DISK_SPACE) - return "Get large disk space (extension)"; else if (op == GET_LARGE_FILE_INFO) return "Get large file info (extension)"; else if (op > MULTIPURPOSE_OPEN) @@ -601,7 +1153,7 @@ select_drive(struct vm86_regs *state, int *drive) case LOCK_UNLOCK_FILE_REGION: /* 0xa */ case UNLOCK_FILE_REGION_OLD: /* 0xb */ case SEEK_FROM_EOF: /* 0x21 */ - case LONG_SEEK: /* 0xc2 */ + case LONG_SEEK: /* 0x42 */ case GET_LARGE_FILE_INFO: /* 0xa6 */ { sft_t sft = (u_char *) Addr(state, es, edi); @@ -612,7 +1164,6 @@ select_drive(struct vm86_regs *state, int *drive) /* CDS in ES:DI */ case GET_DISK_SPACE: /* 0xc */ - case GET_LARGE_DISK_SPACE: /* 0xa3 */ { cds_t esdi_cds = (cds_t) Addr(state, es, edi); @@ -620,6 +1171,7 @@ select_drive(struct vm86_regs *state, int *drive) } break; + case FIND_NEXT: /* 0x1c */ { /* check the drive letter in the findfirst block which is in the DTA */ @@ -664,6 +1216,92 @@ static int fd_on_fat(int fd) } #endif +#define XATTR_DOSATTR_NAME "user.DOSATTRIB" +#define XATTR_ATTRIBS_MASK (READ_ONLY_FILE | HIDDEN_FILE | SYSTEM_FILE | \ + ARCHIVE_NEEDED) + +static int do_extr_xattr(const char *xbuf, ssize_t size, const char *name) +{ + if (size == -1 && errno == ENOTSUP) { + error("MFS: failed to get xattrs for %s, unsupported!\n", name); + return -1; + } + if (size <= 2 || strncmp(xbuf, "0x", 2) != 0) + return -1; + return strtol(xbuf + 2, NULL, 16) & XATTR_ATTRIBS_MASK; +} + +static int get_dos_xattr(const char *fname) +{ + char xbuf[16]; + ssize_t size = getxattr(fname, XATTR_DOSATTR_NAME, xbuf, sizeof(xbuf) - 1); + /* some dosemus forgot \0 so we fix it up here */ + if (size > 0 && xbuf[size - 1] != '\0') { + error("MFS: fixup xattr for %s\n", fname); + xbuf[size++] = '\0'; + setxattr(fname, XATTR_DOSATTR_NAME, xbuf, size, XATTR_REPLACE); + } + return do_extr_xattr(xbuf, size, fname); +} + +static int get_dos_xattr_fd(int fd, const char *name) +{ + char xbuf[16]; + ssize_t size = fgetxattr(fd, XATTR_DOSATTR_NAME, xbuf, sizeof(xbuf) - 1); + /* some dosemus forgot \0 so we fix it up here */ + if (size > 0 && xbuf[size - 1] != '\0') { + error("MFS: fixup xattr\n"); + xbuf[size++] = '\0'; + fsetxattr(fd, XATTR_DOSATTR_NAME, xbuf, size, XATTR_REPLACE); + } + return do_extr_xattr(xbuf, size, name); +} + +static int xattr_str(char *xbuf, int xsize, int attr) +{ + int ret = snprintf(xbuf, xsize, "0x%x", attr & XATTR_ATTRIBS_MASK); + assert(ret > 0); + return (ret + 1); // include '\0' +} + +static int xattr_err(int err, const char *name) +{ + if (err) { + error("MFS: failed to set xattrs for %s: %s\n", name, strerror(errno)); +// leavedos(5); + return ACCESS_DENIED; + } + return 0; +} + +static int set_dos_xattr(const char *fname, int attr) +{ + char xbuf[16]; + int err = setxattr(fname, XATTR_DOSATTR_NAME, xbuf, + xattr_str(xbuf, sizeof(xbuf), attr), 0); + if (err) { + struct stat st; + err = stat(fname, &st); + if (err) + return FILE_NOT_FOUND; + if (!(st.st_mode & S_IWUSR)) { + err = chmod(fname, st.st_mode | S_IWUSR); + if (err) + return ACCESS_DENIED; + err = setxattr(fname, XATTR_DOSATTR_NAME, xbuf, + xattr_str(xbuf, sizeof(xbuf), attr), 0); + } + } + return xattr_err(err, fname); +} + +static int set_dos_xattr_fd(int fd, int attr, const char *name) +{ + char xbuf[16]; + return xattr_err(fsetxattr(fd, XATTR_DOSATTR_NAME, xbuf, + xattr_str(xbuf, sizeof(xbuf), attr), 0), name); +} + static int get_attr_simple(int mode) { int attr = 0; @@ -723,7 +1361,7 @@ static int get_dos_attr_fd(int fd, int mode, const char *name) static int get_unix_attr(int attr) { - int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; + int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; /* Do not make directories read-only as this has completely different semantics in DOS (mostly ignore) than in Unix. Also do not reflect the archive bit as clearing the x bit as that @@ -746,8 +1384,10 @@ int set_dos_attr(char *fpath, int attr) { #ifdef __linux__ int fd = -1; +#endif int res; +#ifdef __linux__ if (fpath && file_on_fat(fpath)) fd = open(fpath, O_RDONLY); if (fd != -1) { @@ -881,25 +1521,17 @@ init_all_drives(void) init_one_drive(dd); } -void mfs_done(void) -{ - int i; - - for (i = 0; i < MAX_OPENED_FILES; i++) { - struct file_fd *f = &open_files[i]; - if (f->name) - mfs_close(f); - } -} - void mfs_reset(void) { - lfn_reset(); - mfs_done(); + int process_mask; emufs_loaded = FALSE; mfs_enabled = FALSE; init_all_drives(); + process_mask = umask(0); + /* we need all group perms */ + process_mask &= ~S_IRWXG; + umask(process_mask); } int mfs_define_drive(const char *path) @@ -969,12 +1601,13 @@ int mfs_redirector(struct vm86_regs *regs, char *stk, int revect) Debug0((dbg_fd, "Finished dos_fs_redirect\n")); regs->eflags &= ~CF; return 1; + case UNCHANGED: + return 1; case REDIRECT: if (!revect) { Debug0((dbg_fd, "dos_fs_redirect unhandled, failing\n")); regs->eflags |= CF; SETWORD(®s->eax, FORMAT_INVALID); - return 1; } return 0; } @@ -1024,8 +1657,7 @@ void extract_filename(const char *filename, char *name, char *ext) } memcpy(name, filename, _min(8, slen)); - if (dot_pos) { - dot_pos++; + if (dot_pos++) { size_t elen = strlen(dot_pos); memcpy(ext, dot_pos, _min(3, elen)); } @@ -1193,7 +1825,7 @@ static struct dir_list *get_dir_ff(char *name, char *mname, char *mext, /* DANG_BEGIN_REMARK * * Added compares to device so that newer versions of Foxpro which test directories - * using xx\yy\device perform closer to what DOS does. + * using xx\yy\device perform closer to whats DOS does. * * DANG_END_REMARK */ @@ -1668,10 +2300,6 @@ dos_fs_dev(struct vm86_regs *state) /* init some global vars */ lol_segment = WORD(state->ecx); lol_offset = WORD(state->edx); - sda_segment = WORD(state->esi); - sda_offset = WORD(state->edi); - /* Some DOSes store DOS_DS in int31's segment */ - dosds_seg31 = (sda_segment == ISEG(0x31)); break; /* Let the caller know the redirector has been initialised and that we @@ -1918,9 +2546,7 @@ int find_file(char *fpath, struct stat * st, int root_len, int *doserrno) } /* first see if the path exists as is */ - if (lstat(fpath, st) == 0) { - /* get data about an actual file, unless dangling symlink */ - stat(fpath, st); + if (stat(fpath, st) == 0) { Debug0((dbg_fd, "file exists as is\n")); return (TRUE); } @@ -1983,11 +2609,10 @@ int find_file(char *fpath, struct stat * st, int root_len, int *doserrno) } /* we've found the file - now stat it */ - if (lstat(fpath, st) != 0) { + if (stat(fpath, st) != 0) { Debug0((dbg_fd, "find_file(): can't stat %s\n", fpath)); return (FALSE); } - stat(fpath, st); Debug0((dbg_fd, "found file %s\n", fpath)); return (TRUE); @@ -2174,7 +2799,7 @@ static inline void hlist_pop(int indx, unsigned psp) --se); hlists.tos = se - hlists.stack + 1; - Debug0((dbg_fd, "hlist_pop: %d popped=%d PSP=%d\n", + Debug0((dbg_fd, "hlist_pop: %d poped=%d PSP=%d\n", hlists.tos, indx, psp)); } @@ -2220,7 +2845,7 @@ static inline void hlist_watch_pop(unsigned psp) continue; if (se->seq < 0) { - se_del = NULL; /* we have found a gap, it is not necessary ... */ + se_del = NULL; /* we have found a gap, it is not neccessary ... */ break; } @@ -2392,7 +3017,7 @@ static int GetRedirection(struct vm86_regs *state, int rSize, int subfunc) } } #if 0 - /* if we don't own this index, pass down */ + /* if we dont own this index, pass down */ redirected_drives = WORD(state->ebx) - index; SETWORD(&state->ebx, index); Debug0((dbg_fd, "GetRedirect passing index of %d, Total redirected=%d\n", index, redirected_drives)); @@ -2791,6 +3416,42 @@ CancelRedirection(struct vm86_regs *state) return TRUE; } +static int lock_file_region(int fd, int lck, long long start, + unsigned long len) +{ + struct flock fl; + + /* make data visible before releasing the lock */ + if (!lck) + dos_flush(fd); + +#ifdef F_GETLK64 // 64bit locks are promoted automatically (e.g. glibc) + static_assert(sizeof(struct flock) == sizeof(struct flock64), "incompatible flock64"); + + Debug0((dbg_fd, "Large file locking start=%llx, len=%lx\n", start, len)); +#else // 32bit locking only +#error 64bit locking not supported +#endif + + fl.l_type = (lck ? F_WRLCK : F_UNLCK); + fl.l_start = start; + fl.l_len = len; + return lock_set(fd, &fl); +} + +static int region_lock_offs(int fd, long long start, unsigned long len) +{ + struct flock fl; + + fl.l_type = F_WRLCK; + fl.l_start = start; + fl.l_len = len; + lock_get(fd, &fl); + if (fl.l_type == F_UNLCK) + return len; + return (fl.l_start - start); +} + /* returns pointer to the basename of fpath */ static char *getbasename(char *fpath) { @@ -2825,16 +3486,16 @@ static void open_device(unsigned int devptr, char *fname, sft_t sft) unsigned char *dev = MK_FP32(FP_SEG16(devptr), FP_OFF16(devptr)); memcpy(sft_name(sft), fname, 8); memset(sft_ext(sft), ' ', 3); - _sft_dev_drive_ptr(sft) = devptr; - _sft_directory_entry(sft) = 0; - _sft_directory_sector(sft) = 0; - _sft_attribute_byte(sft) = 0x40; - _sft_device_info(sft) = + sft_dev_drive_ptr(sft) = devptr; + sft_directory_entry(sft) = 0; + sft_directory_sector(sft) = 0; + sft_attribute_byte(sft) = 0x40; + sft_device_info(sft) = ((dev[4] | dev[5] << 8) & ~SFT_MASK) | SFT_FDEVICE | SFT_FEOF; - time_to_dos(time(NULL), &_sft_date(sft), &_sft_time(sft)); - _sft_size(sft) = 0; - _sft_position(sft) = 0; + time_to_dos(time(NULL), &sft_date(sft), &sft_time(sft)); + sft_size(sft) = 0; + sft_position(sft) = 0; } /* In any Linux directory it is possible to have uids not equal @@ -2862,14 +3523,6 @@ static int dos_would_allow(char *fpath, const char *op, int equal) return TRUE; } -static void set_32bit_size_or_position(uint32_t* sftfield, uint64_t fullvalue) { - if (fullvalue < 0x100000000) { - *sftfield = fullvalue; - } else { - *sftfield = 0xFFFFffff; - } -} - static int find_again(int firstfind, int drive, char *fpath, struct dir_list *hlist, struct vm86_regs *state, sdb_t sdb) { @@ -2881,10 +3534,10 @@ static int find_again(int firstfind, int drive, char *fpath, while (sdb_dir_entry(sdb) < hlist->nr_entries) { de = &hlist->de[sdb_dir_entry(sdb)]; - _sdb_dir_entry(sdb)++; + sdb_dir_entry(sdb)++; Debug0((dbg_fd, "find_again entered with %.8s.%.3s\n", de->name, de->ext)); fill_entry(de, fpath, drive); - _sdb_file_attr(sdb) = de->attr; + sdb_file_attr(sdb) = de->attr; if (de->mode & S_IFDIR) { Debug0((dbg_fd, "Directory ---> YES 0x%x\n", de->mode)); @@ -2897,14 +3550,14 @@ static int find_again(int firstfind, int drive, char *fpath, /* Path is long, so we do not allow subdirectories here. Instead return the entry as a regular file. */ - _sdb_file_attr(sdb) &= ~DIRECTORY; + sdb_file_attr(sdb) &= ~DIRECTORY; de->size = 0; /* fake empty file */ } } time_to_dos(de->time, - &_sdb_file_date(sdb), - &_sdb_file_time(sdb)); - set_32bit_size_or_position(&_sdb_file_size(sdb), de->size); + &sdb_file_date(sdb), + &sdb_file_time(sdb)); + sdb_file_size(sdb) = de->size; strncpy(sdb_file_name(sdb), de->name, 8); strncpy(sdb_file_ext(sdb), de->ext, 3); @@ -3015,7 +3668,7 @@ int dos_mkdir(const char *filename1, int drive, int lfn) fpath)); return ACCESS_DENIED; } - if (mkdir(fpath, 0755) != 0) { + if (mkdir(fpath, 0775) != 0) { find_dir(fpath, drive); Debug0((dbg_fd, "trying '%s'\n", fpath)); if (mkdir(fpath, 0755) != 0) { @@ -3148,6 +3801,14 @@ static u_short unix_access_mode(struct stat *st, int drive, u_short dos_mode) return unix_mode; } +static void set_32bit_size_or_position(uint32_t* sftfield, uint64_t fullvalue) { + if (fullvalue < 0x100000000) { + *sftfield = fullvalue; + } else { + *sftfield = 0xFFFFffff; + } +} + static void do_update_sft(struct file_fd *f, char *fname, char *fext, sft_t sft, int drive, u_char attr, u_short FCBcall, int existing) { @@ -3156,27 +3817,27 @@ static void do_update_sft(struct file_fd *f, char *fname, char *fext, if (!existing) { if (FCBcall) - _sft_open_mode(sft) |= 0x00f0; + sft_open_mode(sft) |= 0x00f0; else #if 0 - _sft_open_mode(sft) = 0x3; /* write only */ + sft_open_mode(sft) = 0x3; /* write only */ #else - _sft_open_mode(sft) = 0x2; /* read/write */ + sft_open_mode(sft) = 0x2; /* read/write */ #endif } - _sft_directory_entry(sft) = 0; - _sft_directory_sector(sft) = 0; - _sft_attribute_byte(sft) = attr; - _sft_device_info(sft) = (drive & 0x1f) | 0x0940 | SFT_FSHARED; + sft_directory_entry(sft) = 0; + sft_directory_sector(sft) = 0; + sft_attribute_byte(sft) = attr; + sft_device_info(sft) = (drive & 0x1f) | 0x0940 | SFT_FSHARED; if (f->type == TYPE_DISK) { - time_to_dos(f->st.st_mtime, &_sft_date(sft), &_sft_time(sft)); + time_to_dos(f->st.st_mtime, &sft_date(sft), &sft_time(sft)); f->size = f->st.st_size; - set_32bit_size_or_position(&_sft_size(sft), f->size); + set_32bit_size_or_position(&sft_size(sft), f->size); } f->seek = 0; - _sft_position(sft) = 0; - _sft_fd(sft) = f->idx; + sft_position(sft) = 0; + sft_fd(sft) = f->idx; } static void update_seek_from_dos(uint32_t seek_from_dos, uint64_t* p_seek) { @@ -3203,6 +3864,7 @@ static struct file_fd *do_open_prn(const char *filename1, const char *fpath) return NULL; f = do_claim_fd(fpath); f->fd = fd; + f->dir_fd = -1; f->type = TYPE_PRINTER; return f; } @@ -3258,21 +3920,6 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) Debug0((dbg_fd, "Entering dos_fs_redirect, FN=%02X, '%s'\n", (int)LOW(state->eax), redirector_op_to_str(LOW(state->eax)))); - /* - * We need to update the pointers here as some variants of DOS move it - * during the boot process. - * e.g. EDR-DOS 7.01.07+ - */ - if (dosds_seg31 && sda_segment != ISEG(0x31)) { - uint16_t dosdataseg = ISEG(0x31); - Debug0((dbg_fd, "EDR-DOS work-around: sda 0x%x --> 0x%x\n", - sda_segment, dosdataseg)); - lol = SEGOFF2LINEAR(dosdataseg, lol_offset); - sda = MK_FP32(dosdataseg, sda_offset); - lol_segment = dosdataseg; - sda_segment = dosdataseg; - } - if (select_drive(state, &drive) == DRV_NOT_FOUND) return REDIRECT; @@ -3355,7 +4002,7 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) Debug0((dbg_fd, "Close file %x (%s)\n", f->fd, filename1)); Debug0((dbg_fd, "Handle cnt %d\n", sft_handle_cnt(sft))); - _sft_handle_cnt(sft)--; + sft_handle_cnt(sft)--; if (sft_handle_cnt(sft) > 0) { Debug0((dbg_fd, "Still more handles\n")); return TRUE; @@ -3391,8 +4038,6 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) case READ_FILE: { /* 0x08 */ int return_val; - int locked = 0; - cnt = sft_fd(sft); if (cnt >= MAX_OPENED_FILES) return FALSE; @@ -3407,54 +4052,32 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) cnt = WORD(state->ecx); if (cnt) { int cnt1 = cnt; - if (!region_is_fully_owned(f->fd, f->seek, cnt, 0, f->mlemu_fds[1]) && - f->seek <= 0xFFFFffff && f->seek + cnt <= 0xFFFFffff) { -#if 1 - /* Since we know the region is not fully locked by us (owned), - * we pretend to be a writer, even if we are a reader. - * This makes sure other's read locks inhibit our unlocked reads. - * Quite silly but is needed to pass some DOS compat tests. */ - int am_i_writer = 1; -#else - int am_i_writer = 0; -#endif - cnt1 = region_lock_offs(f->fd, f->seek, cnt, am_i_writer); - if (cnt1 > 0) - locked = 1; + if (f->seek <= 0xFFFFffff && f->seek + cnt <= 0xFFFFffff) { + cnt1 = region_lock_offs(f->fd, f->seek, cnt); } assert(cnt1 <= cnt); #if 1 - if (cnt1 == 0) { // allow partial reads even though DOS does not + if (cnt1 <= 0) { // allow partial reads even though DOS does not #else - if (cnt1 != -1 && cnt1 < cnt) { // partial reads not allowed - if (locked) { - region_unlock_offs(f->fd); - locked = 0; - } + if (cnt1 < cnt) { // partial reads not allowed #endif - assert(!locked); Debug0((dbg_fd, "error, region already locked\n")); SETWORD(&state->eax, ACCESS_DENIED); return FALSE; } - if (cnt1 != -1) - cnt = cnt1; + cnt = cnt1; } Debug0((dbg_fd, "Read file fd=%d, dta=%#x, cnt=%d\n", f->fd, dta, cnt)); Debug0((dbg_fd, "Read file pos = %"PRIu64"\n", f->seek)); Debug0((dbg_fd, "Handle cnt %d\n", sft_handle_cnt(sft))); s_pos = lseek(f->fd, f->seek, SEEK_SET); if (s_pos < 0 && errno != ESPIPE) { - if (locked) - region_unlock_offs(f->fd); SETWORD(&state->ecx, 0); return TRUE; } Debug0((dbg_fd, "Actual pos %"PRIu64"\n", (uint64_t)s_pos)); ret = dos_read(f->fd, dta, cnt); - if (locked) - region_unlock_offs(f->fd); Debug0((dbg_fd, "Read returned : %d\n", ret)); if (ret < 0) { @@ -3468,12 +4091,12 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) return_val = TRUE; } f->seek += ret; - set_32bit_size_or_position(&_sft_position(sft), f->seek); + set_32bit_size_or_position(&sft_position(sft), f->seek); if (ret + s_pos > sft_size(sft)) { /* someone else enlarged the file! refresh. */ fstat(f->fd, &f->st); f->size = f->st.st_size; - set_32bit_size_or_position(&_sft_size(sft), f->size); + set_32bit_size_or_position(&sft_size(sft), f->size); } // sft_abs_cluster(sft) = 0x174a; /* XXX a test */ /* Debug0((dbg_fd, "File data %02x %02x %02x\n", dta[0], dta[1], dta[2])); */ @@ -3481,14 +4104,12 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) return (return_val); } - case WRITE_FILE: { /* 0x09 */ - int locked = 0; - + case WRITE_FILE: /* 0x09 */ cnt = sft_fd(sft); if (cnt >= MAX_OPENED_FILES) return FALSE; f = &open_files[cnt]; - if (f->name == NULL || read_only(drives[drive])) { + if (f->name == NULL || read_only(drives[drive]) || !f->write_allowed) { SETWORD(&state->eax, ACCESS_DENIED); return FALSE; } @@ -3513,38 +4134,27 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) return FALSE; } f->size = f->seek; - set_32bit_size_or_position(&_sft_size(sft), f->size); + set_32bit_size_or_position(&sft_size(sft), f->size); SETWORD(&state->ecx, 0); } else { int cnt1 = cnt; - if (!region_is_fully_owned(f->fd, f->seek, cnt, 1, f->mlemu_fds[1]) && - f->seek <= 0xFFFFffff && f->seek + cnt <= 0xFFFFffff) { - cnt1 = region_lock_offs(f->fd, f->seek, cnt, 1); - if (cnt1 > 0) - locked = 1; + if (f->seek <= 0xFFFFffff && f->seek + cnt <= 0xFFFFffff) { + cnt1 = region_lock_offs(f->fd, f->seek, cnt); } assert(cnt1 <= cnt); #if 1 - if (cnt1 == 0) { // allow partial writes even though DOS does not + if (cnt1 <= 0) { // allow partial writes even though DOS does not #else - if (cnt1 != -1 && cnt1 < cnt) { // partial writes not allowed - if (locked) { - region_unlock_offs(f->fd); - locked = 0; - } + if (cnt1 < cnt) { // partial writes not allowed #endif - assert(!locked); Debug0((dbg_fd, "error, region already locked\n")); SETWORD(&state->eax, ACCESS_DENIED); return FALSE; } - if (cnt1 != -1) - cnt = cnt1; + cnt = cnt1; s_pos = lseek(f->fd, f->seek, SEEK_SET); if (s_pos < 0 && errno != ESPIPE) { - if (locked) - region_unlock_offs(f->fd); SETWORD(&state->ecx, 0); return TRUE; } @@ -3552,19 +4162,16 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) Debug0((dbg_fd, "fsize = %"PRIx64", fseek = %"PRIx64", dta = %#x, cnt = %x\n", f->size, f->seek, dta, (int)cnt)); ret = dos_write(f->fd, dta, cnt); - if (locked) - region_unlock_offs(f->fd); - if (ret < 0) { Debug0((dbg_fd, "Write Failed : %s\n", strerror(errno))); SETWORD(&state->eax, ACCESS_DENIED); return FALSE; } f->seek += ret; - set_32bit_size_or_position(&_sft_position(sft), f->seek); + set_32bit_size_or_position(&sft_position(sft), f->seek); if ((ret + s_pos) > f->size) { f->size = ret + s_pos; - set_32bit_size_or_position(&_sft_size(sft), f->size); + set_32bit_size_or_position(&sft_size(sft), f->size); } Debug0((dbg_fd, "write operation done,ret=%x\n", ret)); Debug0((dbg_fd, "fseek=%"PRIu64", fsize=%"PRIu64"\n", f->seek, f->size)); @@ -3573,9 +4180,8 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) // sft_abs_cluster(sft) = 0x174a; /* XXX a test */ /* update stat for atime/mtime */ if (fstat(f->fd, &f->st) == 0) - time_to_dos(f->st.st_mtime, &_sft_date(sft), &_sft_time(sft)); + time_to_dos(f->st.st_mtime, &sft_date(sft), &sft_time(sft)); return TRUE; - } case GET_DISK_SPACE: { /* 0x0c */ #ifdef USE_DF_AND_AFS_STUFF @@ -3615,8 +4221,7 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) free = 65535; /* Ralf Brown says: AH=media ID byte - can we let it at 0 here? */ - SETLOW(&state->eax, spc); - SETHIGH(&state->eax, 0); + SETWORD(&state->eax, spc); SETWORD(&state->edx, free); SETWORD(&state->ecx, bps); SETWORD(&state->ebx, tot); @@ -3633,52 +4238,6 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) break; } - case GET_LARGE_DISK_SPACE: /* 0xa3 */ - { - cds_t tcds = Addr(state, es, edi); - char *name = cds_current_path(tcds); - uint64_t avail, total; - uint16_t blocksize; - int dd; - struct statfs fsbuf; - - Debug0((dbg_fd, "Get Large Disk Space(INT2F/11a3)\n")); - - if (!get_drive_from_path(name, &dd)) { - Debug0((dbg_fd, "Bad drive name '%s'\n", name)); - break; - } - - if (!drives[dd].root) { - Debug0((dbg_fd, "Drive not ours\n")); - break; - } - - if (statfs(drives[dd].root, &fsbuf) == -1) { - Debug0((dbg_fd, "Can't stat root path '%s'\n", strerror(errno))); - SETWORD(&state->eax, DISK_DRIVE_INVALID); - return FALSE; - } - - blocksize = 512; - total = (fsbuf.f_blocks * fsbuf.f_bsize) / blocksize; - avail = (fsbuf.f_bavail * fsbuf.f_bsize) / blocksize; - if (total > 0xffffffff) // Clamp to 2TB (with 512 byte blocks) - total = 0xffffffff; - if (avail > 0xffffffff) - avail = 0xffffffff; - - SETWORD(&state->eax, (total >> 16) & 0xffff); - SETWORD(&state->ebx, (total) & 0xffff); - SETWORD(&state->ecx, (avail >> 16) & 0xffff); - SETWORD(&state->edx, (avail) & 0xffff); - SETWORD(&state->esi, blocksize); - - Debug0((dbg_fd, "total blocks=%" PRIu64 ", free blocks=%" PRIu64 ", blocksize=%u\n", total, avail, blocksize)); - - return TRUE; - } - case SET_FILE_ATTRIBUTES: { /* 0x0e */ struct stat st; u_short att = *(u_short *)stk; @@ -3805,10 +4364,10 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) } cnt = strlen(fpath); + fpath[cnt++] = SLASH; de = &dir_list->de[0]; for (i = 0; i < dir_list->nr_entries; i++, de++) { - if ((de->mode & S_IFMT) == S_IFREG || (de->mode & S_IFMT) == S_IFLNK || - (de->mode & S_IFMT) == 0) { + if ((de->mode & S_IFMT) == S_IFREG) { struct stat st; strcpy(fpath + cnt, de->d_name); if (find_file(fpath, &st, drives[drive].root_len, NULL)) { @@ -3844,16 +4403,16 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk) appendix, I can find nothing else which supports this statement. */ dos_mode = *(u_short *)stk; /* check for a high bit set indicating an FCB call */ - FCBcall = _sft_open_mode(sft) & 0x8000; + FCBcall = sft_open_mode(sft) & 0x8000; Debug0((dbg_fd, "(mode = 0x%04x)\n", dos_mode)); Debug0((dbg_fd, "(sft_open_mode = 0x%04x)\n", sft_open_mode(sft))); if (FCBcall) { - _sft_open_mode(sft) |= 0x00f0; + sft_open_mode(sft) |= 0x00f0; } else { /* Keeping sharing modes in sft also, --Maxim Ruchko */ - _sft_open_mode(sft) = dos_mode & 0xff; + sft_open_mode(sft) = dos_mode & 0xff; } /* This method is ALSO in undoc dos. They have the command @@ -3894,7 +4453,7 @@ do_open_existing: SETWORD(&state->eax, FILE_NOT_FOUND); return (FALSE); } - if (dos_mode != READ_ACC && file_is_ro(fpath)) { + if (dos_mode != READ_ACC && file_is_ro(fpath, st.st_mode)) { SETWORD(&state->eax, ACCESS_DENIED); return (FALSE); } @@ -3905,13 +4464,12 @@ do_open_existing: } if (!(f = mfs_open(fpath, unix_access_mode(&st, drive, dos_mode), - share_mode, &doserrno))) { + &st, share_mode, &doserrno))) { Debug0((dbg_fd, "access denied:'%s' (dm=%x %x)\n", fpath, dos_mode, doserrno)); SETWORD(&state->eax, doserrno); return FALSE; } - f->st = st; f->type = TYPE_DISK; do_update_sft(f, fname, fext, sft, drive, get_dos_attr(fpath, st.st_mode), FCBcall, 1); @@ -3923,6 +4481,7 @@ do_open_existing: if (FCBcall) { Debug0((dbg_fd, "FCB Open calling int2f 0x120c\n")); fake_call_to(FCB_HLP_SEG, FCB_HLP_OFF); + return UNCHANGED; } return TRUE; @@ -3942,8 +4501,8 @@ do_open_existing: /* make it a byte - we thus ignore the new bit */ attr &= 0xFF; - if (attr & (DIRECTORY | VOLUME_LABEL)) - return FALSE; + if (attr & DIRECTORY) + return REDIRECT; Debug0((dbg_fd, "Create truncate file %s attr=%x\n", filename1, attr)); build_ufs_path(fpath, filename1, drive); @@ -3986,6 +4545,7 @@ do_create_truncate: fext[0] = 0; f = do_claim_fd(fpath); f->fd = fd; + f->dir_fd = -1; f->type = TYPE_PRINTER; } else { struct stat st; @@ -4018,7 +4578,6 @@ do_create_truncate: return FALSE; } } - fstat(f->fd, &f->st); f->type = TYPE_DISK; #ifdef __linux__ if (file_on_fat(fpath)) @@ -4037,6 +4596,7 @@ do_create_truncate: if (FCBcall) { Debug0((dbg_fd, "FCB Open calling int2f 0x120c\n")); fake_call_to(FCB_HLP_SEG, FCB_HLP_OFF); + return UNCHANGED; } return TRUE; @@ -4058,11 +4618,11 @@ do_create_truncate: build_ufs_path(fpath, filename1, drive); auspr(filename1, fname, fext); - memcpy(_sdb_template_name(sdb), fname, 8); - memcpy(_sdb_template_ext(sdb), fext, 3); - _sdb_attribute(sdb) = attr; - _sdb_drive_letter(sdb) = 0x80 + drive; - _sdb_p_cluster(sdb) = 0xffff; /* correct value later */ + memcpy(sdb_template_name(sdb), fname, 8); + memcpy(sdb_template_ext(sdb), fext, 3); + sdb_attribute(sdb) = attr; + sdb_drive_letter(sdb) = 0x80 + drive; + sdb_p_cluster(sdb) = 0xffff; /* correct value later */ Debug0((dbg_fd, "Find first %8.8s.%3.3s\n", sdb_template_name(sdb), sdb_template_ext(sdb))); @@ -4070,11 +4630,14 @@ do_create_truncate: strncmp(sdb_template_name(sdb), "????????", 8) == 0 && strncmp(sdb_template_ext(sdb), "???", 3) == 0) { get_volume_label(fname, fext, NULL, drive); - memcpy(_sdb_file_name(sdb), fname, 8); - memcpy(_sdb_file_ext(sdb), fext, 3); - _sdb_file_attr(sdb) = VOLUME_LABEL; - _sdb_dir_entry(sdb) = 0x0; - return TRUE; + memcpy(sdb_file_name(sdb), fname, 8); + memcpy(sdb_file_ext(sdb), fext, 3); + sdb_file_attr(sdb) = VOLUME_LABEL; + sdb_dir_entry(sdb) = 0x0; + + /* We fill the hlist for labels not here, + * we do it a few lines later. --ms + */ } bs_pos = getbasename(fpath); @@ -4095,12 +4658,22 @@ do_create_truncate: set_long_path_on_dirs(hlist); } hlist_index = hlist_push(hlist, sda_cur_psp(sda), fpath); - _sdb_dir_entry(sdb) = 0; - _sdb_p_cluster(sdb) = hlist_index; + sdb_dir_entry(sdb) = 0; + sdb_p_cluster(sdb) = hlist_index; hlists.stack[hlist_index].seq = ++hlists.seq; /* new watch stamp --ms */ hlist_set_watch(sda_cur_psp(sda)); + /* + * This is the right place to leave this stuff for volume labels. --ms + */ + if (((attr & (VOLUME_LABEL | DIRECTORY)) == VOLUME_LABEL) && + strncmp(sdb_template_name(sdb), "????????", 8) == 0 && + strncmp(sdb_template_ext(sdb), "???", 3) == 0) { + Debug0((dbg_fd, "DONE LABEL!!\n")); + + return TRUE; + } return find_again(1, drive, fpath, hlist, state, sdb); } @@ -4160,9 +4733,9 @@ do_create_truncate: off_t new_pos = offset + f->st.st_size; /* update file size in case other process changed it */ f->seek = new_pos; - set_32bit_size_or_position(&_sft_position(sft), f->seek); + set_32bit_size_or_position(&sft_position(sft), f->seek); f->size = f->st.st_size; - set_32bit_size_or_position(&_sft_size(sft), f->size); + set_32bit_size_or_position(&sft_size(sft), f->size); SETWORD(&state->edx, sft_position(sft) >> 16); SETWORD(&state->eax, WORD(sft_position(sft))); return TRUE; @@ -4179,7 +4752,7 @@ do_create_truncate: char *dst = (char *)Addr(state, es, edi); char *slash; if (drive > PRINTER_BASE_DRIVE && drive < MAX_DRIVES) { - snprintf(dst, 128, "%s\\%s", LINUX_PRN_RESOURCE, drives[drive].root); + sprintf(dst, "%s\\%s", LINUX_PRN_RESOURCE, drives[drive].root); Debug0((dbg_fd, "Qualify Filename: %s -> %s\n", name, dst)); return TRUE; } @@ -4217,8 +4790,8 @@ do_create_truncate: Debug0((dbg_fd, "lock requested, fd=%d, is_lock=%d, start=%lx, len=%lx\n", f->fd, is_lock, (long)pt->offset, (long)pt->size)); - if (f->name == NULL) { - Debug0((dbg_fd, "file not found, corrupted sft?\n")); + if (f->name == NULL || !f->is_writable) { + Debug0((dbg_fd, "file not writable, lock failed.\n")); SETWORD(&state->eax, ACCESS_DENIED); return FALSE; } @@ -4241,8 +4814,7 @@ do_create_truncate: if ((start & mask) != 0) start = (start & ~mask) | ((start & mask) >> 2); - ret = lock_file_region(f->fd, is_lock, start, pt->size & ~mask, - f->is_writable, f->mlemu_fds[0]); + ret = lock_file_region(f->fd, is_lock, start, pt->size & ~mask); if (ret == 0) { /* locks can be coalesced so the single unlock resets the counter */ if (is_lock) @@ -4264,7 +4836,7 @@ do_create_truncate: hlist_pop_psp(state->ds); if (config.lfn) close_dirhandles(state->ds); - return TRUE; + return REDIRECT; case CONTROL_REDIRECT: { /* 0x1e */ u_short subfunc = *(u_short *)stk; @@ -4441,7 +5013,7 @@ do_create_truncate: if (fstat(f->fd, &f->st) == 0) { /* update file size in case other process changed it */ f->size = f->st.st_size; - set_32bit_size_or_position(&_sft_size(sft), f->size); + set_32bit_size_or_position(&sft_size(sft), f->size); f->seek = f->size + seek; break; } else { @@ -4454,7 +5026,7 @@ do_create_truncate: return FALSE; } d_printf("result seek=%08"PRIX64"h\n", f->seek); - set_32bit_size_or_position(&_sft_position(sft), f->seek); + set_32bit_size_or_position(&sft_position(sft), f->seek); MEMCPY_2DOS(SEGOFF2LINEAR(SREG(ds), LWORD(edx)), &f->seek, sizeof(f->seek)); SETWORD(&state->eax, 0); return TRUE; diff --git a/src/dosext/mfs/mfs.h b/src/dosext/mfs/mfs.h index d01e354..3a74aa8 100644 --- a/src/dosext/mfs/mfs.h +++ b/src/dosext/mfs/mfs.h @@ -29,7 +29,7 @@ Andrew.Tridgell@anu.edu.au 30th March 1993 #define FALSE 0 #define TRUE 1 -//#define UNCHANGED 2 +#define UNCHANGED 2 #define REDIRECT 3 #define dbg_fd -1 @@ -241,7 +241,7 @@ struct dir_ent { char d_name[256]; /* unix name as in readdir */ u_short mode; /* unix st_mode value */ u_short long_path; /* directory has long path */ - uint64_t size; /* size of file */ + int size; /* size of file */ time_t time; /* st_mtime */ int attr; }; @@ -271,64 +271,12 @@ struct mfs_dir unsigned int nr; }; -#define _sdb_drive_letter(sdb) (*(u_char *)&sdb[sdb_drive_letter_off]) -#define _sdb_template_name(sdb) ((char *)&sdb[sdb_template_name_off]) -#define _sdb_template_ext(sdb) ((char *)&sdb[sdb_template_ext_off]) -#define _sdb_attribute(sdb) (*(u_char *)&sdb[sdb_attribute_off]) -#define _sdb_dir_entry(sdb) (*(u_short *)&sdb[sdb_dir_entry_off]) -#define _sdb_p_cluster(sdb) (*(u_short *)&sdb[sdb_p_cluster_off]) -#define _sdb_file_name(sdb) ((char *)&sdb[sdb_file_name_off]) -#define _sdb_file_ext(sdb) ((char *)&sdb[sdb_file_ext_off]) -#define _sdb_file_attr(sdb) (*(u_char *)&sdb[sdb_file_attr_off]) -#define _sdb_file_time(sdb) (*(u_short *)&sdb[sdb_file_time_off]) -#define _sdb_file_date(sdb) (*(u_short *)&sdb[sdb_file_date_off]) -#define _sdb_file_st_cluster(sdb)(*(u_short *)&sdb[sdb_file_st_cluster_off]) -#define _sdb_file_size(sdb) (*(u_int *)&sdb[sdb_file_size_off]) -#define _sft_handle_cnt(sft) (*(u_short *)&sft[sft_handle_cnt_off]) -#define _sft_open_mode(sft) (*(u_short *)&sft[sft_open_mode_off]) -#define _sft_attribute_byte(sft) (*(u_char *)&sft[sft_attribute_byte_off]) -#define _sft_device_info(sft) (*(u_short *)&sft[sft_device_info_off]) -#define _sft_dev_drive_ptr(sft) (*(u_int *)&sft[sft_dev_drive_ptr_off]) -#define _sft_start_cluster(sft) (*(u_short *)&sft[sft_start_cluster_off]) -#define _sft_time(sft) (*(u_short *)&sft[sft_time_off]) -#define _sft_date(sft) (*(u_short *)&sft[sft_date_off]) -#define _sft_size(sft) (*(u_int *)&sft[sft_size_off]) -#define _sft_position(sft) (*(u_int *)&sft[sft_position_off]) -#define _sft_rel_cluster(sft) (*(u_short *)&sft[sft_rel_cluster_off]) -#define _sft_abs_cluster(sft) (*(u_short *)&sft[sft_abs_cluster_off]) -#define _sft_directory_sector(sft) (*(u_short *)&sft[sft_directory_sector_off]) -#define _sft_directory_entry(sft) (*(u_char *)&sft[sft_directory_entry_off]) -#define _sft_name(sft) ( (char *)&sft[sft_name_off]) -#define _sft_ext(sft) ( (char *)&sft[sft_ext_off]) -#define _sft_fd(sft) (*(u_short *)&sft[sft_fd_off]) -#define _sda_current_dta(sda) (FARADDR((far_t *)&sda[sda_current_dta_off])) -#define _sda_error_code(sda) (*(u_short *)&sda[4]) -#define _sda_cur_psp(sda) (*(u_short *)&sda[sda_cur_psp_off]) -#define __sda_cur_drive(sda) (*(u_char *)&sda[sda_cur_drive_off]) -#define _sda_filename1(sda) ((char *)&sda[sda_filename1_off]) -#define _sda_filename2(sda) ((char *)&sda[sda_filename2_off]) -#define _sda_sdb(sda) ((sdb_t )&sda[sda_sdb_off]) -#define _sda_cds(sda) ((cds_t)(uintptr_t)(FARPTR((far_t *)&sda[sda_cds_off]))) -#define _sda_search_attribute(sda) (*(u_char *)&sda[sda_search_attribute_off]) -#define _sda_open_mode(sda) (*(u_char *)&sda[sda_open_mode_off]) -#define _sda_rename_source(sda) ((sdb_t )&sda[sda_rename_source_off]) -#define _sda_user_stack(sda) ((char *)(uintptr_t)(FARPTR((far_t *)&sda[sda_user_stack_off]))) -#define _sda_ext_act(sda) (*(u_short *)&sda[sda_ext_act_off]) -#define _sda_ext_attr(sda) (*(u_short *)&sda[sda_ext_attr_off]) -#define _sda_ext_mode(sda) (*(u_short *)&sda[sda_ext_mode_off]) -#define _psp_parent_psp(psp) (*(u_short *)&psp[0x16]) -#define _psp_handles(psp) ((char *)(uintptr_t)(FARPTR((far_t *)&psp[0x34]))) -#define _lol_dpbfarptr(lol) (rFAR_FARt(READ_DWORD((lol)+lol_dpbfarptr_off))) -#define _lol_cdsfarptr(lol) (rFAR_FARt(READ_DWORD((lol)+lol_cdsfarptr_off))) -#define _lol_last_drive(lol) (READ_BYTE((lol)+lol_last_drive_off)) -#define _lol_nuldev(lol) ((lol)+lol_nuldev_off) -#define _lol_njoined(lol) ((lol)+lol_njoined_off) - -#define Addr_8086(x,y) MK_FP32((x),(y) & 0xffff) #define FAR(x) (Addr_8086(x.segment, x.offset)) #define FARPTR(x) (Addr_8086((x)->segment, (x)->offset)) #define FARADDR(x) (SEGOFF2LINEAR((x)->segment, (x)->offset)) +typedef u_short *psp_t; + #define PSPPTR(x) (Addr_8086(x, 0)) struct drive_info @@ -402,24 +350,3 @@ extern int get_drive_from_path(char *path, int *drive); * Should be checked against MAX_DRIVE to make sure it is actually * a drive, i.e. no impossible-for-drive bits are set. */ #define SFT_DRIVE(sft) ((sft_device_info(sft) & 0x88bf) ^ 0x8800) - -struct file_fd -{ - char *name; - int idx; - int fd; - int type; - void *shlock; - void **shemu_locks; // for share modes emulation - int mlemu_fds[2]; // for mandatory locks emulation - struct stat st; - int is_writable; - int share_mode; - u_short psp; - uint64_t seek; - uint64_t size; - int lock_cnt; -}; - -#define MAX_OPENED_FILES 256 -extern struct file_fd open_files[MAX_OPENED_FILES]; diff --git a/src/dosext/mfs/mscdex.c b/src/dosext/mfs/mscdex.c index a516a13..d2d86d6 100644 --- a/src/dosext/mfs/mscdex.c +++ b/src/dosext/mfs/mscdex.c @@ -400,7 +400,6 @@ int mscdex(void) break; case 0x10: { - uint16_t seg; int driver = GetDriver(_CX); if (!buf) { _AX = 0xf; @@ -409,31 +408,14 @@ int mscdex(void) } CARRY; if (driver >= 4) { -#if 0 - _AX = 0xf; -#else - /* Ultimate Domain game puts junk into CH, - * which leads to a wrong drive. We can - * either clean CH ourselves or not return - * an error here. */ - NOCARRY; -#endif - break; - } - devname[7] = driver + '1'; - dev = is_dos_device(devname); - if (!dev) { _AX = 0xf; break; } - seg = dev >> 16; - dev = SEGOFF2LINEAR(seg, dev & 0xffff); WRITE_BYTE(buf + 1, driver); // set SubUnit - /* call driver with req buf in ES:BX */ - strat = READ_WORD(dev + 6); - intr = READ_WORD(dev + 8); - fake_call_to(seg, intr); - fake_call_to(seg, strat); + strat = READ_WORD(buf + 6); + intr = READ_WORD(buf + 8); + fake_call_to(_ES, intr); + fake_call_to(_ES, strat); NOCARRY; break; } diff --git a/src/dosext/mfs/rlocks.c b/src/dosext/mfs/rlocks.c deleted file mode 100644 index 9ed9080..0000000 --- a/src/dosext/mfs/rlocks.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: region locks support. - * - * Author: @stsp - * - * Note: DOS lock semantic doesn't distinguish between read and write - * locks. It only have exclusive region locks. They are "mandatory", - * therefore they inhibit both reads and writes. - * Posix locks do not mimic that because you can't set the write lock - * on a read-only fd (or set read lock on a write-only fd, not our case). - * We can provide the DOS locking semantic by trying to force the write - * mode on every open file. This may include chmod()ing and checking - * the writability by hands. Huge hacks! We did that at some point of - * time, but current implementation drops all hacks and provides the - * Posix-alike semantic instead, with the "only" difference from Posix - * being the locks are mandatory. - * - * Note: Since we, unlike DOS does, distinguish between reader and - * writer locks, we also need to make sure reader locks never inhibit - * other's read()s, rather than the "inhibit any I/O of others" - * behavior of the DOS exclusive locks. This is because now multiple - * readers can grab the read lock simultaneously, so all should be - * able to read, rather than blocking each other's read()s. - * But for the more DOS-compatible behavior we inhibit read()s - * of the readers that didn't acquire any lock (DOS locks are mandatory, - * so locks on one FD are enough to inhibit I/O on other FDs there). - * Unfortunately with Posix locks its quite difficult to test - * the locks on our own FD, as locks on same FD never conflict, - * so some emulation is emploied for that task. - * The future kernels will support our Posix extension of using F_UNLCK - * for testing own locks. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include "dosemu_debug.h" -#include "rlocks.h" - -#define d_Stub(arg1, s, a...) d_printf("MFS: " s, ##a) -#define Debug0(args) d_Stub args -#define Debug1(args) d_Stub args - -static int lock_set(int fd, struct flock *fl) -{ - int ret; - fl->l_pid = 0; // needed for OFD locks - fl->l_whence = SEEK_SET; - ret = fcntl(fd, F_OFD_SETLK, fl); - if (ret) { - int err = errno; - if (err != EAGAIN) - error("OFD_SETLK failed, %s\n", strerror(err)); - } - return ret; -} - -static int do_lock_get(int fd, struct flock *fl) -{ - fl->l_pid = 0; // needed for OFD locks - fl->l_whence = SEEK_SET; - return fcntl(fd, F_OFD_GETLK, fl); -} - -static void lock_get(int fd, struct flock *fl) -{ - int ret = do_lock_get(fd, fl); - if (ret) { - error("OFD_GETLK failed, %s\n", strerror(errno)); - /* pretend nothing is locked */ - fl->l_type = F_UNLCK; - } -} - -int lock_file_region(int fd, int lck, long long start, - unsigned long len, int wr, int mlemu_fd) -{ - struct flock fl; - int ret; - - /* make data visible before releasing the lock */ - if (!lck) - fsync(fd); - - fl.l_type = (lck ? (wr ? F_WRLCK : F_RDLCK) : F_UNLCK); - fl.l_start = start; - fl.l_len = len; - /* needs to lock against I/O operations in another process */ - ret = flock(fd, LOCK_EX); - if (ret) - return -1; - ret = lock_set(fd, &fl); -#if FUNLCK_WA - if (mlemu_fd != -1) - lock_set(mlemu_fd, &fl); -#endif - flock(fd, LOCK_UN); - return ret; -} - -int region_is_fully_owned(int fd, long long start, unsigned long len, int wr, - int mlemu_fd2) -{ - struct flock fl; - int err; - - fl.l_type = F_UNLCK; - fl.l_start = start; - fl.l_len = len; - err = do_lock_get(fd, &fl); -#if FUNLCK_WA - if (err && errno == EINVAL) { // F_UNLCK extension unsupported - /* check on mirror fd so rd/wr inverted */ - fl.l_type = wr ? F_RDLCK : F_WRLCK; - fl.l_start = start; - fl.l_len = len; - lock_get(mlemu_fd2, &fl); - } else -#endif - if (err) { - perror("fcntl()"); - return 0; - } - if (fl.l_type == F_UNLCK) - return 0; // not locked - if (wr && fl.l_type == F_RDLCK) { -#if FUNLCK_WA - assert(!err); // can only happen with F_UNLCK method -#endif - return 0; // not sufficient - } - if (fl.l_start > start) - return 0; // not fully locked - if (fl.l_start + fl.l_len < start + len) - return 0; // not fully locked - return 1; -} - -int region_lock_offs(int fd, long long start, unsigned long len, int wr) -{ - struct flock fl; - int ret; - - /* needs to lock against lock changes in another process */ - ret = flock(fd, LOCK_EX); - if (ret) - return -1; - fl.l_type = wr ? F_WRLCK : F_RDLCK; - fl.l_start = start; - fl.l_len = len; - lock_get(fd, &fl); - if (fl.l_type == F_UNLCK) - return len; - if (fl.l_start > start) - return (fl.l_start - start); // found partially unlocked region - /* no allowed region found, unlock and return 0 */ - return flock(fd, LOCK_UN); -} - -void region_unlock_offs(int fd) -{ - flock(fd, LOCK_UN); -} - -#if FUNLCK_WA -void open_mlemu(int *r_fds) -{ - char mltmpl[] = "/tmp/dosemu2_mlemu_XXXXXX"; - int fd0, fd1; - - r_fds[0] = r_fds[1] = -1; - /* create 2 fds, 1 for mirroring locks and 1 for testing locks */ - fd0 = mkstemp(mltmpl); - if (fd0 == -1) { - perror("mkstemp()"); - return; - } - fd1 = open(mltmpl, O_RDONLY | O_CLOEXEC); - unlink(mltmpl); - if (fd1 == -1) { - perror("open()"); - close(fd0); - return; - } - r_fds[0] = fd0; - r_fds[1] = fd1; -} - -void close_mlemu(int *fds) -{ - if (fds[0] != -1) - close(fds[0]); - if (fds[1] != -1) - close(fds[1]); -} -#endif diff --git a/src/dosext/mfs/rlocks.h b/src/dosext/mfs/rlocks.h deleted file mode 100644 index 9d14a3f..0000000 --- a/src/dosext/mfs/rlocks.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef RLOCKS_H -#define RLOCKS_H - -#if HAVE_DECL_F_OFD_SETLK - -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) - #ifdef WARN_UNDISABLED_WA - #warning Not disabling FUNLCK_WA, update your kernel - #endif - #define FUNLCK_WA 1 -#else - #ifdef DISABLE_SYSTEM_WA - #define FUNLCK_WA 0 - #else - #define FUNLCK_WA 1 - #endif -#endif - -#if FUNLCK_WA -void open_mlemu(int *r_fds); -void close_mlemu(int *fds); -#else -static inline void open_mlemu(int *r_fds) -{ -} - -static inline void close_mlemu(int *fds) -{ -} -#endif - -int lock_file_region(int fd, int lck, long long start, - unsigned long len, int wr, int mlemu_fd); -int region_lock_offs(int fd, long long start, unsigned long len, - int wr); -void region_unlock_offs(int fd); -int region_is_fully_owned(int fd, long long start, unsigned long len, int wr, - int mlemu_fd2); - -#else - -static inline void open_mlemu(int *r_fds) -{ -} - -static inline void close_mlemu(int *fds) -{ -} - -static inline int lock_file_region(int fd, int lck, long long start, - unsigned long len, int wr, int mlemu_fd) -{ - return 0; -} - -static inline int region_lock_offs(int fd, long long start, unsigned long len, - int wr) -{ - return len; -} - -static inline void region_unlock_offs(int fd) -{ -} - -static inline int region_is_fully_owned(int fd, long long start, - unsigned long len, int wr, int mlemu_fd2) -{ - return 1; // locks not implemented, allow everything -} - -#endif - -#endif diff --git a/src/dosext/mfs/share.c b/src/dosext/mfs/share.c deleted file mode 100644 index 18ee163..0000000 --- a/src/dosext/mfs/share.c +++ /dev/null @@ -1,514 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: open share modes support. - * - * Author: @stsp - * - */ -#include -#include -#include -#include -#include -#include -#include -#include "emu.h" -#include "dosemu_debug.h" -#include "dos2linux.h" -#include "mfs.h" -#include "xattr.h" -#include "shlock.h" -#include "rlocks.h" -#include "share.h" - -#define SHLOCK_DIR "dosemu2_sh" -#define EXLOCK_DIR "dosemu2_ex" - -enum { compat_lk, noncompat_lk, denyR_lk, denyW_lk, R_lk, W_lk, lk_MAX }; - -static char *prepare_shlock_name(const char *fname) -{ - char *p; - char *nm = strdup(fname); - while ((p = strchr(nm, '/'))) - *p = '\\'; - return nm; -} - -static void *apply_shlock(const char *fname) -{ - char *nm = prepare_shlock_name(fname); - void *ret = shlock_open(SHLOCK_DIR, nm, 0, 1); - free(nm); - return ret; -} - -static void *apply_exlock(const char *fname) -{ - char *nm = prepare_shlock_name(fname); - void *ret = shlock_open(EXLOCK_DIR, nm, 1, 1); - free(nm); - return ret; -} - -static int is_locked_shlock(const char *name) -{ - char *nm = prepare_shlock_name(name); - /* try to create exlock in a shlock dir in non-blocking mode */ - void *exlock = shlock_open(SHLOCK_DIR, nm, 1, 0); - free(nm); - if (!exlock) - return 1; - /* we are called under another exlock, so no races if we drop the lock - * or if it failed to be created */ - shlock_close(exlock); - return 0; -} - -struct file_fd *do_claim_fd(const char *name) -{ - int i; - struct file_fd *ret = NULL; - - for (i = 0; i < MAX_OPENED_FILES; i++) { - struct file_fd *f = &open_files[i]; - if (!f->name) { - f->name = strdup(name); - f->shemu_locks = malloc(sizeof(void *) * lk_MAX); - f->idx = i; - ret = f; - break; - } - } - if (!ret) { - error("MFS: too many open files\n"); - leavedos(1); - return NULL; - } - memset(ret->shemu_locks, 0, sizeof(void *) * lk_MAX); - ret->seek = 0; - ret->size = 0; - return ret; -} - -static struct file_fd *do_find_fd(const char *name) -{ - int i; - struct file_fd *ret = NULL; - - for (i = 0; i < MAX_OPENED_FILES; i++) { - struct file_fd *f = &open_files[i]; - if (f->name && strcmp(name, f->name) == 0) { - ret = f; - break; - } - } - return ret; -} - -static int file_is_opened(const char *name) -{ - int lck = is_locked_shlock(name); - if (lck) - return 1; // locked means already opened - return access(name, F_OK); -} - -static char *prepare_shemu_name(const char *fname, int id) -{ - const char *sf[lk_MAX] = { "compat", "noncompat", "denyR", "denyW", - "R", "W" }; - char *nm; - asprintf(&nm, "%s.%s", fname, sf[id]); - return nm; -} - -static int is_locked(const char *fname, int id) -{ - char *lname = prepare_shemu_name(fname, id); - int lck = is_locked_shlock(lname); - free(lname); - return lck; -} - -static void do_lock(const char *fname, int id, void **locks) -{ - char *lname = prepare_shemu_name(fname, id); - locks[id] = apply_shlock(lname); - free(lname); -} - -static int open_compat(const char *fname, int open_mode, void **locks) -{ - if (is_locked(fname, noncompat_lk)) - return -1; - do_lock(fname, compat_lk, locks); - if (open_mode != O_WRONLY) - do_lock(fname, R_lk, locks); - if (open_mode == O_WRONLY || open_mode == O_RDWR) - do_lock(fname, W_lk, locks); - return 0; -} - -static int open_share(const char *fname, int open_mode, int share_mode, - void **locks) -{ - int denyR = (share_mode == DENY_READ || share_mode == DENY_ALL); - int denyW = (share_mode == DENY_WRITE || share_mode == DENY_ALL); - /* inhibit compat mode */ - if (is_locked(fname, compat_lk)) - return -1; - if (open_mode != O_WRONLY) { - /* read mode allowed? */ - if (is_locked(fname, denyR_lk)) - return -1; - } - if (open_mode == O_WRONLY || open_mode == O_RDWR) { - /* write mode allowed? */ - if (is_locked(fname, denyW_lk)) - return -1; - } - if (denyR) { - /* denyR allowed? */ - if (is_locked(fname, R_lk)) - return -1; - } - if (denyW) { - /* denyW allowed? */ - if (is_locked(fname, W_lk)) - return -1; - } - - /* all checks passed, claim our locks */ - do_lock(fname, noncompat_lk, locks); - if (open_mode != O_WRONLY) - do_lock(fname, R_lk, locks); - if (open_mode == O_WRONLY || open_mode == O_RDWR) - do_lock(fname, W_lk, locks); - if (denyR) - do_lock(fname, denyR_lk, locks); - if (denyW) - do_lock(fname, denyW_lk, locks); - return 0; -} - -static int do_mfs_open(struct file_fd *f, const char *fname, - int flags, int share_mode, int *r_err) -{ - int fd, err, i; - void *shlock; - void *exlock; - int is_writable = (flags == O_WRONLY || flags == O_RDWR); - - *r_err = ACCESS_DENIED; - exlock = apply_exlock(fname); - if (!exlock) - return -1; - fd = open(fname, flags | O_CLOEXEC); - if (fd == -1) - goto err; - if (!share_mode) { - err = open_compat(fname, flags, f->shemu_locks); - /* NOTE: DOS-6.22 checks if the file is R/O, DOS-7 doesn't. - * Below the R/O check is commented out to be compatible with - * DOS-7. That solves many problems, see - * https://github.com/dosemu2/dosemu2/issues/2143 - * Or for example running windows-3.1 in 2 dosemu2 instances - * would result in no sound in the second instance if the R/O - * check is enforced and the sound drivers are not marked as - * R/O. - * BUT we do not implement the DOS-7 share rules fully. - * Namely, DenyNone is implemented the 6.22 way. - */ - if (err && !is_writable /*&& file_is_ro(fname)*/ && - !is_locked(fname, denyR_lk) && !is_locked(fname, W_lk)) { - d_printf("SHARE: allowing compat open of R/O file\n"); - err = 0; - } - } else { - int denyR = (share_mode == DENY_READ || share_mode == DENY_ALL); - err = open_share(fname, flags, share_mode, f->shemu_locks); - /* See above note about the disabled R/O check. */ - if (err && !is_writable && !denyR /*&& file_is_ro(fname)*/ && - is_locked(fname, compat_lk) && !is_locked(fname, W_lk)) { - d_printf("SHARE: allowing share open of R/O file\n"); - err = 0; - } - } - if (err) { - *r_err = SHARING_VIOLATION; - goto err2; - } - shlock = apply_shlock(fname); - if (!shlock) { - *r_err = SHARING_VIOLATION; - goto err3; - } - shlock_close(exlock); - - f->fd = fd; - f->shlock = shlock; - f->share_mode = share_mode; - f->psp = sda_cur_psp(sda); - f->is_writable = is_writable; - open_mlemu(f->mlemu_fds); - return 0; - -err3: - for (i = 0; i < lk_MAX; i++) { - if (f->shemu_locks[i]) - shlock_close(f->shemu_locks[i]); - } -err2: - close(fd); -err: - shlock_close(exlock); - return -1; -} - -struct file_fd *mfs_open(const char *name, int flags, - int share_mode, int *r_err) -{ - struct file_fd *f; - int err; - - f = do_claim_fd(name); - if (!f) - return NULL; - err = do_mfs_open(f, name, flags, share_mode, r_err); - if (err) { - free(f->name); - f->name = NULL; - free(f->shemu_locks); - f->shemu_locks = NULL; - return NULL; - } - return f; -} - -static int do_mfs_creat(struct file_fd *f, const char *fname, mode_t mode) -{ - int fd, err, i; - void *shlock; - void *exlock; - - exlock = apply_exlock(fname); - if (!exlock) - return -1; - fd = open(fname, O_RDWR | O_CLOEXEC | O_CREAT | O_TRUNC, mode); - if (fd == -1) - goto err; - /* set compat mode */ - err = open_compat(fname, O_RDWR, f->shemu_locks); - if (err) - goto err2; - shlock = apply_shlock(fname); - if (!shlock) - goto err3; - shlock_close(exlock); - - f->fd = fd; - f->shlock = shlock; - f->share_mode = 0; - f->psp = sda_cur_psp(sda); - f->is_writable = 1; - open_mlemu(f->mlemu_fds); - return 0; - -err3: - for (i = 0; i < lk_MAX; i++) { - if (f->shemu_locks[i]) - shlock_close(f->shemu_locks[i]); - } -err2: - unlink(fname); - close(fd); -err: - shlock_close(exlock); - return -1; -} - -struct file_fd *mfs_creat(const char *name, mode_t mode) -{ - struct file_fd *f; - int err; - - f = do_claim_fd(name); - if (!f) - return NULL; - err = do_mfs_creat(f, name, mode); - if (err) { - free(f->name); - f->name = NULL; - free(f->shemu_locks); - f->shemu_locks = NULL; - return NULL; - } - return f; -} - -static int do_mfs_unlink(const char *fname, int force) -{ - int rc; - void *exlock; - - exlock = apply_exlock(fname); - if (!exlock) - return -1; - rc = file_is_opened(fname); - switch (rc) { - case -1: - shlock_close(exlock); - return FILE_NOT_FOUND; - case 0: - break; - case 1: - if (!force) { - shlock_close(exlock); - return ACCESS_DENIED; - } - } - rc = unlink(fname); - shlock_close(exlock); - if (rc) - return FILE_NOT_FOUND; - return 0; -} - -int mfs_unlink(char *name) -{ - struct file_fd *f; - - f = do_find_fd(name); - if (f && (f->share_mode || f->psp != sda_cur_psp(sda))) - return ACCESS_DENIED; - return do_mfs_unlink(name, f && !f->share_mode && - f->psp == sda_cur_psp(sda)); -} - -static int do_mfs_setattr(const char *fname, int attr, int force) -{ - int rc; - void *exlock; - - exlock = apply_exlock(fname); - if (!exlock) - return -1; - rc = file_is_opened(fname); - switch (rc) { - case -1: - shlock_close(exlock); - return FILE_NOT_FOUND; - case 0: - break; - case 1: - if (!force) { - shlock_close(exlock); - return ACCESS_DENIED; - } - } - rc = set_dos_xattr(fname, attr); - shlock_close(exlock); - return rc; -} - -int mfs_setattr(char *name, int attr) -{ - struct file_fd *f; - - f = do_find_fd(name); - if (f && (f->share_mode || f->psp != sda_cur_psp(sda))) - return ACCESS_DENIED; - return do_mfs_setattr(name, attr, f && !f->share_mode && - f->psp == sda_cur_psp(sda)); -} - -static int do_mfs_rename(const char *fname, const char *fname2, int force) -{ - int rc; - void *exlock; - void *exlock2; - - exlock = apply_exlock(fname); - if (!exlock) - return -1; - rc = file_is_opened(fname); - switch (rc) { - case -1: - shlock_close(exlock); - return FILE_NOT_FOUND; - case 0: - break; - case 1: - if (!force) { - shlock_close(exlock); - return ACCESS_DENIED; - } - } - - exlock2 = apply_exlock(fname2); - if (!exlock2) - goto err2; - rc = file_is_opened(fname2); - if (rc != -1) { - /* dest file exists, do not overwrite */ - shlock_close(exlock2); - shlock_close(exlock); - return ACCESS_DENIED; - } - - rc = rename(fname, fname2); - shlock_close(exlock2); - shlock_close(exlock); - if (rc) { - perror("rename()"); - return FILE_NOT_FOUND; - } - return 0; - -err2: - shlock_close(exlock); - return ACCESS_DENIED; -} - -int mfs_rename(char *name, char *name2) -{ - struct file_fd *f; - - f = do_find_fd(name); - if (f && (f->share_mode || f->psp != sda_cur_psp(sda))) - return ACCESS_DENIED; - return do_mfs_rename(name, name2, f && !f->share_mode && - f->psp == sda_cur_psp(sda)); -} - -void mfs_close(struct file_fd *f) -{ - int i; - - close(f->fd); - shlock_close(f->shlock); - for (i = 0; i < lk_MAX; i++) { - if (f->shemu_locks[i]) - shlock_close(f->shemu_locks[i]); - } - close_mlemu(f->mlemu_fds); - free(f->shemu_locks); - free(f->name); - f->name = NULL; -} diff --git a/src/dosext/mfs/share.h b/src/dosext/mfs/share.h deleted file mode 100644 index 1432c73..0000000 --- a/src/dosext/mfs/share.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#ifndef SHARE_H -#define SHARE_H - -struct file_fd; - -struct file_fd *do_claim_fd(const char *name); -struct file_fd *mfs_creat(const char *name, mode_t mode); -struct file_fd *mfs_open(const char *name, int flags, - int share_mode, int *r_err); -int mfs_unlink(char *name); -int mfs_setattr(char *name, int attr); -int mfs_rename(char *name, char *name2); -void mfs_close(struct file_fd *f); - -#endif diff --git a/src/dosext/mfs/util.c b/src/dosext/mfs/util.c index 394dbbf..f14c663 100644 --- a/src/dosext/mfs/util.c +++ b/src/dosext/mfs/util.c @@ -167,14 +167,6 @@ char *strupperDOS(char *src) return s; } -char *strnupperDOS(char *src, int n) -{ - char *s = src; - for (; n > 0 && *src; src++, n--) - *src = toupperDOS(*src); - return s; -} - char *strlowerDOS(char *src) { char *s = src; @@ -183,18 +175,21 @@ char *strlowerDOS(char *src) return s; } -char *strnlowerDOS(char *src, int n) +/* locale-independent routins */ + +/*************************************************************************** +line strncpy but always null terminates. Make sure there is room! +****************************************************************************/ +char *StrnCpy(char *dest,const char *src,int n) { - char *s = src; - for (; n > 0 && *src; src++, n--) - *src = tolowerDOS(*src); - return s; + char *d = dest; + while (n-- && (*d++ = *src++)) ; + *d = 0; + return(dest); } -/* locale-independent routines */ - /**************************************************************************** -promote a dptr (to make it recently used) +prompte a dptr (to make it recently used) ****************************************************************************/ void array_promote(char *array,int elsize,int element) { diff --git a/src/dosext/mfs/xattr.c b/src/dosext/mfs/xattr.c deleted file mode 100644 index d607fef..0000000 --- a/src/dosext/mfs/xattr.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: xattrs support. - * - * Author: @stsp - * - */ -#include -#include -#include -#include -#include -#include -#include -#include "dosemu_debug.h" -#include "mfs.h" -#include "xattr.h" - -#define XATTR_DOSATTR_NAME "user.DOSATTRIB" -#define XATTR_ATTRIBS_MASK (READ_ONLY_FILE | HIDDEN_FILE | SYSTEM_FILE | \ - ARCHIVE_NEEDED) - -#ifdef __APPLE__ -#define getxattr(path,name,value,size) getxattr(path,name,value,size,0,0) -#define fgetxattr(fd,name,value,size) fgetxattr(fd,name,value,size,0,0) -#define setxattr(path,name,value,size,flags) setxattr(path,name,value,size,0,flags) -#define fsetxattr(fd,name,value,size,flags) fsetxattr(fd,name,value,size,0,flags) -#endif - -static int do_extr_xattr(const char *xbuf, ssize_t size, const char *name) -{ - if (size == -1 && errno == ENOTSUP) { - error("MFS: failed to get xattrs for %s, unsupported!\n", name); - return -1; - } - if (size <= 2 || strncmp(xbuf, "0x", 2) != 0) - return -1; - return strtol(xbuf + 2, NULL, 16) & XATTR_ATTRIBS_MASK; -} - -static int xattr_str(char *xbuf, int xsize, int attr) -{ - int ret = snprintf(xbuf, xsize, "0x%x", attr & XATTR_ATTRIBS_MASK); - assert(ret > 0); - return (ret + 1); // include '\0' -} - -static int xattr_err(int err, const char *name) -{ - if (err) { - error("MFS: failed to set xattrs for %s: %s\n", name, strerror(errno)); -// leavedos(5); -// return ACCESS_DENIED; - } - return 0; -} - -int set_dos_xattr_fd(int fd, int attr, const char *name) -{ - char xbuf[16]; - return xattr_err(fsetxattr(fd, XATTR_DOSATTR_NAME, xbuf, - xattr_str(xbuf, sizeof(xbuf), attr), 0), name); -} - -int set_dos_xattr(const char *fname, int attr) -{ - char xbuf[16]; - int err = setxattr(fname, XATTR_DOSATTR_NAME, xbuf, - xattr_str(xbuf, sizeof(xbuf), attr), 0); - if (err) { - struct stat st; - int err2 = stat(fname, &st); - if (err2) - return FILE_NOT_FOUND; - if (!(st.st_mode & S_IWUSR)) { - err = chmod(fname, st.st_mode | S_IWUSR); - if (err) - return ACCESS_DENIED; - err = setxattr(fname, XATTR_DOSATTR_NAME, xbuf, - xattr_str(xbuf, sizeof(xbuf), attr), 0); - } - } - return xattr_err(err, fname); -} - -int get_dos_xattr(const char *fname) -{ - char xbuf[16]; - ssize_t size = getxattr(fname, XATTR_DOSATTR_NAME, xbuf, sizeof(xbuf) - 1); - /* some dosemus forgot \0 so we fix it up here */ - if (size > 0 && xbuf[size - 1] != '\0') { - error("MFS: fixup xattr for %s\n", fname); - xbuf[size++] = '\0'; - setxattr(fname, XATTR_DOSATTR_NAME, xbuf, size, XATTR_REPLACE); - } - return do_extr_xattr(xbuf, size, fname); -} - -int get_dos_xattr_fd(int fd, const char *name) -{ - char xbuf[16]; - ssize_t size = fgetxattr(fd, XATTR_DOSATTR_NAME, xbuf, sizeof(xbuf) - 1); - /* some dosemus forgot \0 so we fix it up here */ - if (size > 0 && xbuf[size - 1] != '\0') { - error("MFS: fixup xattr\n"); - xbuf[size++] = '\0'; - fsetxattr(fd, XATTR_DOSATTR_NAME, xbuf, size, XATTR_REPLACE); - } - return do_extr_xattr(xbuf, size, name); -} - -int file_is_ro(const char *fname) -{ - int attr = get_dos_xattr(fname); - /* NOTE: do not use unix file perms for R/O as that may crash - * some cdrom games: - * https://github.com/dosemu2/dosemu2/issues/989 - */ - if (attr == -1) - return 0; - return !!(attr & READ_ONLY_FILE); -} diff --git a/src/dosext/mfs/xattr.h b/src/dosext/mfs/xattr.h deleted file mode 100644 index a77d717..0000000 --- a/src/dosext/mfs/xattr.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#ifndef XATTR_H -#define XATTR_H - -#ifdef HAVE_SETXATTR - -int file_is_ro(const char *fname); -int set_dos_xattr(const char *fname, int attr); -int get_dos_xattr(const char *fname); -int get_dos_xattr_fd(int fd, const char *name); -int set_dos_xattr_fd(int fd, int attr, const char *name); - -#else - -static inline int file_is_ro(const char *fname) -{ - return 0; -} - -static inline int set_dos_xattr(const char *fname, int attr) -{ - return 0; -} - -static inline int get_dos_xattr(const char *fname) -{ - return -1; -} - -static inline int get_dos_xattr_fd(int fd, const char *name) -{ - return -1; -} - -static inline int set_dos_xattr_fd(int fd, int attr, const char *name) -{ - return 0; -} - -#endif - -#endif diff --git a/src/dosext/misc/emm.c b/src/dosext/misc/emm.c index b8b9844..1606da9 100644 --- a/src/dosext/misc/emm.c +++ b/src/dosext/misc/emm.c @@ -915,7 +915,7 @@ reallocate_pages(struct vm86_regs * state) /* * Here we come, when reallocation would lead to a ZERO sized block. * This would be bad for mremap(), because this is equal to munmap() - * We destroy the object instead + * We destroy the objekt instead */ destroy_memory_object(handle_info[handle].object,handle_info[handle].numpages*EMM_PAGE_SIZE); handle_info[handle].object = 0; diff --git a/src/dosext/misc/xms.c b/src/dosext/misc/xms.c index 3afeb0b..b552452 100644 --- a/src/dosext/misc/xms.c +++ b/src/dosext/misc/xms.c @@ -30,12 +30,9 @@ #include "int.h" #include "hma.h" #include "emm.h" -#include "mapping.h" #include "dos2linux.h" -#include "utilities.h" #include "cpu-emu.h" #include "smalloc.h" -#include "pgalloc.h" #undef DEBUG_XMS @@ -61,7 +58,6 @@ static char RCSxms[] = "$Id$"; #define XMS_RESIZE_EXTENDED_MEMORY_BLOCK 0x0f #define XMS_ALLOCATE_UMB 0x10 #define XMS_DEALLOCATE_UMB 0x11 -#define XMS_REALLOCATE_UMB 0x12 #define HIGH_MEMORY_IN_USE 0x92 #define HIGH_MEMORY_NOT_ALLOCATED 0x93 @@ -70,28 +66,9 @@ static char RCSxms[] = "$Id$"; static int a20_local, a20_global, freeHMA; /* is HMA free? */ -struct __attribute__ ((__packed__)) EMM { - unsigned int Length; - unsigned short SourceHandle; - unsigned int SourceOffset; - unsigned short DestHandle; - unsigned int DestOffset; -}; - -struct Handle { - unsigned short int num; - void *addr; - unsigned int size; - int lockcount; - unsigned dst; -}; - static struct Handle handles[NUM_HANDLES]; static int handle_count; static int intdrv; -static int ext_hooked_hma; -static int totalBytes; -static void *pgapool; void show_emm(struct EMM); static unsigned char xms_query_freemem(int), xms_allocate_EMB(int), xms_free_EMB(void), @@ -124,6 +101,7 @@ umb_setup(int umb_ems) { dosaddr_t addr_start; uint32_t size; +// int i; memcheck_addtype('U', "Upper Memory Block (UMB, XMS 3.0)"); @@ -226,103 +204,38 @@ umb_query(void) /* end of stuff from Mach */ -static void *xms_alloc(unsigned size) +static smpool mp; + +static unsigned xms_alloc(unsigned size) { - void *ptr = alloc_mapping(MAPPING_OTHER, PAGE_ALIGN(size)); - if (ptr == MAP_FAILED) + unsigned char *ptr = smalloc(&mp, size); + if (!ptr) return 0; - return ptr; + return ptr - ext_mem_base + LOWMEM_SIZE + HMASIZE; } -static void *xms_realloc(void *optr, unsigned osize, unsigned size) +static unsigned xms_realloc(unsigned dosptr, unsigned size) { - void *ptr = realloc_mapping(MAPPING_OTHER, optr, PAGE_ALIGN(osize), - PAGE_ALIGN(size)); - if (ptr == MAP_FAILED) + unsigned char *optr = &ext_mem_base[dosptr - (LOWMEM_SIZE + HMASIZE)]; + unsigned char *ptr = smrealloc(&mp, optr, size); + if (!ptr) return 0; - return ptr; + return ptr - ext_mem_base + LOWMEM_SIZE + HMASIZE; } -static void xms_free(void *addr, unsigned osize) +static void xms_free(unsigned addr) { - free_mapping(MAPPING_OTHER, addr, PAGE_ALIGN(osize)); -} - -static unsigned map_EMB(void *addr, unsigned size, unsigned handle) -{ - int page, rc; - unsigned ret = 0; - - page = pgaalloc(pgapool, PAGE_ALIGN(size) >> PAGE_SHIFT, handle); - if (page < 0) { - error("error allocating %i bytes for xms\n", size); - return ret; - } - ret = xms_base + (page << PAGE_SHIFT); - rc = alias_mapping_pa(MAPPING_EXTMEM, ret, PAGE_ALIGN(size), - PROT_READ | PROT_WRITE, addr); - if (rc == -1) { - error("failure to map xms\n"); - leavedos(2); - } - return ret; -} - -static void unmap_EMB(unsigned base, unsigned size) -{ - e_invalidate_full_pa(base, PAGE_ALIGN(size)); - unalias_mapping_pa(MAPPING_DPMI, base, PAGE_ALIGN(size)); - pgafree(pgapool, (base - xms_base) >> PAGE_SHIFT); -} - -#if 0 -/* unused */ -void *xms_resolve_physaddr(unsigned addr) -{ - struct pgrm m; - assert(addr >= xms_base && addr < xms_base + XMS_SIZE); - m = pgarmap(pgapool, (addr - xms_base) >> PAGE_SHIFT); - if (m.pgoff == -1) - return MAP_FAILED; - assert(m.id >= 0 && m.id < NUM_HANDLES && handles[m.id].addr); - return (handles[m.id].addr + (m.pgoff << PAGE_SHIFT) + - (addr & (PAGE_SIZE - 1))); -} -#endif - -static void do_free_EMB(int h) -{ - if (handles[h].dst) - unmap_EMB(handles[h].dst, handles[h].size); - handles[h].dst = 0; - if (handles[h].addr) - xms_free(handles[h].addr, handles[h].size); - handles[h].addr = NULL; + smfree(&mp, &ext_mem_base[addr - (LOWMEM_SIZE + HMASIZE)]); } void xms_reset(void) { - int i; - if (umbs_used) { umb_free_all(); memcheck_map_free('U'); } - - for (i = 0; i < NUM_HANDLES; i++) - do_free_EMB(i); - handle_count = 0; - totalBytes = 0; - intdrv = 0; - freeHMA = 0; - ext_hooked_hma = 0; - a20_global = a20_local = 0; - pgareset(pgapool); -} - -static void xms_local_reset(void) -{ + config.xms_size = 0; intdrv = 0; } @@ -336,36 +249,37 @@ static void xx_printf(int prio, const char *fmt, ...) int xms_intdrv(void) { - return (intdrv || ext_hooked_hma); + return intdrv; } -uint16_t xms_install_check(void) +static void xms_helper_init(void) { - /* for ext_hooked_hma return special code which is recognized by our drv */ - return (intdrv ? 0x80 : 0x8180); -} + int i; + + NOCARRY; /* report success */ -static int xms_helper_init(void) -{ if (intdrv) - return 1; + return; + intdrv = 1; + config.xms_size = EXTMEM_SIZE >> 10; x_printf("XMS: initializing XMS... %d handles\n", NUM_HANDLES); - freeHMA = (config.hma && !ext_hooked_hma); - ext_hooked_hma = 0; + freeHMA = 1; + a20_global = a20_local = 0; if (!config.xms_size) - return 0; - intdrv = 1; - return 1; -} + return; + handle_count = 0; + for (i = 0; i < NUM_HANDLES; i++) { + if (handles[i].valid && handles[i].addr) + xms_free(handles[i].addr); + handles[i].valid = 0; + } -int xms_helper_init_ext(void) -{ - assert(!intdrv); - ext_hooked_hma = (xms_helper_init() && freeHMA); - return ext_hooked_hma; + smdestroy(&mp); + sminit(&mp, ext_mem_base, config.xms_size * 1024); + smregister_error_notifier(&mp, xx_printf); } void xms_helper(void) @@ -375,8 +289,7 @@ void xms_helper(void) switch (HI(ax)) { case XMS_HELPER_XMS_INIT: - if (!xms_helper_init()) - CARRY; + xms_helper_init(); break; case XMS_HELPER_GET_ENTRY_POINT: @@ -453,14 +366,9 @@ void xms_helper(void) } } -void xms_init(void) +void +xms_init(void) { - pgapool = pgainit(XMS_SIZE >> PAGE_SHIFT); -} - -void xms_done(void) -{ - pgadone(pgapool); } static void XMS_RET(int err) @@ -479,7 +387,6 @@ void xms_control(void) { int is_umb_fn = 0; - clear_ZF(); /* First do the UMB functions */ switch (HI(ax)) { case XMS_ALLOCATE_UMB: @@ -508,8 +415,6 @@ void xms_control(void) Debug0((dbg_fd, "Allocate UMB Success\n")); XMS_RET(0); LWORD(ebx) = addr >> 4; - if (addr > 0xfffff) - CARRY; LWORD(edx) = size >> 4; Debug0((dbg_fd, "umb_allocated: %#x:%#x\n", addr, size)); } @@ -528,7 +433,7 @@ void xms_control(void) break; } - case XMS_REALLOCATE_UMB: + case 0x12: is_umb_fn = 1; x_printf("XMS realloc UMB segment 0x%04x size 0x%04x\n", LWORD(edx), LWORD(ebx)); @@ -538,7 +443,7 @@ void xms_control(void) if (intdrv && !is_umb_fn) { switch (HI(ax)) { - case XMS_GET_VERSION: /* Get XMS Version Number */ + case 0: /* Get XMS Version Number */ LWORD(eax) = XMS_VERSION; LWORD(ebx) = XMS_DRIVER_VERSION; LWORD(edx) = 1; /* HMA exists */ @@ -546,14 +451,12 @@ void xms_control(void) LWORD(eax), LWORD(ebx)); break; - case XMS_ALLOCATE_HIGH_MEMORY: /* Request High Memory Area */ + case 1: /* Request High Memory Area */ x_printf("XMS request HMA size 0x%04x\n", LWORD(edx)); if (freeHMA) { x_printf("XMS: allocating HMA size 0x%04x\n", LWORD(edx)); freeHMA = 0; XMS_RET(0); /* no error */ - if (ext_hooked_hma) // drop external hma hook - xms_local_reset(); } else { x_printf("XMS: HMA already allocated\n"); @@ -561,7 +464,7 @@ void xms_control(void) } break; - case XMS_FREE_HIGH_MEMORY: /* Release High Memory Area */ + case 2: /* Release High Memory Area */ x_printf("XMS release HMA\n"); if (freeHMA) { x_printf("XMS: HMA already free\n"); @@ -569,12 +472,12 @@ void xms_control(void) } else { x_printf("XMS: freeing HMA\n"); - freeHMA = config.hma; + freeHMA = 1; XMS_RET(0); /* no error */ } break; - case XMS_GLOBAL_ENABLE_A20: /* Global Enable A20 */ + case 3: /* Global Enable A20 */ x_printf("XMS global enable A20\n"); if (!a20_global) set_a20(1); /* map in HMA */ @@ -582,7 +485,7 @@ void xms_control(void) XMS_RET(0); /* no error */ break; - case XMS_GLOBAL_DISABLE_A20: /* Global Disable A20 */ + case 4: /* Global Disable A20 */ x_printf("XMS global disable A20\n"); if (a20_global) set_a20(0); @@ -590,7 +493,7 @@ void xms_control(void) XMS_RET(0); /* no error */ break; - case XMS_LOCAL_ENABLE_A20: /* Local Enable A20 */ + case 5: /* Local Enable A20 */ x_printf("XMS LOCAL enable A20\n"); if (!a20_local) set_a20(1); @@ -598,11 +501,11 @@ void xms_control(void) XMS_RET(0); /* no error */ break; - case XMS_LOCAL_DISABLE_A20: /* Local Disable A20 */ + case 6: /* Local Disable A20 */ x_printf("XMS LOCAL disable A20\n"); if (a20_local) a20_local--; - if (!a20_local && !a20_global) + if (!a20_local) set_a20(0); XMS_RET(0); /* no error */ break; @@ -610,58 +513,58 @@ void xms_control(void) /* DOS, if loaded as "dos=high,umb" will continually poll * the A20 line. */ - case XMS_QUERY_A20: /* Query A20 */ + case 7: /* Query A20 */ LWORD(eax) = a20 ? 1 : 0; LO(bx) = 0; /* no error */ break; - case XMS_QUERY_FREE_EXTENDED_MEMORY: /* Query Free Extended Memory */ + case 8: /* Query Free Extended Memory */ xms_query_freemem(OLDXMS); break; - case XMS_ALLOCATE_EXTENDED_MEMORY: /* Allocate Extended Memory Block */ + case 9: /* Allocate Extended Memory Block */ XMS_RET(xms_allocate_EMB(OLDXMS)); break; - case XMS_FREE_EXTENDED_MEMORY: /* Free Extended Memory Block */ + case 0xa: /* Free Extended Memory Block */ XMS_RET(xms_free_EMB()); break; - case XMS_MOVE_EXTENDED_MEMORY_BLOCK: /* Move Extended Memory Block */ + case 0xb: /* Move Extended Memory Block */ XMS_RET(xms_move_EMB()); break; - case XMS_LOCK_EXTENDED_MEMORY_BLOCK: /* Lock Extended Memory Block */ + case 0xc: /* Lock Extended Memory Block */ XMS_RET(xms_lock_EMB(1)); break; - case XMS_UNLOCK_EXTENDED_MEMORY_BLOCK: /* Unlock Extended Memory Block */ + case 0xd: /* Unlock Extended Memory Block */ XMS_RET(xms_lock_EMB(0)); break; - case XMS_GET_EMB_HANDLE_INFORMATION: /* Get EMB Handle Information */ + case 0xe: /* Get EMB Handle Information */ XMS_RET(xms_EMB_info(OLDXMS)); break; - case XMS_RESIZE_EXTENDED_MEMORY_BLOCK: /* Reallocate Extended Memory Block */ + case 0xf: /* Reallocate Extended Memory Block */ XMS_RET(xms_realloc_EMB(OLDXMS)); break; /* the functions below are the newer, 32-bit XMS 3.0 interface */ - case 0x80|XMS_QUERY_FREE_EXTENDED_MEMORY: /* Query Any Free Extended Memory */ + case 0x88: /* Query Any Free Extended Memory */ xms_query_freemem(NEWXMS); break; - case 0x80|XMS_ALLOCATE_EXTENDED_MEMORY: /* Allocate Extended Memory */ + case 0x89: /* Allocate Extended Memory */ XMS_RET(xms_allocate_EMB(NEWXMS)); break; - case 0x80|XMS_GET_EMB_HANDLE_INFORMATION: /* Get EMB Handle Information */ + case 0x8e: /* Get EMB Handle Information */ XMS_RET(xms_EMB_info(NEWXMS)); break; - case 0x80|XMS_RESIZE_EXTENDED_MEMORY_BLOCK: /* Reallocate EMB */ + case 0x8f: /* Reallocate EMB */ XMS_RET(xms_realloc_EMB(NEWXMS)); break; @@ -672,15 +575,15 @@ void xms_control(void) } } /* If this is the UMB request which came via the external himem.sys, - * don't pass it back. */ + * dont pass it back. */ if (!intdrv) { if (is_umb_fn) - set_ZF(); // tell our hook to skip external himem call + LWORD(esp) += 4; else x_printf("XMS: skipping external request, ax=0x%04x, dx=0x%04x\n", LWORD(eax), LWORD(edx)); } - LWORD(eip)++; // skip hlt in bios.s + LWORD(eip)++; } static int @@ -690,7 +593,7 @@ FindFreeHandle(int start) /* first free handle is 1 */ for (i = start; (i < NUM_HANDLES) && (h == 0); i++) { - if (!handles[i].addr) { + if (!handles[i].valid) { x_printf("XMS: found free handle: %d\n", i); h = i; break; @@ -704,7 +607,7 @@ FindFreeHandle(int start) static int ValidHandle(unsigned short h) { - if ((h < NUM_HANDLES) && (handles[h].addr)) + if ((h < NUM_HANDLES) && (handles[h].valid)) return 1; else return 0; @@ -713,9 +616,10 @@ ValidHandle(unsigned short h) static unsigned char xms_query_freemem(int api) { - unsigned subtotal, largest; + unsigned totalBytes = 0, subtotal, largest; + int h; - if (!intdrv) { + if (!config.xms_size) { if (api == OLDXMS) { LWORD(eax) = 0; LWORD(edx) = 0; @@ -734,11 +638,24 @@ xms_query_freemem(int api) if (api == NEWXMS) x_printf("XMS: new XMS API query_freemem()!\n"); - /* xms_size is page-aligned in config.c */ + /* total XMS mem and largest block can be different because of + * fragmentation + */ + + totalBytes = 0; + for (h = FIRST_HANDLE; h < NUM_HANDLES; h++) { + if (ValidHandle(h)) + totalBytes += handles[h].size; + } + subtotal = config.xms_size - (totalBytes / 1024); + if (debug_level('x')) { + if (smget_free_space(&mp) != subtotal * 1024) + x_printf("XMS smalloc mismatch!!!\n"); + } /* total free is max allowable XMS - the number of K already allocated */ - largest = pgaavail_largest(pgapool) * 4; - largest = largest ? _min(largest, subtotal) : subtotal; + + largest = smget_largest_free_area(&mp) / 1024; if (api == OLDXMS) { /* old XMS API uses only AX, while new API uses EAX. make @@ -760,7 +677,7 @@ xms_query_freemem(int api) else { REG(eax) = largest; REG(edx) = subtotal; - REG(ecx) = main_pool.size - 1; + REG(ecx) = (config.xms_size * 1024 + LOWMEM_SIZE + HMASIZE) - 1; x_printf("XMS query free memory(new): %dK %dK\n", REG(eax), REG(edx)); } @@ -773,10 +690,10 @@ static unsigned char xms_allocate_EMB(int api) { unsigned int h; - unsigned int kbsize, size; - void *addr; + unsigned int kbsize; + unsigned addr; - if (!intdrv) + if (!config.xms_size) return 0xa0; if (api == OLDXMS) @@ -789,23 +706,19 @@ xms_allocate_EMB(int api) x_printf("XMS: out of handles\n"); return 0xa1; } - size = kbsize * 1024; if (kbsize == 0) { x_printf("XMS WARNING: allocating 0 size EMB\n"); - return 0xa0; - } else if (totalBytes + size > config.xms_size * 1024) { - error("XMS: OOM allocating %i bytes EMB\n", size); - return 0xa0; + addr = 0; } else { - addr = xms_alloc(size); + addr = xms_alloc(kbsize*1024); if (!addr) { x_printf("XMS: out of memory\n"); return 0xa0; /* Out of memory */ } - totalBytes += size; } handles[h].num = h; - handles[h].size = size; + handles[h].valid = 1; + handles[h].size = kbsize*1024; handles[h].addr = addr; x_printf("XMS: EMB size %d bytes\n", handles[h].size); @@ -818,7 +731,7 @@ xms_allocate_EMB(int api) handles[h].lockcount = 0; handle_count++; - x_printf("XMS: allocated EMB %u at %p\n", h, handles[h].addr); + x_printf("XMS: allocated EMB %u at %#x\n", h, handles[h].addr); if (api == OLDXMS) LWORD(edx) = h; /* handle # */ @@ -837,8 +750,13 @@ xms_free_EMB(void) return 0xa2; } else { - totalBytes -= handles[h].size; - do_free_EMB(h); + + if (handles[h].addr) + xms_free(handles[h].addr); + else + x_printf("XMS WARNING: freeing handle w/no address, size 0x%08x\n", + handles[h].size); + handles[h].valid = 0; handle_count--; x_printf("XMS: free'd EMB %d\n", h); @@ -850,60 +768,46 @@ static unsigned char xms_move_EMB(void) { unsigned int src, dest; - void *s, *d; struct EMM e; MEMCPY_2UNIX(&e, SEGOFF2LINEAR(SREG(ds), LWORD(esi)), sizeof e); x_printf("XMS move extended memory block\n"); show_emm(e); - /* Length must be even, XMS spec says, tested on himem too. */ - if (e.Length & 1) - return 0xa7; - if (e.SourceHandle == 0) { src = SEGOFF2LINEAR(e.SourceOffset >> 16, e.SourceOffset & 0xffff); - if (src + e.Length > LOWMEM_SIZE + HMASIZE) - return 0xa7; /* invalid Length */ - s = LINEAR2UNIX(src); } else { - if (e.SourceHandle >= NUM_HANDLES || !handles[e.SourceHandle].addr) { + if (e.SourceHandle >= NUM_HANDLES || handles[e.SourceHandle].valid == 0) { x_printf("XMS: invalid source handle\n"); return 0xa3; } - if (e.SourceOffset > handles[e.SourceHandle].size) + src = handles[e.SourceHandle].addr + e.SourceOffset; + if (src > handles[e.SourceHandle].addr + handles[e.SourceHandle].size) return 0xa4; /* invalid source offset */ - if (e.SourceOffset + e.Length > handles[e.SourceHandle].size) + if (src + e.Length > handles[e.SourceHandle].addr + handles[e.SourceHandle].size) return 0xa7; /* invalid Length */ - s = handles[e.SourceHandle].addr + e.SourceOffset; } if (e.DestHandle == 0) { dest = SEGOFF2LINEAR(e.DestOffset >> 16, e.DestOffset & 0xffff); - if (dest + e.Length > LOWMEM_SIZE + HMASIZE) - return 0xa7; /* invalid Length */ - e_invalidate(dest, e.Length); - d = LINEAR2UNIX(dest); } else { - if (!handles[e.DestHandle].addr) { + if (handles[e.DestHandle].valid == 0) { x_printf("XMS: invalid dest handle\n"); return 0xa5; } - if (e.DestOffset > handles[e.DestHandle].size) + dest = handles[e.DestHandle].addr + e.DestOffset; + if (dest > handles[e.DestHandle].addr + handles[e.DestHandle].size) return 0xa6; /* invalid dest offset */ - if (e.DestOffset + e.Length > handles[e.DestHandle].size) { + if (dest + e.Length > handles[e.DestHandle].addr + handles[e.DestHandle].size) { return 0xa7; /* invalid Length */ } - if (handles[e.DestHandle].dst) // .pa is set if mapped, invalidate on va - e_invalidate_pa(handles[e.DestHandle].dst + e.DestOffset, e.Length); - d = handles[e.DestHandle].addr + e.DestOffset; } - x_printf("XMS: block move from %p to %p len 0x%x\n", - s, d, e.Length); - memcpy(d, s, e.Length); + x_printf("XMS: block move from %#x to %#x len 0x%x\n", + src, dest, e.Length); + extmem_copy(dest, src, e.Length); x_printf("XMS: block move done\n"); return 0; @@ -915,38 +819,28 @@ xms_lock_EMB(int flag) int h = LWORD(edx); unsigned addr; + if (flag) + x_printf("XMS lock EMB %d\n", h); + else + x_printf("XMS unlock EMB %d\n", h); + if (ValidHandle(h)) { /* flag=1 locks, flag=0 unlocks */ - if (!flag) { + if (flag) + handles[h].lockcount++; + else if (handles[h].lockcount) handles[h].lockcount--; else { x_printf("XMS: Unlock handle %d already at 0\n", h); return 0xaa; /* Block is not locked */ } - if (!handles[h].lockcount) { - x_printf("XMS unlock EMB %d --> %#x\n", h, handles[h].dst); - unmap_EMB(handles[h].dst, handles[h].size); - handles[h].dst = 0; - } - return 0; - } - if (handles[h].lockcount) - addr = handles[h].dst; - else - addr = map_EMB(handles[h].addr, handles[h].size, h); - if (addr) { - handles[h].lockcount++; - x_printf("XMS lock EMB %d --> %#x\n", h, addr); - handles[h].dst = addr; - LWORD(edx) = addr >> 16; - LWORD(ebx) = addr & 0xffff; - return 0; - } - x_printf("XMS lock EMB %d failed\n", h); - return 0xad; /* lock failed */ + addr = handles[h].addr; + LWORD(edx) = addr >> 16; + LWORD(ebx) = addr & 0xffff; + return 0; } else { x_printf("XMS: invalid handle %d, can't (un)lock\n", h); @@ -983,8 +877,7 @@ static unsigned char xms_realloc_EMB(int api) { int h; - unsigned int newsize; - void *newaddr; + unsigned int newaddr, newsize; h = LWORD(edx); @@ -1011,7 +904,7 @@ xms_realloc_EMB(int api) x_printf("XMS realloc EMB(%s) %d to size 0x%04x\n", api == OLDXMS ? "old" : "new", h, newsize); - newaddr = xms_realloc(handles[h].addr, handles[h].size, newsize); + newaddr = xms_realloc(handles[h].addr, newsize); if (!newaddr) { x_printf("XMS: out of memory on realloc\n"); return 0xa0; /* Out of memory */ diff --git a/src/dosext/net/Makefile b/src/dosext/net/Makefile index 5665b94..ec0a0fa 100644 --- a/src/dosext/net/Makefile +++ b/src/dosext/net/Makefile @@ -27,7 +27,7 @@ ALL = $(CFILES) $(HFILES) libpacket.c.multi libpacket.c.single \ pktnew.c.multi pktnew.c.single README -all: lib +all: lib install: diff --git a/src/dosext/net/ipx.c b/src/dosext/net/ipx.c index ac42203..ec33f07 100644 --- a/src/dosext/net/ipx.c +++ b/src/dosext/net/ipx.c @@ -23,19 +23,15 @@ #include "ipx_wrp.h" #include #include -#include #include "emu.h" #include "timers.h" #include "sig.h" #include "cpu.h" #include "int.h" -#include "hlt.h" -#include "virq.h" #include "emudpmi.h" #include "bios.h" #include "coopth.h" -#include "ioselect.h" #include "ipx.h" #ifdef IPX @@ -47,23 +43,17 @@ /* declare some function prototypes */ static u_char IPXCancelEvent(far_t ECBPtr); -static enum VirqSwRet ipx_recv_esr_call(void *arg); -static enum VirqSwRet ipx_aes_esr_call(void *arg); -static int recv_tid, aes_tid, int7a_tid; -static uint16_t ipx_hlt; +static void ipx_recv_esr_call(void); +static void ipx_aes_esr_call(void); +static int recv_tid, aes_tid; static ipx_socket_t *ipx_socket_list = NULL; -static fd_set act_fds; -static pthread_mutex_t fds_mtx = PTHREAD_MUTEX_INITIALIZER; /* hopefully these static ECBs will not cause races... */ static far_t recvECB; static far_t aesECB; static void AESTimerTick(void); static void ipx_recv_esr_call_thr(void *arg); static void ipx_aes_esr_call_thr(void *arg); -static void do_int7a(void); -static enum VirqHwRet ipx_receive(void *arg); -static enum VirqHwRet IPXCheckForAESReady(void *arg); /* DANG_FIXTHIS - get a real value for my address !! */ static unsigned char MyAddress[10] = @@ -125,22 +115,9 @@ static int GetMyAddress(unsigned long ipx_net, unsigned char *MyAddress) return(0); } -static void ipx_int7a_thr(void *arg) -{ - do_int7a(); -} - -static void ipx_call(uint16_t idx, HLT_ARG(arg)) -{ - fake_retf(); - coopth_start(int7a_tid, NULL); -} - void ipx_init(void) { int ccode; - emu_hlt_t hlt_hdlr = HLT_INITIALIZER; - if (!config.ipxsup) return; ccode = GetMyAddress(config.ipx_net, MyAddress); @@ -150,20 +127,13 @@ void ipx_init(void) config.ipx_net); return; } - virq_register(VIRQ_IPX, ipx_receive, ipx_recv_esr_call, NULL); - virq_register(VIRQ_IPX_AES, IPXCheckForAESReady, ipx_aes_esr_call, NULL); + pic_seti(PIC_IPX, ipx_receive, 0, ipx_recv_esr_call); + pic_seti(PIC_IPX_AES, IPXCheckForAESReady, 0, ipx_aes_esr_call); recv_tid = coopth_create("IPX receiver callback", ipx_recv_esr_call_thr); aes_tid = coopth_create("IPX aes callback", ipx_aes_esr_call_thr); - int7a_tid = coopth_create("IPX int7a", ipx_int7a_thr); - - hlt_hdlr.name = "ipx"; - hlt_hdlr.func = ipx_call; - ipx_hlt = hlt_register_handler_vm86(hlt_hdlr); sigalrm_register_handler(AESTimerTick); - - FD_ZERO(&act_fds); } /************************* @@ -174,10 +144,10 @@ void ipx_init(void) int IPXInt2FHandler(void) { LO(ax) = 0xff; - SREG(es) = BIOS_HLT_BLK_SEG; - LWORD(edi) = ipx_hlt; + SREG(es) = IPX_SEG; + LWORD(edi) = IPX_OFF; n_printf("IPX: request for IPX far call handler address %x:%x\n", - BIOS_HLT_BLK_SEG, ipx_hlt); + IPX_SEG, IPX_OFF); return 1; } @@ -329,15 +299,10 @@ static void printIPXHeader(IPXPacket_t * IPXHeader) } } -static void ipx_async_callback(int fd, void *arg) +static void ipx_async_callback(void *arg) { - fd_set *fds = arg; - - pthread_mutex_lock(&fds_mtx); - FD_SET(fd, fds); - pthread_mutex_unlock(&fds_mtx); n_printf("IPX: requesting receiver IRQ\n"); - virq_raise(VIRQ_IPX); + pic_request(PIC_IPX); } static u_char IPXOpenSocket(u_short port, u_short * newPort) @@ -414,7 +379,7 @@ static u_char IPXOpenSocket(u_short port, u_short * newPort) /* if we successfully bound to this port, then record it */ ipx_insert_socket(port, /* PSP */ 0, sock); - add_to_io_select_masked(sock, ipx_async_callback, &act_fds); + add_to_io_select(sock, ipx_async_callback, NULL); n_printf("IPX: successfully opened socket %i, %04x\n", sock, port); *newPort = port; return (RCODE_SUCCESS); @@ -515,32 +480,22 @@ static void ipx_recv_esr_call_thr(void *arg) { n_printf("IPX: Calling receive ESR\n"); ipx_esr_call(recvECB, ESR_CALLOUT_IPX); - recvECB = FAR_NULL; } -static enum VirqSwRet ipx_recv_esr_call(void *arg) +static void ipx_recv_esr_call(void) { - if (recvECB.segment) { - coopth_start(recv_tid, NULL); - return VIRQ_SWRET_BH; - } - return VIRQ_SWRET_DONE; + coopth_start(recv_tid, NULL); } static void ipx_aes_esr_call_thr(void *arg) { n_printf("IPX: Calling AES ESR\n"); ipx_esr_call(aesECB, ESR_CALLOUT_AES); - aesECB = FAR_NULL; } -static enum VirqSwRet ipx_aes_esr_call(void *arg) +static void ipx_aes_esr_call(void) { - if (aesECB.segment) { - coopth_start(aes_tid, NULL); - return VIRQ_SWRET_BH; - } - return VIRQ_SWRET_DONE; + coopth_start(aes_tid, NULL); } static u_char IPXSendPacket(far_t ECBPtr) @@ -742,7 +697,7 @@ static void AESTimerTick(void) ECB->TimeLeft, ECB); if (ECB->TimeLeft == 0) { /* now setup to call the ESR for this event */ - virq_raise(VIRQ_IPX_AES); + pic_request(PIC_IPX_AES); return; } } @@ -752,6 +707,22 @@ static void AESTimerTick(void) } } +static int ipx_fdset(fd_set * set) +{ + ipx_socket_t *s; + int max_fd = -1; + + s = ipx_socket_list; + while (s != NULL) { + FD_SET(s->fd, set); + if (s->fd > max_fd) + max_fd = s->fd; + s = s->next; + } + + return max_fd; +} + static int ScatterFragmentData(int size, unsigned char *buffer, ECB_t * ECB, struct sockaddr_ipx *sipx) { @@ -824,7 +795,7 @@ static int IPXReceivePacket(ipx_socket_t * s) socklen_t sz; sz = sizeof(ipxs); - size = recvfrom(s->fd, buffer, sizeof(buffer), MSG_DONTWAIT, (struct sockaddr*)&ipxs, &sz); + size = recvfrom(s->fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&ipxs, &sz); n_printf("IPX: received %d bytes of data\n", size); if (size > 0 && s->listenCount) { ECBPtr = s->listenList; @@ -846,7 +817,7 @@ static int IPXReceivePacket(ipx_socket_t * s) return 0; } -static enum VirqHwRet IPXCheckForAESReady(void *arg) +int IPXCheckForAESReady(int ilevel) { ipx_socket_t *s; far_t ECBPtr; @@ -867,14 +838,14 @@ static enum VirqHwRet IPXCheckForAESReady(void *arg) if (rcode == RCODE_SUCCESS) { ECBp->CompletionCode = CC_SUCCESS; } - return VIRQ_HWRET_CONT; + return 1; /* run IRQ */ } ECBPtr = ECBp->Link; } } s = s->next; } - return VIRQ_HWRET_DONE; + return 0; } static ipx_socket_t *check_ipx_ready(fd_set * set) @@ -893,55 +864,56 @@ static ipx_socket_t *check_ipx_ready(fd_set * set) static void IPXRelinquishControl(void) { - idle_enable(5, 0, "IPX"); + idle_enable(0, 5, 0, "IPX"); } -static enum VirqHwRet _ipx_receive(void *arg) +int ipx_receive(int ilevel) { + /* DOS program has given us a time slice */ + /* let's use this as an opportunity to poll outstanding listens */ + fd_set fds; + int selrtn; + int max_fd; ipx_socket_t *s; + far_t ECBPtr; + struct timeval timeout; - if ((s = check_ipx_ready(&act_fds))) { - far_t ECBPtr = s->listenList; + FD_ZERO(&fds); - if (IPXReceivePacket(s)) { - if (FARt_PTR2(ECBp->ESRAddress)) - recvECB = ECBPtr; - return VIRQ_HWRET_CONT; - } - ioselect_complete(s->fd); - FD_CLR(s->fd, &act_fds); - n_printf("IPX: completed fd %i\n", s->fd); - } else { - int i; + max_fd = ipx_fdset(&fds); + if (max_fd == -1) + return 0; - for (i = 0; i < FD_SETSIZE; i++) { - if (FD_ISSET(i, &act_fds)) { - remove_from_io_select(i); - FD_CLR(i, &act_fds); - error("IPX: removing stalled fd %i\n", i); + timeout.tv_sec = 0; + timeout.tv_usec = 0; + n_printf("IPX: select\n"); + + switch ((selrtn = select(max_fd + 1, &fds, NULL, NULL, &timeout))) { + case 0: /* none ready */ + /* n_printf("IPX: no receives ready\n"); */ + break; + + case -1: /* error (not EINTR) */ + error("bad ipc_select: %s\n", strerror(errno)); + break; + + default: /* has at least 1 descriptor ready */ + n_printf("IPX: receive ready (%i), checking fd\n", selrtn); + if ((s = check_ipx_ready(&fds))) { + ECBPtr = s->listenList; + if (IPXReceivePacket(s)) { + if (FARt_PTR2(ECBp->ESRAddress)) { + recvECB = ECBPtr; + return 1; /* run IRQ */ + } } } + break; } - return VIRQ_HWRET_DONE; -} - -static enum VirqHwRet ipx_receive(void *arg) -{ - enum VirqHwRet ret; - - pthread_mutex_lock(&fds_mtx); - ret = _ipx_receive(arg); - pthread_mutex_unlock(&fds_mtx); - return ret; + return 0; } int ipx_int7a(void) -{ - do_int7a(); - return 1; -} - -static void do_int7a(void) { u_short port; /* port here means DOS IPX socket */ u_short newPort; @@ -993,7 +965,7 @@ static void do_int7a(void) ECBPtr.segment = SREG(es); ECBPtr.offset = LWORD(esi); n_printf("IPX: send packet ECB at %p\n", ECBp); - /* What the hell is the async send? Do it synchronously! */ + /* What the hell is the async send? Do it synchroniously! */ ret = IPXSendPacket(ECBPtr); if ((ret == RCODE_SUCCESS) && FARt_PTR2(ECBp->ESRAddress)) ipx_esr_call(ECBPtr, ESR_CALLOUT_IPX); @@ -1075,6 +1047,7 @@ static void do_int7a(void) n_printf("IPX: Unimplemented function.\n"); break; } + return 1; } /* ipx_close is called on DOSEMU shutdown */ diff --git a/src/dosext/net/ipx_wrp.h b/src/dosext/net/ipx_wrp.h index 4b98529..f5a54c1 100644 --- a/src/dosext/net/ipx_wrp.h +++ b/src/dosext/net/ipx_wrp.h @@ -8,8 +8,6 @@ #define IPX_TYPE 1 #define SOL_IPX 256 #else -#ifdef __linux__ #warning no ipx.h #endif #endif -#endif diff --git a/src/dosext/net/ipxglt.c b/src/dosext/net/ipxglt.c index 5218706..c4b16a4 100644 --- a/src/dosext/net/ipxglt.c +++ b/src/dosext/net/ipxglt.c @@ -84,8 +84,6 @@ static int CheckRouteExist(unsigned long targetNet #if !TRUST_RTABLE char buf_net[9], buf_node[13]; #endif - int err; - sprintf(buf_targ, "%08lX", (unsigned long)htonl(targetNet)); #if !TRUST_RTABLE sprintf(buf_net, "%08lX", (unsigned long)htonl(network)); @@ -94,13 +92,11 @@ static int CheckRouteExist(unsigned long targetNet #endif if(access("/proc/net/ipx/route",R_OK) == 0) - err = open_proc_scan("/proc/net/ipx/route"); + open_proc_scan("/proc/net/ipx/route"); else if(access("/proc/net/ipx_route",R_OK) == 0) - err = open_proc_scan("/proc/net/ipx_route"); + open_proc_scan("/proc/net/ipx_route"); else return 0; - if (err) - return 0; proc_str = get_proc_string_by_key(buf_targ); if (!proc_str) { diff --git a/src/dosext/net/libpacket.c b/src/dosext/net/libpacket.c index 2a03128..b7bac80 100644 --- a/src/dosext/net/libpacket.c +++ b/src/dosext/net/libpacket.c @@ -3,10 +3,11 @@ * Placed under the GNU LGPL. * * First cut at a library of handy support routines. Comments, additions - * and bug fixes gratefully received. + * and bug fixes greatfully received. * * (c) 1994 Alan Cox iiitac@pyr.swan.ac.uk GW4PTS@GB7SWN */ +#ifdef HAVE_NETPACKET_PACKET_H #include #include #include @@ -17,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -26,9 +26,7 @@ #include #include "Linux/if_tun.h" #include -#ifdef HAVE_NETPACKET_PACKET_H #include -#endif #include #include @@ -52,7 +50,6 @@ static struct pkt_ops *ops[VNET_TYPE_MAX]; static int pkt_flags; static int early_fd; static int rcv_mode; -static int open_cnt; /* Should return a unique ID corresponding to this invocation of dosemu not clashing with other dosemus. We use a random value and @@ -78,7 +75,6 @@ static struct pkt_ops *find_ops(int id) return NULL; } -#ifdef HAVE_NETPACKET_PACKET_H /* * Obtain a file handle on a raw ethernet type. In actual fact * you can also request the dummy types for AX.25 or 802.3 also @@ -145,7 +141,6 @@ static int OpenNetworkLinkEth(const char *name, void (*cbk)(int, int)) cbk(s, receive_mode); return 0; } -#endif static int OpenNetworkLinkTap(const char *name, void (*cbk)(int, int)) { @@ -161,26 +156,6 @@ static int OpenNetworkLinkTap(const char *name, void (*cbk)(int, int)) return 0; } -static int OpenNetworkLinkSock(const char *name, void (*cbk)(int, int)) -{ - int pkt_fd, ret; - struct sockaddr_un saddr_un; - - saddr_un.sun_family = PF_UNIX; - strlcpy(saddr_un.sun_path, name, sizeof(saddr_un.sun_path)); - pkt_fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (pkt_fd < 0) - return pkt_fd; - ret = connect(pkt_fd, (struct sockaddr *)&saddr_un, sizeof(saddr_un)); - if (ret < 0) { - close(pkt_fd); - return ret; - } - cbk(pkt_fd, 6); - pd_printf("PKT: Using socket device %s\n", name); - return 0; -} - static void set_fd(int fd, int mode) { early_fd = fd; @@ -198,11 +173,8 @@ static int Open_sockets(const char *name, int vnet) int OpenNetworkLink(void (*cbk)(int, int)) { int ret = -1; - struct pkt_ops *o = NULL; -#define CB() ((o->flags & PFLG_ASYNC) ? cbk : set_fd) -#define BAD_OPS() (!o || ((o->flags & PFLG_ASYNC) && open_cnt > 1)) + struct pkt_ops *o; - open_cnt++; assert(early_fd != 0); if (early_fd != -1) { cbk(early_fd, rcv_mode); @@ -212,27 +184,7 @@ int OpenNetworkLink(void (*cbk)(int, int)) switch (config.vnet) { case VNET_TYPE_AUTO: pkt_set_flags(PKT_FLG_QUIET); - /* no break, try sock, slirp */ - case VNET_TYPE_SOCK: - if (config.netsock && config.netsock[0]) - o = find_ops(VNET_TYPE_SOCK); - if (!BAD_OPS()) { - ret = o->open(config.netsock, CB()); - if (ret < 0) { - if (config.vnet == VNET_TYPE_AUTO || open_cnt > 1) - warn("PKT: Cannot open sock\n"); - else - error("Unable to open sock\n"); - } else { - if (config.vnet == VNET_TYPE_AUTO) - config.vnet = VNET_TYPE_SOCK; - pd_printf("PKT: Using sock networking\n"); - break; - } - } else if (config.vnet == VNET_TYPE_SOCK && open_cnt == 1) { - error("Unable to open sock\n"); - } - /* no break, try slirp */ + /* no break, slirp default */ case VNET_TYPE_SLIRP: { if (!pkt_is_registered_type(VNET_TYPE_SLIRP)) { if (config.vnet != VNET_TYPE_AUTO) @@ -240,23 +192,21 @@ int OpenNetworkLink(void (*cbk)(int, int)) break; } o = find_ops(VNET_TYPE_SLIRP); - if (!BAD_OPS()) { - ret = o->open("slirp", CB()); - if (ret < 0) { - if (config.vnet == VNET_TYPE_AUTO || open_cnt > 1) - warn("PKT: Cannot run slirp\n"); - else - error("Unable to run slirp\n"); - } else { - if (config.vnet == VNET_TYPE_AUTO) - config.vnet = VNET_TYPE_SLIRP; - pd_printf("PKT: Using slirp networking\n"); - break; - } - } else if (config.vnet == VNET_TYPE_SLIRP && open_cnt == 1) { - error("Unable to open slirp\n"); + if (!o) + ret = -1; + else + ret = o->open("slirp", cbk); + if (ret < 0) { + if (config.vnet == VNET_TYPE_AUTO) + warn("PKT: Cannot run slirp\n"); + else + error("Unable to run slirp\n"); + } else { + if (config.vnet == VNET_TYPE_AUTO) + config.vnet = VNET_TYPE_SLIRP; + pd_printf("PKT: Using slirp networking\n"); } - /* no break, try VDE */ + break; } case VNET_TYPE_VDE: { const char *pr_dev = config.vdeswitch[0] ? config.vdeswitch : "(auto)"; @@ -266,35 +216,30 @@ int OpenNetworkLink(void (*cbk)(int, int)) break; } o = find_ops(VNET_TYPE_VDE); - if (!BAD_OPS()) { - ret = o->open(config.vdeswitch, CB()); - if (ret < 0) { - if (config.vnet == VNET_TYPE_AUTO || open_cnt > 1) - warn("PKT: Cannot run VDE %s\n", pr_dev); - else - error("Unable to run VDE %s\n", pr_dev); - } else { - if (config.vnet == VNET_TYPE_AUTO) - config.vnet = VNET_TYPE_VDE; - pd_printf("PKT: Using device %s\n", pr_dev); - break; - } - } else if (config.vnet == VNET_TYPE_VDE && open_cnt == 1) { - error("Unable to open VDE\n"); + if (!o) + ret = -1; + else + ret = o->open(config.vdeswitch, cbk); + if (ret < 0) { + if (config.vnet == VNET_TYPE_AUTO) + warn("PKT: Cannot run VDE %s\n", pr_dev); + else + error("Unable to run VDE %s\n", pr_dev); + } else { + if (config.vnet == VNET_TYPE_AUTO) + config.vnet = VNET_TYPE_VDE; + pd_printf("PKT: Using device %s\n", pr_dev); } - /* no break, try whatever remains */ + break; } } - if (ret != -1 && o && !(o->flags & PFLG_ASYNC)) - cbk(early_fd, rcv_mode); - if (ret == -1) - open_cnt--; return ret; } /* * Close a file handle to a raw packet type. */ + static void CloseNetworkLinkEth(int pkt_fd) { close(pkt_fd); @@ -302,10 +247,7 @@ static void CloseNetworkLinkEth(int pkt_fd) void CloseNetworkLink(int pkt_fd) { - if (!open_cnt) - return; - if (--open_cnt == 0) - find_ops(config.vnet)->close(pkt_fd); + find_ops(config.vnet)->close(pkt_fd); } /* @@ -318,7 +260,6 @@ void CloseNetworkLink(int pkt_fd) */ #define NET3 -#ifdef HAVE_NETPACKET_PACKET_H /* * Obtain the hardware address of an interface. * addr should be a buffer of 8 bytes or more. @@ -327,6 +268,7 @@ void CloseNetworkLink(int pkt_fd) * 0 Success, buffer holds data. * -1 Error. */ + static int GetDeviceHardwareAddressEth(unsigned char *addr) { int s; @@ -352,7 +294,6 @@ static int GetDeviceHardwareAddressEth(unsigned char *addr) return 0; } -#endif void pkt_get_fake_mac(unsigned char *addr) { @@ -378,7 +319,6 @@ int GetDeviceHardwareAddress(unsigned char *addr) return ret; } -#ifdef HAVE_NETPACKET_PACKET_H /* * Obtain the maximum packet size on an interface. * @@ -386,6 +326,7 @@ int GetDeviceHardwareAddress(unsigned char *addr) * >0 Return is the mtu of the interface * -1 Error. */ + static int GetDeviceMTUEth(void) { int s; @@ -405,12 +346,6 @@ static int GetDeviceMTUEth(void) return -1; return req.ifr_mtu; } -#endif - -static int GetDeviceMTUTap(void) -{ - return 1500; -} int GetDeviceMTU(void) { @@ -448,7 +383,7 @@ int tun_alloc(char *dev) enter_priv_on(); err = ioctl(fd, TUNSETIFF, (void *) &ifr); leave_priv_setting(); - if (err < 0) { + if (err < 0 ) { close(fd); return err; } @@ -478,41 +413,6 @@ static ssize_t pkt_read_eth(int pkt_fd, void *buf, size_t count) return read(pkt_fd, buf, count); } -static ssize_t pkt_read_sock(int pkt_fd, void *buf, size_t count) -{ - struct timeval tv; - fd_set readset; - uint32_t tmpbuf; - uint32_t len; - int ret; - - tv.tv_sec = 0; /* set a (small) timeout */ - tv.tv_usec = 0; - - /* anything ready? */ - FD_ZERO(&readset); - FD_SET(pkt_fd, &readset); - /* anything ready? */ - if (select(pkt_fd + 1, &readset, NULL, NULL, &tv) <= 0) - return 0; - - if(!FD_ISSET(pkt_fd, &readset)) - return 0; - - ret = read(pkt_fd, &tmpbuf, sizeof(tmpbuf)); - if (ret < 4) - return 0; - len = ntohl(tmpbuf); - if (len > count) { - error("PKT: buffer too small, %zi need %i\n", count, len); - len = count; - } - ret = read(pkt_fd, buf, len); - if (ret != len) - error("PKT: expected %i byes but got %i\n", len, ret); - return ret; -} - ssize_t pkt_read(int fd, void *buf, size_t count) { return find_ops(config.vnet)->pkt_read(fd, buf, count); @@ -523,13 +423,6 @@ static ssize_t pkt_write_eth(int pkt_fd, const void *buf, size_t count) return write(pkt_fd, buf, count); } -static ssize_t pkt_write_sock(int pkt_fd, const void *buf, size_t count) -{ - uint32_t len = htonl(count); - write(pkt_fd, &len, sizeof(len)); - return write(pkt_fd, buf, count); -} - ssize_t pkt_write(int fd, const void *buf, size_t count) { return find_ops(config.vnet)->pkt_write(fd, buf, count); @@ -543,7 +436,6 @@ int pkt_register_backend(struct pkt_ops *o) return idx; } -#ifdef HAVE_NETPACKET_PACKET_H static struct pkt_ops eth_ops = { .id = VNET_TYPE_ETH, .open = OpenNetworkLinkEth, @@ -553,24 +445,13 @@ static struct pkt_ops eth_ops = { .pkt_read = pkt_read_eth, .pkt_write = pkt_write_eth, }; -#endif - -static struct pkt_ops sock_ops = { - .id = VNET_TYPE_SOCK, - .open = OpenNetworkLinkSock, - .close = CloseNetworkLinkEth, - .get_hw_addr = GetDeviceHardwareAddressTap, - .get_MTU = GetDeviceMTUTap, - .pkt_read = pkt_read_sock, - .pkt_write = pkt_write_sock, -}; static struct pkt_ops tap_ops = { .id = VNET_TYPE_TAP, .open = OpenNetworkLinkTap, .close = CloseNetworkLinkEth, .get_hw_addr = GetDeviceHardwareAddressTap, - .get_MTU = GetDeviceMTUTap, + .get_MTU = GetDeviceMTUEth, .pkt_read = pkt_read_eth, .pkt_write = pkt_write_eth, }; @@ -581,11 +462,8 @@ void LibpacketInit(void) GenerateDosnetID(); -#ifdef HAVE_NETPACKET_PACKET_H pkt_register_backend(ð_ops); -#endif pkt_register_backend(&tap_ops); - pkt_register_backend(&sock_ops); #ifdef USE_DL_PLUGINS #ifdef USE_VDE @@ -596,7 +474,6 @@ void LibpacketInit(void) #endif #endif early_fd = -1; - /* Open sockets only for priv configs */ switch (config.vnet) { case VNET_TYPE_ETH: @@ -607,6 +484,21 @@ void LibpacketInit(void) else pd_printf("PKT: eth backend enabled, dev=%s\n", config.ethdev); break; + case VNET_TYPE_AUTO: + case VNET_TYPE_SLIRP: + ret = Open_sockets("slirp", VNET_TYPE_SLIRP); + if (ret < 0) { + if (config.vnet != VNET_TYPE_AUTO) { + error("PKT: Cannot open slirp\n"); + } else { + pd_printf("PKT: Cannot open slirp\n"); + } + } else { + if (config.vnet == VNET_TYPE_AUTO) + config.vnet = VNET_TYPE_SLIRP; + pd_printf("PKT: slirp backend enabled\n"); + } + break; case VNET_TYPE_TAP: { char devname[256]; if (!config.tapdev || !config.tapdev[0]) { @@ -645,3 +537,5 @@ static int pkt_is_registered_type(int type) { return !!find_ops(type); } + +#endif diff --git a/src/dosext/net/pktnew.c b/src/dosext/net/pktnew.c index c1271fe..8cb0d0a 100644 --- a/src/dosext/net/pktnew.c +++ b/src/dosext/net/pktnew.c @@ -45,12 +45,11 @@ #include #include #include "libpacket.h" -#include "virq.h" +#include "pic.h" #include "coopth.h" #include "hlt.h" #include "utilities.h" #include "emudpmi.h" -#include "ioselect.h" #ifndef ETH_FRAME_LEN #define ETH_FRAME_LEN 1514 @@ -73,10 +72,9 @@ static void pkt_hlt(Bit16u idx, HLT_ARG(arg)); static int Insert_Type(int, int, Bit8u *); static int Remove_Type(int); int Find_Handle(u_char *buf); -static void printbuf(const char *, struct ethhdr *, uint32_t len); -static int pkt_receive(void); -static enum VirqHwRet pkt_virq_receive(void *arg); -static enum VirqSwRet pkt_receiver_callback(void *arg); +static void printbuf(const char *, struct ethhdr *); +static int pkt_check_receive(int ilevel); +static void pkt_receiver_callback(void); static void pkt_receiver_callback_thr(void *arg); static void pkt_register_net_fd_and_mode(int fd, int mode); static Bit32u PKTRcvCall_TID; @@ -136,6 +134,16 @@ struct pkt_statistics *p_stats; /************************************************************************/ +/* initialize the packet driver interface (called at startup) */ +void pkt_priv_init(void) +{ + if (!config.pktdrv) + return; + + /* initialize the globals */ + LibpacketInit(); +} + void pkt_init(void) { @@ -158,7 +166,7 @@ pkt_init(void) p_stats = MK_FP32(BIOSSEG, PKTDRV_stats); pd_printf("PKT: VNET mode is %i\n", config.vnet); - virq_register(VIRQ_PKT, pkt_virq_receive, pkt_receiver_callback, NULL); + pic_seti(PIC_NET, pkt_check_receive, 0, pkt_receiver_callback); /* fill other global data */ @@ -382,7 +390,7 @@ static int pkt_int(void) p_stats->bytes_out += LWORD(ecx); pd_printf("========Sending packet======\n"); - printbuf("packet to send:", SEG_ADR((struct ethhdr *), ds, si), LWORD(ecx)); + printbuf("packet to send:", SEG_ADR((struct ethhdr *), ds, si)); if (pg.flags & FLAG_NOVELL) /* Novell hack? */ { char *p; @@ -500,15 +508,15 @@ static void pkt_hlt(Bit16u idx, HLT_ARG(arg)) pkt_int(); } -static void pkt_receive_req_async(int fd, void *arg) +static void pkt_receive_req_async(void *arg) { - virq_raise(VIRQ_PKT); + pic_request(PIC_NET); } static void pkt_register_net_fd_and_mode(int fd, int mode) { pkt_fd = fd; - add_to_io_select_masked(pkt_fd, pkt_receive_req_async, NULL); + add_to_io_select(pkt_fd, pkt_receive_req_async, NULL); receive_mode = mode; local_receive_mode = mode; pd_printf("PKT: detected receive mode %i\n", mode); @@ -562,13 +570,10 @@ Remove_Type(int handle) return 0; } -static enum VirqSwRet pkt_receiver_callback(void *arg) +static void pkt_receiver_callback(void) { - if (p_helper_size) { - coopth_start(PKTRcvCall_TID, NULL); - return VIRQ_SWRET_BH; - } - return VIRQ_SWRET_DONE; + assert(p_helper_size); + coopth_start(PKTRcvCall_TID, NULL); } static void pkt_receiver_callback_thr(void *arg) @@ -594,6 +599,9 @@ static void pkt_receiver_callback_thr(void *arg) out: p_helper_size = 0; REGS = rcv_saved_regs; + + /* check for next frame */ + pic_request(PIC_NET); } static int pkt_receive(void) @@ -656,7 +664,7 @@ static int pkt_receive(void) p_stats->packets_in++; p_stats->bytes_in += size; - printbuf("received packet:", (struct ethhdr *)pkt_buf, size); + printbuf("received packet:", (struct ethhdr *)pkt_buf); /* stuff things in global vars and queue a hardware */ /* interrupt which will perform the upcall */ if (p_helper_size) @@ -676,13 +684,11 @@ static int pkt_receive(void) return 0; } -static enum VirqHwRet pkt_virq_receive(void *arg) +static int pkt_check_receive(int ilevel) { - int rc = pkt_receive(); - if (rc) - return VIRQ_HWRET_CONT; - ioselect_complete(pkt_fd); - return VIRQ_HWRET_DONE; + if (pkt_receive()) + return 1; /* run IRQ */ + return 0; } /* Find_Handle does type demultiplexing. @@ -713,27 +719,23 @@ Find_Handle(u_char *buf) return -1; } -static void printbuf(const char *mesg, struct ethhdr *buf, uint32_t len) +static void printbuf(const char *mesg, struct ethhdr *buf) { int i; u_char *p; - pd_printf("%s :\n Dest=", mesg); + pd_printf("%s :\n Dest.=", mesg); for (i = 0; i < 6; i++) - pd_printf("%02x:", buf->h_dest[i]); + pd_printf("%x:", buf->h_dest[i]); pd_printf(" Source="); for (i = 0; i < 6; i++) - pd_printf("%02x:", buf->h_source[i]); - if (ntohs(buf->h_proto) >= 1536) + pd_printf("%x:", buf->h_source[i]); + if (ntohs(buf->h_proto) >= 1536) { + p = (u_char *)buf + 2 * ETH_ALEN; /* Ethernet-II */ pd_printf(" Ethernet-II;"); - else + } else { + p = (u_char *)buf + 2 * ETH_ALEN + 2; /* All the rest frame types. */ pd_printf(" 802.3;"); - p = (u_char *)buf + 2 * ETH_ALEN + 4; - pd_printf(" Type/len=0x%x \n", ntohs(*(u_short *)p)); - p += 2; - len -= p - (u_char *)buf; - pd_printf(" Payload:\n"); - for (i = 0; i < len; i++) - pd_printf(" %02x", p[i]); - pd_printf("\n"); + } + pd_printf(" Type= 0x%x \n", ntohs(*(u_short *)p)); } diff --git a/src/include/Asm/ldt.h b/src/include/Asm/ldt.h index d62ac5d..ac5dc87 100644 --- a/src/include/Asm/ldt.h +++ b/src/include/Asm/ldt.h @@ -4,6 +4,9 @@ * * Definitions of structures used with the modify_ldt system call. */ +#ifdef __linux__ +#include +#else #ifndef _ASM_X86_LDT_H #define _ASM_X86_LDT_H @@ -46,3 +49,4 @@ struct user_desc { #endif /* !__ASSEMBLY__ */ #endif /* _ASM_X86_LDT_H */ +#endif diff --git a/src/include/Asm/processor-flags.h b/src/include/Asm/processor-flags.h deleted file mode 100644 index b92222d..0000000 --- a/src/include/Asm/processor-flags.h +++ /dev/null @@ -1,168 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _ASM_X86_PROCESSOR_FLAGS_H -#define _ASM_X86_PROCESSOR_FLAGS_H -/* Various flags defined: can be included from assembler. */ - -#include - -/* - * EFLAGS bits - */ -#define X86_EFLAGS_CF_BIT 0 /* Carry Flag */ -#define X86_EFLAGS_CF _BITUL(X86_EFLAGS_CF_BIT) -#define X86_EFLAGS_FIXED_BIT 1 /* Bit 1 - always on */ -#define X86_EFLAGS_FIXED _BITUL(X86_EFLAGS_FIXED_BIT) -#define X86_EFLAGS_PF_BIT 2 /* Parity Flag */ -#define X86_EFLAGS_PF _BITUL(X86_EFLAGS_PF_BIT) -#define X86_EFLAGS_AF_BIT 4 /* Auxiliary carry Flag */ -#define X86_EFLAGS_AF _BITUL(X86_EFLAGS_AF_BIT) -#define X86_EFLAGS_ZF_BIT 6 /* Zero Flag */ -#define X86_EFLAGS_ZF _BITUL(X86_EFLAGS_ZF_BIT) -#define X86_EFLAGS_SF_BIT 7 /* Sign Flag */ -#define X86_EFLAGS_SF _BITUL(X86_EFLAGS_SF_BIT) -#define X86_EFLAGS_TF_BIT 8 /* Trap Flag */ -#define X86_EFLAGS_TF _BITUL(X86_EFLAGS_TF_BIT) -#define X86_EFLAGS_IF_BIT 9 /* Interrupt Flag */ -#define X86_EFLAGS_IF _BITUL(X86_EFLAGS_IF_BIT) -#define X86_EFLAGS_DF_BIT 10 /* Direction Flag */ -#define X86_EFLAGS_DF _BITUL(X86_EFLAGS_DF_BIT) -#define X86_EFLAGS_OF_BIT 11 /* Overflow Flag */ -#define X86_EFLAGS_OF _BITUL(X86_EFLAGS_OF_BIT) -#define X86_EFLAGS_IOPL_BIT 12 /* I/O Privilege Level (2 bits) */ -#define X86_EFLAGS_IOPL (_AC(3,UL) << X86_EFLAGS_IOPL_BIT) -#define X86_EFLAGS_NT_BIT 14 /* Nested Task */ -#define X86_EFLAGS_NT _BITUL(X86_EFLAGS_NT_BIT) -#define X86_EFLAGS_RF_BIT 16 /* Resume Flag */ -#define X86_EFLAGS_RF _BITUL(X86_EFLAGS_RF_BIT) -#define X86_EFLAGS_VM_BIT 17 /* Virtual Mode */ -#define X86_EFLAGS_VM _BITUL(X86_EFLAGS_VM_BIT) -#define X86_EFLAGS_AC_BIT 18 /* Alignment Check/Access Control */ -#define X86_EFLAGS_AC _BITUL(X86_EFLAGS_AC_BIT) -#define X86_EFLAGS_VIF_BIT 19 /* Virtual Interrupt Flag */ -#define X86_EFLAGS_VIF _BITUL(X86_EFLAGS_VIF_BIT) -#define X86_EFLAGS_VIP_BIT 20 /* Virtual Interrupt Pending */ -#define X86_EFLAGS_VIP _BITUL(X86_EFLAGS_VIP_BIT) -#define X86_EFLAGS_ID_BIT 21 /* CPUID detection */ -#define X86_EFLAGS_ID _BITUL(X86_EFLAGS_ID_BIT) - -/* - * Basic CPU control in CR0 - */ -#define X86_CR0_PE_BIT 0 /* Protection Enable */ -#define X86_CR0_PE _BITUL(X86_CR0_PE_BIT) -#define X86_CR0_MP_BIT 1 /* Monitor Coprocessor */ -#define X86_CR0_MP _BITUL(X86_CR0_MP_BIT) -#define X86_CR0_EM_BIT 2 /* Emulation */ -#define X86_CR0_EM _BITUL(X86_CR0_EM_BIT) -#define X86_CR0_TS_BIT 3 /* Task Switched */ -#define X86_CR0_TS _BITUL(X86_CR0_TS_BIT) -#define X86_CR0_ET_BIT 4 /* Extension Type */ -#define X86_CR0_ET _BITUL(X86_CR0_ET_BIT) -#define X86_CR0_NE_BIT 5 /* Numeric Error */ -#define X86_CR0_NE _BITUL(X86_CR0_NE_BIT) -#define X86_CR0_WP_BIT 16 /* Write Protect */ -#define X86_CR0_WP _BITUL(X86_CR0_WP_BIT) -#define X86_CR0_AM_BIT 18 /* Alignment Mask */ -#define X86_CR0_AM _BITUL(X86_CR0_AM_BIT) -#define X86_CR0_NW_BIT 29 /* Not Write-through */ -#define X86_CR0_NW _BITUL(X86_CR0_NW_BIT) -#define X86_CR0_CD_BIT 30 /* Cache Disable */ -#define X86_CR0_CD _BITUL(X86_CR0_CD_BIT) -#define X86_CR0_PG_BIT 31 /* Paging */ -#define X86_CR0_PG _BITUL(X86_CR0_PG_BIT) - -/* - * Paging options in CR3 - */ -#define X86_CR3_PWT_BIT 3 /* Page Write Through */ -#define X86_CR3_PWT _BITUL(X86_CR3_PWT_BIT) -#define X86_CR3_PCD_BIT 4 /* Page Cache Disable */ -#define X86_CR3_PCD _BITUL(X86_CR3_PCD_BIT) - -#define X86_CR3_PCID_BITS 12 -#define X86_CR3_PCID_MASK (_AC((1UL << X86_CR3_PCID_BITS) - 1, UL)) - -#define X86_CR3_PCID_NOFLUSH_BIT 63 /* Preserve old PCID */ -#define X86_CR3_PCID_NOFLUSH _BITULL(X86_CR3_PCID_NOFLUSH_BIT) - -/* - * Intel CPU features in CR4 - */ -#define X86_CR4_VME_BIT 0 /* enable vm86 extensions */ -#define X86_CR4_VME _BITUL(X86_CR4_VME_BIT) -#define X86_CR4_PVI_BIT 1 /* virtual interrupts flag enable */ -#define X86_CR4_PVI _BITUL(X86_CR4_PVI_BIT) -#define X86_CR4_TSD_BIT 2 /* disable time stamp at ipl 3 */ -#define X86_CR4_TSD _BITUL(X86_CR4_TSD_BIT) -#define X86_CR4_DE_BIT 3 /* enable debugging extensions */ -#define X86_CR4_DE _BITUL(X86_CR4_DE_BIT) -#define X86_CR4_PSE_BIT 4 /* enable page size extensions */ -#define X86_CR4_PSE _BITUL(X86_CR4_PSE_BIT) -#define X86_CR4_PAE_BIT 5 /* enable physical address extensions */ -#define X86_CR4_PAE _BITUL(X86_CR4_PAE_BIT) -#define X86_CR4_MCE_BIT 6 /* Machine check enable */ -#define X86_CR4_MCE _BITUL(X86_CR4_MCE_BIT) -#define X86_CR4_PGE_BIT 7 /* enable global pages */ -#define X86_CR4_PGE _BITUL(X86_CR4_PGE_BIT) -#define X86_CR4_PCE_BIT 8 /* enable performance counters at ipl 3 */ -#define X86_CR4_PCE _BITUL(X86_CR4_PCE_BIT) -#define X86_CR4_OSFXSR_BIT 9 /* enable fast FPU save and restore */ -#define X86_CR4_OSFXSR _BITUL(X86_CR4_OSFXSR_BIT) -#define X86_CR4_OSXMMEXCPT_BIT 10 /* enable unmasked SSE exceptions */ -#define X86_CR4_OSXMMEXCPT _BITUL(X86_CR4_OSXMMEXCPT_BIT) -#define X86_CR4_UMIP_BIT 11 /* enable UMIP support */ -#define X86_CR4_UMIP _BITUL(X86_CR4_UMIP_BIT) -#define X86_CR4_LA57_BIT 12 /* enable 5-level page tables */ -#define X86_CR4_LA57 _BITUL(X86_CR4_LA57_BIT) -#define X86_CR4_VMXE_BIT 13 /* enable VMX virtualization */ -#define X86_CR4_VMXE _BITUL(X86_CR4_VMXE_BIT) -#define X86_CR4_SMXE_BIT 14 /* enable safer mode (TXT) */ -#define X86_CR4_SMXE _BITUL(X86_CR4_SMXE_BIT) -#define X86_CR4_FSGSBASE_BIT 16 /* enable RDWRFSGS support */ -#define X86_CR4_FSGSBASE _BITUL(X86_CR4_FSGSBASE_BIT) -#define X86_CR4_PCIDE_BIT 17 /* enable PCID support */ -#define X86_CR4_PCIDE _BITUL(X86_CR4_PCIDE_BIT) -#define X86_CR4_OSXSAVE_BIT 18 /* enable xsave and xrestore */ -#define X86_CR4_OSXSAVE _BITUL(X86_CR4_OSXSAVE_BIT) -#define X86_CR4_SMEP_BIT 20 /* enable SMEP support */ -#define X86_CR4_SMEP _BITUL(X86_CR4_SMEP_BIT) -#define X86_CR4_SMAP_BIT 21 /* enable SMAP support */ -#define X86_CR4_SMAP _BITUL(X86_CR4_SMAP_BIT) -#define X86_CR4_PKE_BIT 22 /* enable Protection Keys support */ -#define X86_CR4_PKE _BITUL(X86_CR4_PKE_BIT) -#define X86_CR4_CET_BIT 23 /* enable Control-flow Enforcement Technology */ -#define X86_CR4_CET _BITUL(X86_CR4_CET_BIT) - -/* - * x86-64 Task Priority Register, CR8 - */ -#define X86_CR8_TPR _AC(0x0000000f,UL) /* task priority register */ - -/* - * AMD and Transmeta use MSRs for configuration; see - */ - -/* - * NSC/Cyrix CPU configuration register indexes - */ -#define CX86_PCR0 0x20 -#define CX86_GCR 0xb8 -#define CX86_CCR0 0xc0 -#define CX86_CCR1 0xc1 -#define CX86_CCR2 0xc2 -#define CX86_CCR3 0xc3 -#define CX86_CCR4 0xe8 -#define CX86_CCR5 0xe9 -#define CX86_CCR6 0xea -#define CX86_CCR7 0xeb -#define CX86_PCR1 0xf0 -#define CX86_DIR0 0xfe -#define CX86_DIR1 0xff -#define CX86_ARR_BASE 0xc4 -#define CX86_RCR_BASE 0xdc - -#define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \ - X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \ - X86_CR0_PG) - -#endif /* _ASM_X86_PROCESSOR_FLAGS_H */ diff --git a/src/include/Linux/const.h b/src/include/Linux/const.h deleted file mode 100644 index 5e48987..0000000 --- a/src/include/Linux/const.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* const.h: Macros for dealing with constants. */ - -#ifndef _LINUX_CONST_H -#define _LINUX_CONST_H - -/* Some constant macros are used in both assembler and - * C code. Therefore we cannot annotate them always with - * 'UL' and other type specifiers unilaterally. We - * use the following macros to deal with this. - * - * Similarly, _AT() will cast an expression with a type in C, but - * leave it unchanged in asm. - */ - -#ifdef __ASSEMBLY__ -#define _AC(X,Y) X -#define _AT(T,X) X -#else -#define __AC(X,Y) (X##Y) -#define _AC(X,Y) __AC(X,Y) -#define _AT(T,X) ((T)(X)) -#endif - -#define _UL(x) (_AC(x, UL)) -#define _ULL(x) (_AC(x, ULL)) - -#define _BITUL(x) (_UL(1) << (x)) -#define _BITULL(x) (_ULL(1) << (x)) - -#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) -#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) - -#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) - -#endif /* _LINUX_CONST_H */ diff --git a/src/include/Linux/kd.h b/src/include/Linux/kd.h deleted file mode 100644 index 7d0807e..0000000 --- a/src/include/Linux/kd.h +++ /dev/null @@ -1,190 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _LINUX_KD_H -#define _LINUX_KD_H -#include - - -/* 0x4B is 'K', to avoid collision with termios and vt */ - -#define GIO_FONT 0x4B60 /* gets font in expanded form */ -#define PIO_FONT 0x4B61 /* use font in expanded form */ - -#define GIO_FONTX 0x4B6B /* get font using struct consolefontdesc */ -#define PIO_FONTX 0x4B6C /* set font using struct consolefontdesc */ -struct consolefontdesc { - unsigned short charcount; /* characters in font (256 or 512) */ - unsigned short charheight; /* scan lines per character (1-32) */ - char *chardata; /* font data in expanded form */ -}; - -#define PIO_FONTRESET 0x4B6D /* reset to default font */ - -#define GIO_CMAP 0x4B70 /* gets colour palette on VGA+ */ -#define PIO_CMAP 0x4B71 /* sets colour palette on VGA+ */ - -#define KIOCSOUND 0x4B2F /* start sound generation (0 for off) */ -#define KDMKTONE 0x4B30 /* generate tone */ - -#define KDGETLED 0x4B31 /* return current led state */ -#define KDSETLED 0x4B32 /* set led state [lights, not flags] */ -#define LED_SCR 0x01 /* scroll lock led */ -#define LED_NUM 0x02 /* num lock led */ -#define LED_CAP 0x04 /* caps lock led */ - -#define KDGKBTYPE 0x4B33 /* get keyboard type */ -#define KB_84 0x01 -#define KB_101 0x02 /* this is what we always answer */ -#define KB_OTHER 0x03 - -#define KDADDIO 0x4B34 /* add i/o port as valid */ -#define KDDELIO 0x4B35 /* del i/o port as valid */ -#define KDENABIO 0x4B36 /* enable i/o to video board */ -#define KDDISABIO 0x4B37 /* disable i/o to video board */ - -#define KDSETMODE 0x4B3A /* set text/graphics mode */ -#define KD_TEXT 0x00 -#define KD_GRAPHICS 0x01 -#define KD_TEXT0 0x02 /* obsolete */ -#define KD_TEXT1 0x03 /* obsolete */ -#define KDGETMODE 0x4B3B /* get current mode */ - -#define KDMAPDISP 0x4B3C /* map display into address space */ -#define KDUNMAPDISP 0x4B3D /* unmap display from address space */ - -typedef char scrnmap_t; -#define E_TABSZ 256 -#define GIO_SCRNMAP 0x4B40 /* get screen mapping from kernel */ -#define PIO_SCRNMAP 0x4B41 /* put screen mapping table in kernel */ -#define GIO_UNISCRNMAP 0x4B69 /* get full Unicode screen mapping */ -#define PIO_UNISCRNMAP 0x4B6A /* set full Unicode screen mapping */ - -#define GIO_UNIMAP 0x4B66 /* get unicode-to-font mapping from kernel */ -struct unipair { - unsigned short unicode; - unsigned short fontpos; -}; -struct unimapdesc { - unsigned short entry_ct; - struct unipair *entries; -}; -#define PIO_UNIMAP 0x4B67 /* put unicode-to-font mapping in kernel */ -#define PIO_UNIMAPCLR 0x4B68 /* clear table, possibly advise hash algorithm */ -struct unimapinit { - unsigned short advised_hashsize; /* 0 if no opinion */ - unsigned short advised_hashstep; /* 0 if no opinion */ - unsigned short advised_hashlevel; /* 0 if no opinion */ -}; - -#define UNI_DIRECT_BASE 0xF000 /* start of Direct Font Region */ -#define UNI_DIRECT_MASK 0x01FF /* Direct Font Region bitmask */ - -#define K_RAW 0x00 -#define K_XLATE 0x01 -#define K_MEDIUMRAW 0x02 -#define K_UNICODE 0x03 -#define K_OFF 0x04 -#define KDGKBMODE 0x4B44 /* gets current keyboard mode */ -#define KDSKBMODE 0x4B45 /* sets current keyboard mode */ - -#define K_METABIT 0x03 -#define K_ESCPREFIX 0x04 -#define KDGKBMETA 0x4B62 /* gets meta key handling mode */ -#define KDSKBMETA 0x4B63 /* sets meta key handling mode */ - -#define K_SCROLLLOCK 0x01 -#define K_NUMLOCK 0x02 -#define K_CAPSLOCK 0x04 -#define KDGKBLED 0x4B64 /* get led flags (not lights) */ -#define KDSKBLED 0x4B65 /* set led flags (not lights) */ - -struct kbentry { - unsigned char kb_table; - unsigned char kb_index; - unsigned short kb_value; -}; -#define K_NORMTAB 0x00 -#define K_SHIFTTAB 0x01 -#define K_ALTTAB 0x02 -#define K_ALTSHIFTTAB 0x03 - -#define KDGKBENT 0x4B46 /* gets one entry in translation table */ -#define KDSKBENT 0x4B47 /* sets one entry in translation table */ - -struct kbsentry { - unsigned char kb_func; - unsigned char kb_string[512]; -}; -#define KDGKBSENT 0x4B48 /* gets one function key string entry */ -#define KDSKBSENT 0x4B49 /* sets one function key string entry */ - -struct kbdiacr { - unsigned char diacr, base, result; -}; -struct kbdiacrs { - unsigned int kb_cnt; /* number of entries in following array */ - struct kbdiacr kbdiacr[256]; /* MAX_DIACR from keyboard.h */ -}; -#define KDGKBDIACR 0x4B4A /* read kernel accent table */ -#define KDSKBDIACR 0x4B4B /* write kernel accent table */ - -struct kbdiacruc { - unsigned int diacr, base, result; -}; -struct kbdiacrsuc { - unsigned int kb_cnt; /* number of entries in following array */ - struct kbdiacruc kbdiacruc[256]; /* MAX_DIACR from keyboard.h */ -}; -#define KDGKBDIACRUC 0x4BFA /* read kernel accent table - UCS */ -#define KDSKBDIACRUC 0x4BFB /* write kernel accent table - UCS */ - -struct kbkeycode { - unsigned int scancode, keycode; -}; -#define KDGETKEYCODE 0x4B4C /* read kernel keycode table entry */ -#define KDSETKEYCODE 0x4B4D /* write kernel keycode table entry */ - -#define KDSIGACCEPT 0x4B4E /* accept kbd generated signals */ - -struct kbd_repeat { - int delay; /* in msec; <= 0: don't change */ - int period; /* in msec; <= 0: don't change */ - /* earlier this field was misnamed "rate" */ -}; - -#define KDKBDREP 0x4B52 /* set keyboard delay/repeat rate; - * actually used values are returned */ - -#define KDFONTOP 0x4B72 /* font operations */ - -struct console_font_op { - unsigned int op; /* operation code KD_FONT_OP_* */ - unsigned int flags; /* KD_FONT_FLAG_* */ - unsigned int width, height; /* font size */ - unsigned int charcount; - unsigned char *data; /* font data with vpitch fixed to 32 for - * KD_FONT_OP_SET/GET - */ -}; - -struct console_font { - unsigned int width, height; /* font size */ - unsigned int charcount; - unsigned char *data; /* font data with vpitch fixed to 32 for - * KD_FONT_OP_SET/GET - */ -}; - -#define KD_FONT_OP_SET 0 /* Set font */ -#define KD_FONT_OP_GET 1 /* Get font */ -#define KD_FONT_OP_SET_DEFAULT 2 /* Set font to default, data points to name / NULL */ -#define KD_FONT_OP_COPY 3 /* Obsolete, do not use */ -#define KD_FONT_OP_SET_TALL 4 /* Set font with vpitch = height */ -#define KD_FONT_OP_GET_TALL 5 /* Get font with vpitch = height */ - -#define KD_FONT_FLAG_DONT_RECALC 1 /* Don't recalculate hw charcell size [compat] */ - -/* note: 0x4B00-0x4B4E all have had a value at some time; - don't reuse for the time being */ -/* note: 0x4B60-0x4B6D, 0x4B70-0x4B72 used above */ - -#endif /* _LINUX_KD_H */ diff --git a/src/include/Linux/magic.h b/src/include/Linux/magic.h deleted file mode 100644 index 1f70efb..0000000 --- a/src/include/Linux/magic.h +++ /dev/null @@ -1,107 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef __LINUX_MAGIC_H__ -#define __LINUX_MAGIC_H__ - -#define ADFS_SUPER_MAGIC 0xadf5 -#define AFFS_SUPER_MAGIC 0xadff -#define AFS_SUPER_MAGIC 0x5346414F -#define AUTOFS_SUPER_MAGIC 0x0187 -#define CEPH_SUPER_MAGIC 0x00c36400 -#define CODA_SUPER_MAGIC 0x73757245 -#define CRAMFS_MAGIC 0x28cd3d45 /* some random number */ -#define CRAMFS_MAGIC_WEND 0x453dcd28 /* magic number with the wrong endianess */ -#define DEBUGFS_MAGIC 0x64626720 -#define SECURITYFS_MAGIC 0x73636673 -#define SELINUX_MAGIC 0xf97cff8c -#define SMACK_MAGIC 0x43415d53 /* "SMAC" */ -#define RAMFS_MAGIC 0x858458f6 /* some random number */ -#define TMPFS_MAGIC 0x01021994 -#define HUGETLBFS_MAGIC 0x958458f6 /* some random number */ -#define SQUASHFS_MAGIC 0x73717368 -#define ECRYPTFS_SUPER_MAGIC 0xf15f -#define EFS_SUPER_MAGIC 0x414A53 -#define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 -#define EXT2_SUPER_MAGIC 0xEF53 -#define EXT3_SUPER_MAGIC 0xEF53 -#define XENFS_SUPER_MAGIC 0xabba1974 -#define EXT4_SUPER_MAGIC 0xEF53 -#define BTRFS_SUPER_MAGIC 0x9123683E -#define NILFS_SUPER_MAGIC 0x3434 -#define F2FS_SUPER_MAGIC 0xF2F52010 -#define HPFS_SUPER_MAGIC 0xf995e849 -#define ISOFS_SUPER_MAGIC 0x9660 -#define JFFS2_SUPER_MAGIC 0x72b6 -#define XFS_SUPER_MAGIC 0x58465342 /* "XFSB" */ -#define PSTOREFS_MAGIC 0x6165676C -#define EFIVARFS_MAGIC 0xde5e81e4 -#define HOSTFS_SUPER_MAGIC 0x00c0ffee -#define OVERLAYFS_SUPER_MAGIC 0x794c7630 -#define FUSE_SUPER_MAGIC 0x65735546 - -#define MINIX_SUPER_MAGIC 0x137F /* minix v1 fs, 14 char names */ -#define MINIX_SUPER_MAGIC2 0x138F /* minix v1 fs, 30 char names */ -#define MINIX2_SUPER_MAGIC 0x2468 /* minix v2 fs, 14 char names */ -#define MINIX2_SUPER_MAGIC2 0x2478 /* minix v2 fs, 30 char names */ -#define MINIX3_SUPER_MAGIC 0x4d5a /* minix v3 fs, 60 char names */ - -#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ -#define EXFAT_SUPER_MAGIC 0x2011BAB0 -#define NCP_SUPER_MAGIC 0x564c /* Guess, what 0x564c is :-) */ -#define NFS_SUPER_MAGIC 0x6969 -#define OCFS2_SUPER_MAGIC 0x7461636f -#define OPENPROM_SUPER_MAGIC 0x9fa1 -#define QNX4_SUPER_MAGIC 0x002f /* qnx4 fs detection */ -#define QNX6_SUPER_MAGIC 0x68191122 /* qnx6 fs detection */ -#define AFS_FS_MAGIC 0x6B414653 - - -#define REISERFS_SUPER_MAGIC 0x52654973 /* used by gcc */ - /* used by file system utilities that - look at the superblock, etc. */ -#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs" -#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" -#define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" - -#define SMB_SUPER_MAGIC 0x517B -#define CIFS_SUPER_MAGIC 0xFF534D42 /* the first four bytes of SMB PDUs */ -#define SMB2_SUPER_MAGIC 0xFE534D42 - -#define CGROUP_SUPER_MAGIC 0x27e0eb -#define CGROUP2_SUPER_MAGIC 0x63677270 - -#define RDTGROUP_SUPER_MAGIC 0x7655821 - -#define STACK_END_MAGIC 0x57AC6E9D - -#define TRACEFS_MAGIC 0x74726163 - -#define V9FS_MAGIC 0x01021997 - -#define BDEVFS_MAGIC 0x62646576 -#define DAXFS_MAGIC 0x64646178 -#define BINFMTFS_MAGIC 0x42494e4d -#define DEVPTS_SUPER_MAGIC 0x1cd1 -#define BINDERFS_SUPER_MAGIC 0x6c6f6f70 -#define FUTEXFS_SUPER_MAGIC 0xBAD1DEA -#define PIPEFS_MAGIC 0x50495045 -#define PROC_SUPER_MAGIC 0x9fa0 -#define SOCKFS_MAGIC 0x534F434B -#define SYSFS_MAGIC 0x62656572 -#define USBDEVICE_SUPER_MAGIC 0x9fa2 -#define MTD_INODE_FS_MAGIC 0x11307854 -#define ANON_INODE_FS_MAGIC 0x09041934 -#define BTRFS_TEST_MAGIC 0x73727279 -#define NSFS_MAGIC 0x6e736673 -#define BPF_FS_MAGIC 0xcafe4a11 -#define AAFS_MAGIC 0x5a3c69f0 -#define ZONEFS_MAGIC 0x5a4f4653 - -/* Since UDF 2.01 is ISO 13346 based... */ -#define UDF_SUPER_MAGIC 0x15013346 -#define DMA_BUF_MAGIC 0x444d4142 /* "DMAB" */ -#define DEVMEM_MAGIC 0x454d444d /* "DMEM" */ -#define SECRETMEM_MAGIC 0x5345434d /* "SECM" */ - -#define SHIFTFS_MAGIC 0x6a656a62 - -#endif /* __LINUX_MAGIC_H__ */ diff --git a/src/include/Sys/kd.h b/src/include/Sys/kd.h deleted file mode 100644 index 96818ef..0000000 --- a/src/include/Sys/kd.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 1996-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _SYS_KD_H -#define _SYS_KD_H 1 - -/* Make sure the header is not loaded. */ -#ifndef _LINUX_TYPES_H -# define _LINUX_TYPES_H 1 -# define __undef_LINUX_TYPES_H -#endif - -#include "Linux/kd.h" - -#ifdef __undef_LINUX_TYPES_H -# undef _LINUX_TYPES_H -# undef __undef_LINUX_TYPES_H -#endif - -#endif /* sys/kd.h */ diff --git a/src/include/bios.h b/src/include/bios.h index 9a27aec..eb82bd3 100644 --- a/src/include/bios.h +++ b/src/include/bios.h @@ -7,7 +7,7 @@ extern "C" { #endif -#include "bios_offsets.h" +#include "bios_offsets.hh" #define DOSEMU_BIOS_SIZE() (bios_f000_end - bios_data_start + 1) /* @@ -130,9 +130,6 @@ void bios_setup_init(void); void post_hook(void); -extern char _binary_bios_o_bin_end[] asm("_binary_bios_o_bin_end"); -extern char _binary_bios_o_bin_start[] asm("_binary_bios_o_bin_start"); - #ifdef __cplusplus }; #endif diff --git a/src/include/bitops.h b/src/include/bitops.h index 525de2b..fada073 100644 --- a/src/include/bitops.h +++ b/src/include/bitops.h @@ -1,19 +1,132 @@ #ifndef _ASM_BITOPS_H #define _ASM_BITOPS_H +/* + * This is a hacked-up version of Linus' bitops.h file. I've added a + * function and removed the "extern"s (in the i386 part) for convenience. + * If I can figure out how to use Linus' bitops.h directly, I'll reduce + * this file to an #include and just my added function. For now, this + * works. -JLS $Id$ + * + */ -//#include "ffs.h" -#include // for ffs -#include "fls.h" -#include "generic-non-atomic.h" +/* + * Copyright 1992, Linus Torvalds. + */ -#define find_bit(w) (ffs(w) - 1) -#define find_bit_r(w) (fls(w) - 1) -#define set_bit(nr, addr) generic___set_bit(nr, (unsigned long *)(addr)) -#define clear_bit(nr, addr) generic___clear_bit(nr, (unsigned long *)(addr)) -#define change_bit(nr, addr) generic___change_bit(nr, (unsigned long *)(addr)) -#define test_bit(nr, addr) generic_test_bit(nr, (const unsigned long *)(addr)) -#define test_and_set_bit(nr, addr) generic___test_and_set_bit(nr, (unsigned long *)(addr)) -#define test_and_clear_bit(nr, addr) generic___test_and_clear_bit(nr, (unsigned long *)(addr)) -#define test_and_change_bit(nr, addr) generic___test_and_change_bit(nr, (unsigned long *)(addr)) +/* + * find_bit() Copyright 1994, J. Lawrence Stephan. + */ + +/* function definitions */ + + +static int find_bit(unsigned int word); +static int find_bit_r(unsigned int word); +static int set_bit(int nr, void * addr); +static int clear_bit(int nr, void * addr); +static int change_bit(int nr, void * addr); +static int test_bit(int nr, void * addr); + +/* + * These have to be done with inline assembly: that way the bit-setting is + * guaranteed to be atomic. All bit operations return 0 if the bit was + * cleared before the operation and != 0 if it was not. + * + * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). + */ + +#define ADDR (*(volatile unsigned *) addr) + +/* JLS's stuff */ +/* + * find_bit returns the bit number of the lowest bit that's set + * Returns -1 if no one exists. + */ +static __inline__ int +find_bit(unsigned int word) +{ + int result = -1; /* value to return on error */ + __asm__("bsfl %2,%0" + :"=r" (result) /* output */ + :"0" (result), "r" (word)); /* input */ + return result; +} + +/* + * find_bit_r returns the bit number of the highest bit that's set + * Returns -1 if no one exists. + */ +static __inline__ int +find_bit_r(unsigned int word) +{ + int result = -1; /* value to return on error */ + __asm__("bsrl %2,%0" + :"=r" (result) /* output */ + :"0" (result), "r" (word)); /* input */ + return result; +} + +/* + * Linus' stuff follows - except each __inline__ had an extern in front of + * it + */ +static __inline__ int +change_bit(int nr, void *addr) +{ + int oldbit; + + __asm__ __volatile__("btcl %2,%1\n\tsbbl %0,%0" + :"=r"(oldbit), "=m"(ADDR) + :"r"(nr)); + return oldbit; +} + +static __inline__ int +set_bit(int nr, void *addr) +{ + int oldbit; + + __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0" + :"=r"(oldbit), "=m"(ADDR) + :"r"(nr)); + return oldbit; +} + +static __inline__ int +clear_bit(int nr, void *addr) +{ + int oldbit; + + __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0" + :"=r"(oldbit), "=m"(ADDR) + :"r"(nr)); + return oldbit; +} + +/* + * This routine doesn't need to be atomic, but it's faster to code it this + * way. + */ +static __inline__ int +test_bit(int nr, void *addr) +{ + int oldbit; + + __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0" + :"=r"(oldbit) + :"m"(ADDR), "r"(nr)); + return oldbit; +} + +static __inline__ int +test_bit_i(int nr, unsigned val) +{ + int oldbit; + + __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0" + :"=r"(oldbit) + :"r"(val), "r"(nr)); + return oldbit; +} #endif /* _ASM_BITOPS_H */ diff --git a/src/include/chipset.h b/src/include/chipset.h index 0214e5c..4219ea2 100644 --- a/src/include/chipset.h +++ b/src/include/chipset.h @@ -9,10 +9,4 @@ void chipset_init(void); -#define PIC0_EXTPORT_START 0x560 -#define PIC0_VECBASE_PORT 0x560 -#define PIC1_EXTPORT_START 0x570 -#define PIC1_VECBASE_PORT 0x570 -#define PICx_EXT_PORTS 1 - #endif diff --git a/src/include/clipboard.h b/src/include/clipboard.h deleted file mode 100644 index 889e73b..0000000 --- a/src/include/clipboard.h +++ /dev/null @@ -1,34 +0,0 @@ -#include - -/* Text format. Each line ends with a carriage return/linefeed (CR-LF) - * combination. A null character signals the end of the data. Use this - * format for ANSI text. */ -#define CF_TEXT 1 - -/* Text format containing characters in the OEM character set. Each line - * ends with a carriage return/linefeed (CR-LF) combination. A null - * character signals the end of the data. */ -#define CF_OEMTEXT 7 - -/* Unicode text format. Each line ends with a carriage return/linefeed - * (CR-LF) combination. A null character signals the end of the data. */ -#define CF_UNICODETEXT 13 - -struct clipboard_system -{ - int (*clear)(void); - int (*write)(int type, const char *p, int size); - int (*getsize)(int type); - int (*getdata)(int type, char *p, int size); - const char *name; -}; - -extern struct clipboard_system *Clipboard; -extern char *clip_str; - -int register_clipboard_system(struct clipboard_system *cs); -void add_clip_str(char *q); -int cnn_clear(void); -int cnn_write(int type, const char *p, int size); -int cnn_getsize(int type); -int cnn_getdata(int type, char *p, int size); diff --git a/src/include/cmos.h b/src/include/cmos.h index 04e5c99..7976272 100644 --- a/src/include/cmos.h +++ b/src/include/cmos.h @@ -43,10 +43,8 @@ #define CMOS_INFO 0x33 #define CMOS_RESV4 0x34 /* 12 bytes reserved */ -void cmos_write(ioport_t reg, Bit8u val, void *arg); -void cmos_init(void); -void cmos_reset(void); -Bit8u cmos_read(ioport_t, void *arg); +void cmos_write(ioport_t, Bit8u), cmos_init(void), cmos_reset(void); +Bit8u cmos_read(ioport_t); Bit8u rtc_read(Bit8u reg); void rtc_write(Bit8u reg, Bit8u val); void rtc_run(void); diff --git a/src/include/coopth.h b/src/include/coopth.h index a02d427..391f693 100644 --- a/src/include/coopth.h +++ b/src/include/coopth.h @@ -1,17 +1,7 @@ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * for details see file COPYING.DOSEMU in the DOSEMU distribution */ #ifndef COOPTH_H @@ -29,7 +19,6 @@ int coopth_create(const char *name, coopth_func_t func); int coopth_create_multi(const char *name, int len, coopth_func_t func); int coopth_create_vm86(const char *name, coopth_func_t func, void (*post)(void), uint16_t *hlt_off); -void coopth_leave_vm86(void); int coopth_start(int tid, void *arg); int coopth_set_permanent_post_handler(int tid, coopth_hndl_t func); int coopth_set_ctx_handlers(int tid, coopth_hndl_t pre, coopth_hndl_t post, @@ -51,9 +40,9 @@ void *coopth_pop_user_data_cur(void); int coopth_get_tid(void); void coopth_ensure_sleeping(int tid); void coopth_ensure_single(int tid); -int coopth_yield(void); -int coopth_wait(void); -int coopth_sleep(void); +void coopth_yield(void); +void coopth_wait(void); +void coopth_sleep(void); int coopth_sched(void); int coopth_sched_cond(void); void coopth_detach(void); @@ -69,10 +58,9 @@ void coopth_run(void); void coopth_run_tid(int tid); int coopth_wants_sleep_vm86(void); void coopth_set_ctx_checker_vm86(int (*checker)(void)); -void coopth_cancel_disable_cur(void); -void coopth_cancel_enable_cur(void); +void coopth_cancel_disable(void); +void coopth_cancel_enable(void); void coopth_dump(int all); -void coopth_set_nothread_notifier(void (*notifier)(int)); -int coopth_get_thread_count_in_process_vm86(void); +void coopth_set_nothread_notifier(void (*notifier)(void)); #endif diff --git a/src/include/coopth_be.h b/src/include/coopth_be.h index 76250d3..1a78f5a 100644 --- a/src/include/coopth_be.h +++ b/src/include/coopth_be.h @@ -25,7 +25,7 @@ struct coopth_be_ops { void (*callf)(int tid, int idx); void (*retf)(int tid, int idx); void (*prep)(int tid, int idx); - int (*to_sleep)(int tid); + int (*to_sleep)(void); void (*sleep)(void); uint64_t (*get_dbg_val)(int tid, int idx); unsigned id; @@ -55,6 +55,5 @@ int coopth_flush_internal(unsigned id, void (*helper)(void)); struct crun_ret coopth_run_thread_internal(int tid); int coopth_wants_sleep_internal(unsigned id); void coopth_call_post_internal(int tid); -void coopth_leave_internal(void); #endif diff --git a/src/include/coopth_pm.h b/src/include/coopth_pm.h deleted file mode 100644 index e295292..0000000 --- a/src/include/coopth_pm.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include "../dosext/dpmi/coopth_pm.h" diff --git a/src/include/cpu-emu.h b/src/include/cpu-emu.h index 6744055..136eb49 100644 --- a/src/include/cpu-emu.h +++ b/src/include/cpu-emu.h @@ -3,7 +3,6 @@ #include #include "bitops.h" -#include "cpu.h" extern void e_priv_iopl(int); #define test_ioperm(a) (test_bit((a),emu_io_bitmap)) @@ -43,11 +42,11 @@ extern void e_priv_iopl(int); #define CPUEMU_DIRECT_IO #endif -#ifdef X86_JIT +#if defined(__i386__) || defined(__x86_64__) #define HOST_ARCH_X86 -#define IS_EMU_JIT() (IS_EMU() && !config.cpusim) +#define CONFIG_CPUSIM config.cpusim #else -#define IS_EMU_JIT() (0) +#define CONFIG_CPUSIM 1 #endif /* ----------------------------------------------------------------------- */ @@ -62,7 +61,6 @@ extern void e_priv_iopl(int); #define CeS_INHI 0x800 /* inhibit interrupts(pop ss; pop sp et sim.) */ #define CeS_TRAP 0x1000 /* INT01 Sstep active */ #define CeS_DRTRAP 0x2000 /* Debug Registers active */ -#define CeS_INSTREMU 0x4000 /* behave like former instr_emu, with counter for VGAEMU faults */ extern int IsV86Emu; extern int IsDpmiEmu; @@ -75,21 +73,15 @@ int e_vm86(void); /* called from dpmi.c */ void emu_mhp_SetTypebyte (unsigned short selector, int typebyte); unsigned short emu_do_LAR (unsigned short selector); -char *e_scp_disasm(cpuctx_t *scp, int pmode); +char *e_scp_disasm(sigcontext_t *scp, int pmode); /* called from mfs.c, fatfs.c and some places that memcpy */ -#ifdef X86_JIT +#ifdef X86_EMULATOR void e_invalidate(unsigned data, int cnt); void e_invalidate_full(unsigned data, int cnt); -void e_invalidate_full_pa(unsigned data, int cnt); -int e_invalidate_page_full(unsigned data); -void e_invalidate_pa(unsigned data, int cnt); #else #define e_invalidate(x,y) #define e_invalidate_full(x,y) -#define e_invalidate_full_pa(x,y) -#define e_invalidate_page_full(x) 0 -#define e_invalidate_pa(x,y) #endif /* called from cpu.c */ @@ -97,34 +89,24 @@ void init_emu_cpu (void); void reset_emu_cpu (void); /* called/used from dpmi.c */ -int e_dpmi(cpuctx_t *scp); -void e_dpmi_b0x(int op,cpuctx_t *scp); +int e_dpmi(sigcontext_t *scp); +void e_dpmi_b0x(int op,sigcontext_t *scp); extern int in_dpmi_emu; -/* called/used from vgaemu.c */ -int instr_emu_sim(cpuctx_t *scp, int pmode, int cnt); -void instr_emu_sim_reset_count(int cnt); - /* called from emu-ldt.c */ void InvalidateSegs(void); -#ifdef X86_JIT /* called from sigsegv.c */ -int e_emu_fault(sigcontext_t *scp, int in_vm86); -#else -#define e_emu_fault(scp, in_vm86) 0 -#endif - -#ifdef X86_EMULATOR -/* called from signal.c */ +int e_emu_pagefault(sigcontext_t *scp, int pmode); +int e_handle_pagefault(dosaddr_t addr, unsigned err, sigcontext_t *scp); +int e_handle_fault(sigcontext_t *scp); int e_in_compiled_code(void); -void e_gen_sigalrm(void); -#else -#define e_gen_sigalrm() -#define e_in_compiled_code() 0 -#endif -/* called from dos2linux.c */ -int e_querymprot(dosaddr_t addr); +/* called from signal.c */ +#ifdef X86_EMULATOR +void e_gen_sigalrm(sigcontext_t *scp); +#else +#define e_gen_sigalrm(x) +#endif #endif /*DOSEMU_CPUEMU_H*/ diff --git a/src/include/cpu.h b/src/include/cpu.h index 5d9edd6..9ab7843 100644 --- a/src/include/cpu.h +++ b/src/include/cpu.h @@ -43,8 +43,6 @@ #define READ_SEG_REG(reg) (REGS.reg) #define WRITE_SEG_REG(reg, val) REGS.reg = (val) -#define MAY_ALIAS __attribute__((may_alias)) - union dword { Bit32u d; struct { Bit16u l, h; } w; @@ -54,56 +52,65 @@ union dword { unsigned long ul; #endif struct { Bit8u l, h, b2, b3; } b; -} MAY_ALIAS; +}; union word { Bit16u w; struct { Bit8u l, h; } b; -} MAY_ALIAS; - -struct emu_fsave { - uint32_t cw; - uint32_t sw; - uint32_t tag; - uint32_t ipoff; - uint32_t cssel; - uint32_t dataoff; - uint32_t datasel; - struct { uint16_t element[5]; } st[8]; - uint32_t status; }; -struct emu_fpxstate { - /* 32-bit FXSAVE format in 64bit mode (same as in 32bit mode but more xmms) */ - uint16_t cwd; - uint16_t swd; - uint16_t ftw; - uint16_t fop; - uint32_t fip; - uint32_t fcs; - uint32_t fdp; - uint32_t fds; - uint32_t mxcsr; - uint32_t mxcr_mask; - struct { uint32_t element[4]; } st[8]; - struct { uint32_t element[4]; } xmm[16]; - struct { uint32_t element[4]; } reserved[3]; - struct { uint32_t element[4]; } scratch[3]; -}; - -static_assert(sizeof(struct emu_fpxstate) == 512, "size mismatch"); - -void fxsave_to_fsave(const struct emu_fpxstate *fxsave, - struct emu_fsave *fptr); -void fsave_to_fxsave(const struct emu_fsave *fptr, - struct emu_fpxstate *fxsave); - -/* Structure to describe FPU registers. */ -typedef struct emu_fpxstate emu_fpstate; -typedef emu_fpstate *emu_fpregset_t; - #ifndef __linux__ -typedef unsigned long greg_t; +#define __ctx(fld) fld +#ifdef __x86_64__ +/* taken from glibc, don't blame me :) */ +typedef long long int greg_t; +struct _libc_fpxreg +{ + unsigned short int __ctx(significand)[4]; + unsigned short int __ctx(exponent); + unsigned short int __glibc_reserved1[3]; +}; +struct _libc_xmmreg +{ + __uint32_t __ctx(element)[4]; +}; +struct _libc_fpstate +{ + /* 64-bit FXSAVE format. */ + uint16_t __ctx(cwd); + uint16_t __ctx(swd); + uint16_t __ctx(ftw); + uint16_t __ctx(fop); + uint64_t __ctx(rip); + uint64_t __ctx(rdp); + uint32_t __ctx(mxcsr); + uint32_t __ctx(mxcr_mask); + struct _libc_fpxreg _st[8]; + struct _libc_xmmreg _xmm[16]; + uint32_t __glibc_reserved1[24]; +}; +/* Structure to describe FPU registers. */ +typedef struct _libc_fpstate *fpregset_t; +#else +typedef int greg_t; +struct _libc_fpreg +{ + unsigned short int __ctx(significand)[4]; + unsigned short int __ctx(exponent); +}; +struct _libc_fpstate +{ + unsigned long int __ctx(cw); + unsigned long int __ctx(sw); + unsigned long int __ctx(tag); + unsigned long int __ctx(ipoff); + unsigned long int __ctx(cssel); + unsigned long int __ctx(dataoff); + unsigned long int __ctx(datasel); + struct _libc_fpreg _st[8]; + unsigned long int __ctx(status); +}; +#endif #endif union g_reg { @@ -116,7 +123,7 @@ union g_reg { uint32_t d[1]; uint16_t w[2]; #endif -} MAY_ALIAS; +}; #define DWORD__(reg, c) (((c union g_reg *)&(reg))->d[0]) /* vxd.c redefines DWORD */ @@ -213,7 +220,6 @@ typedef struct { u_short offset; u_short segment; } far_t; -#define FAR_NULL (far_t){0,0} #define MK_FP16(s,o) ((((unsigned int)(s)) << 16) | ((o) & 0xffff)) #define MK_FP(f) MK_FP16(f.segment, f.offset) #define FP_OFF16(far_ptr) ((far_ptr) & 0xffff) @@ -236,7 +242,7 @@ static inline dosaddr_t FAR2ADDR(far_t ptr) { #define peek(seg, off) (READ_WORD(SEGOFF2LINEAR(seg, off))) -extern emu_fpstate vm86_fpu_state; +extern fpregset_t vm86_fpu_state; extern fenv_t dosemu_fenv; /* @@ -282,52 +288,82 @@ extern fenv_t dosemu_fenv; (__res1 << 16) | __res0; \ }) -#if defined(__x86_64__) || defined (__i386__) +#define loadflags(value) asm volatile("push %0 ; popf"::"g" (value): "cc" ) + #define getflags() \ ({ \ unsigned long __value; \ asm volatile("pushf ; pop %0":"=g" (__value)); \ __value; \ }) + +#define loadregister(reg, value) \ + asm volatile("mov %0, %%" #reg ::"rm" (value)) + +#define getregister(reg) \ + ({ \ + unsigned long __value; \ + asm volatile("mov %%" #reg ",%0":"=rm" (__value)); \ + __value; \ + }) + +#define getsegment(reg) \ + ({ \ + Bit16u __value; \ + asm volatile("mov %%" #reg ",%0":"=rm" (__value)); \ + __value; \ + }) + +#ifdef __x86_64__ +#define loadfpstate(value) \ + asm volatile("fxrstor64 %0\n" :: "m"(value)) + +#define savefpstate(value) \ + asm volatile("fxsave64 %0; fninit\n": "=m"(value)) #else -#define getflags() 0 +#define loadfpstate(value) \ + do { \ + if (config.cpufxsr) \ + asm volatile("fxrstor %0\n" :: \ + "m"(*((char *)&value+112))); \ + else \ + asm volatile("frstor %0\n" :: "m"(value)); \ + } while(0) + +#define savefpstate(value) \ + do { \ + if (config.cpufxsr) { \ + asm volatile("fxsave %0; fninit\n" : \ + "=m"(*((char *)&value+112))); \ + } else \ + asm volatile("fnsave %0; fwait\n" : "=m"(value)); \ + } while(0) #endif -static inline void loadfpstate_legacy(emu_fpstate *buf) +static __inline__ void set_revectored(int nr, struct revectored_struct * bitmap) { - struct emu_fsave fsave; - fxsave_to_fsave(buf, &fsave); - asm volatile("frstor %0\n" :: "m"(fsave)); + __asm__ __volatile__("btsl %1,%0" + : /* no output */ + :"m" (*bitmap),"r" (nr)); } -static inline void savefpstate_legacy(emu_fpstate *buf) +static __inline__ void reset_revectored(int nr, struct revectored_struct * bitmap) { - struct emu_fsave fsave; - asm volatile("fnsave %0; fwait\n" : "=m"(fsave)); - fsave_to_fxsave(&fsave, buf); + __asm__ __volatile__("btrl %1,%0" + : /* no output */ + :"m" (*bitmap),"r" (nr)); } -#if defined(__x86_64__) -/* use 32bit versions */ -#define loadfpstate(value) asm volatile("fxrstor %0\n" :: "m"(value)) -#define savefpstate(value) asm volatile("fxsave %0\n" : "=m"(value)) -#elif defined (__i386__) -#define loadfpstate(value) do { \ - if (config.cpufxsr) \ - asm volatile("fxrstor %0\n" :: "m"(value)); \ - else \ - loadfpstate_legacy(&value); \ -} while (0) -#define savefpstate(value) do { \ - if (config.cpufxsr) \ - asm volatile("fxsave %0\n" : "=m"(value)); \ - else \ - savefpstate_legacy(&value); \ -} while (0) -#else -#define loadfpstate(value) -#define savefpstate(value) -#endif +static __inline__ int is_revectored(int nr, struct revectored_struct * bitmap) +{ + uint8_t ret; + __asm__ __volatile__( + "btl %2,%1\n" + "setcb %0\n" + : "=r"(ret) + :"m" (*bitmap),"r" (nr)); + return ret; +} /* flags */ #define CF (1 << 0) @@ -439,67 +475,146 @@ EXTERN struct vec_t *ivecs; #endif #define IVEC(i) ((ISEG(i)<<4) + IOFF(i)) -#define SETIVEC(i, seg, ofs) do { WRITE_WORD(i * 4 + 2, seg); \ - WRITE_WORD(i * 4, ofs); } while (0) +#define SETIVEC(i, seg, ofs) { WRITE_WORD(i * 4 + 2, seg); \ + WRITE_WORD(i * 4, ofs); } #define OP_IRET 0xcf #include "memory.h" /* for INT_OFF */ -#define IS_REDIRECTED(i) (ISEG(i) != BIOSSEG) +//#define IS_REDIRECTED(i) (IVEC(i) != SEGOFF2LINEAR(BIOSSEG, INT_OFF(i))) #define IS_IRET(i) (READ_BYTE(IVEC(i)) == OP_IRET) /* #define WORD(i) (unsigned short)(i) */ -struct pm_regs { - unsigned ebx; - unsigned ecx; - unsigned edx; - unsigned esi; - unsigned edi; - unsigned ebp; - unsigned eax; - unsigned eip; - unsigned short cs; - unsigned eflags; - unsigned esp; - unsigned short ss; - unsigned short es; - unsigned short ds; - unsigned short fs; - unsigned short gs; - - unsigned trapno; - unsigned err; - dosaddr_t cr2; -}; -typedef struct pm_regs cpuctx_t; -#define REGS_SIZE offsetof(struct pm_regs, trapno) - -#define _es (scp->es) -#define _ds (scp->ds) -#define _es_ (scp->es) -#define _ds_ (scp->ds) -#define get_edi(s) ((s)->edi) -#define get_esi(s) ((s)->esi) -#define get_ebp(s) ((s)->ebp) -#define get_esp(s) ((s)->esp) -#define get_ebx(s) ((s)->ebx) -#define get_edx(s) ((s)->edx) -#define get_ecx(s) ((s)->ecx) -#define get_eax(s) ((s)->eax) -#define get_eip(s) ((s)->eip) -#define get_eflags(s) ((s)->eflags) -#define get_es(s) ((s)->es) -#define get_ds(s) ((s)->ds) -#define get_ss(s) ((s)->ss) -#define get_fs(s) ((s)->fs) -#define get_gs(s) ((s)->gs) -#define get_cs(s) ((s)->cs) -#define get_trapno(s) ((s)->trapno) -#define get_err(s) ((s)->err) -#define get_cr2(s) ((s)->cr2) +#ifdef __APPLE__ +extern uint16_t _es; +extern uint16_t _ds; +#define _rdi ((*scp)->__ss.__rdi) +#define _rsi ((*scp)->__ss.__rsi) +#define _rbp ((*scp)->__ss.__rbp) +#define _rsp ((*scp)->__ss.__rsp) +#define _rbx ((*scp)->__ss.__rbx) +#define _rdx ((*scp)->__ss.__rdx) +#define _rcx ((*scp)->__ss.__rcx) +#define _rax ((*scp)->__ss.__rax) +#define _rip ((*scp)->__ss.__rip) +extern uint16_t _cs; +extern uint16_t _gs; +extern uint16_t _fs; +extern uint16_t _ss; +extern uint64_t _err; +extern uint64_t _eflags; +#define _eflags_ _eflags +extern uint64_t _cr2; +extern uint16_t _trapno; +#define __fpstate (&(*scp)->__fs) +#define PRI_RG PRIx64 +#elif defined(__FreeBSD__) +#ifdef __x86_64__ +#define _rax scp->mc_rax +#define _rbx scp->mc_rbx +#define _rcx scp->mc_rcx +#define _rdx scp->mc_rdx +#define _rbp scp->mc_rbp +#define _rsp scp->mc_rsp +#define _rsi scp->mc_rsi +#define _rdi scp->mc_rdi +#define _rip scp->mc_rip +#define _eflags (*(unsigned *)&scp->mc_rflags) +#define _eflags_ (*(const unsigned *)&scp->mc_rflags) +#define _cr2 (*(uint64_t *)&scp->mc_spare[0]) +#define PRI_RG PRIx64 +#else +#define _eax scp->mc_eax +#define _ebx scp->mc_ebx +#define _ecx scp->mc_ecx +#define _edx scp->mc_edx +#define _ebp scp->mc_ebp +#define _esp scp->mc_esp +#define _esi scp->mc_esi +#define _edi scp->mc_edi +#define _eip scp->mc_eip +#define _eflags scp->mc_eflags +#define _eflags_ scp->mc_eflags +#define _cr2 scp->mc_spare[0] +#define PRI_RG PRIx32 +#endif +#define _cs (*(unsigned *)&scp->mc_cs) +#define _ds (*(unsigned *)&scp->mc_ds) +#define _es (*(unsigned *)&scp->mc_es) +#define _ds_ (*(const unsigned *)&scp->mc_ds) +#define _es_ (*(const unsigned *)&scp->mc_es) +#define _fs (*(unsigned *)&scp->mc_fs) +#define _gs (*(unsigned *)&scp->mc_gs) +#define _ss (*(unsigned *)&scp->mc_ss) +#define _trapno scp->mc_trapno +#define _err (*(unsigned *)&scp->mc_err) +#define __fpstate scp->mc_fpstate +#elif defined(__x86_64__) +#define _es (((union g_reg *)&(scp->gregs[REG_TRAPNO]))->w[1]) +#define _ds (((union g_reg *)&(scp->gregs[REG_TRAPNO]))->w[2]) +#define _es_ (((const union g_reg *)&(scp->gregs[REG_TRAPNO]))->w[1]) +#define _ds_ (((const union g_reg *)&(scp->gregs[REG_TRAPNO]))->w[2]) +#define get_rdi(s) ((s)->gregs[REG_RDI]) +#define get_rsi(s) ((s)->gregs[REG_RSI]) +#define get_rbp(s) ((s)->gregs[REG_RBP]) +#define get_rsp(s) ((s)->gregs[REG_RSP]) +#define get_rbx(s) ((s)->gregs[REG_RBX]) +#define get_rdx(s) ((s)->gregs[REG_RDX]) +#define get_rcx(s) ((s)->gregs[REG_RCX]) +#define get_rax(s) ((s)->gregs[REG_RAX]) +#define get_rip(s) ((s)->gregs[REG_RIP]) +#define get_rflags(s) ((s)->gregs[REG_EFL]) +#define get_es(s) (((union g_reg *)&((s)->gregs[REG_TRAPNO]))->w[1]) +#define get_ds(s) (((union g_reg *)&((s)->gregs[REG_TRAPNO]))->w[2]) +#define get_ss(s) (((union g_reg *)&(s)->gregs[REG_CSGSFS])->w[3]) +#define get_fs(s) (((union g_reg *)&(s)->gregs[REG_CSGSFS])->w[2]) +#define get_gs(s) (((union g_reg *)&(s)->gregs[REG_CSGSFS])->w[1]) +#define get_cs(s) (((union g_reg *)&(s)->gregs[REG_CSGSFS])->w[0]) +#define _rdi get_rdi(scp) +#define _rsi get_rsi(scp) +#define _rbp get_rbp(scp) +#define _rsp get_rsp(scp) +#define _rbx get_rbx(scp) +#define _rdx get_rdx(scp) +#define _rcx get_rcx(scp) +#define _rax get_rax(scp) +#define _rip get_rip(scp) +#define _cs (((union g_reg *)&scp->gregs[REG_CSGSFS])->w[0]) +#define _cs_ (((const union g_reg *)&scp->gregs[REG_CSGSFS])->w[0]) +#define _gs (((union g_reg *)&scp->gregs[REG_CSGSFS])->w[1]) +#define _fs (((union g_reg *)&scp->gregs[REG_CSGSFS])->w[2]) +#define _ss (((union g_reg *)&scp->gregs[REG_CSGSFS])->w[3]) +#define _err DWORD_(scp->gregs[REG_ERR]) +#define _eflags DWORD_(scp->gregs[REG_EFL]) +#define _eflags_ DWORD__(scp->gregs[REG_EFL], const) +#define _cr2 (scp->gregs[REG_CR2]) +#define _trapno (((union g_reg *)&(scp->gregs[REG_TRAPNO]))->w[0]) +#define __fpstate (scp->fpregs) +#define PRI_RG "llx" +#else +#define _es (scp->gregs[REG_ES]) +#define _ds (scp->gregs[REG_DS]) +#define _es_ (scp->gregs[REG_ES]) +#define _ds_ (scp->gregs[REG_DS]) +#define get_edi(s) (*(uint32_t *)&(s)->gregs[REG_EDI]) +#define get_esi(s) (*(uint32_t *)&(s)->gregs[REG_ESI]) +#define get_ebp(s) (*(uint32_t *)&(s)->gregs[REG_EBP]) +#define get_esp(s) (*(uint32_t *)&(s)->gregs[REG_ESP]) +#define get_ebx(s) (*(uint32_t *)&(s)->gregs[REG_EBX]) +#define get_edx(s) (*(uint32_t *)&(s)->gregs[REG_EDX]) +#define get_ecx(s) (*(uint32_t *)&(s)->gregs[REG_ECX]) +#define get_eax(s) (*(uint32_t *)&(s)->gregs[REG_EAX]) +#define get_eip(s) (*(uint32_t *)&(s)->gregs[REG_EIP]) +#define get_eflags(s) (*(uint32_t *)&(s)->gregs[REG_EFL]) +#define get_es(s) ((s)->gregs[REG_ES]) +#define get_ds(s) ((s)->gregs[REG_DS]) +#define get_ss(s) ((s)->gregs[REG_SS]) +#define get_fs(s) ((s)->gregs[REG_FS]) +#define get_gs(s) ((s)->gregs[REG_GS]) +#define get_cs(s) ((s)->gregs[REG_CS]) #define _edi get_edi(scp) #define _esi get_esi(scp) #define _ebp get_ebp(scp) @@ -509,25 +624,64 @@ typedef struct pm_regs cpuctx_t; #define _ecx get_ecx(scp) #define _eax get_eax(scp) #define _eip get_eip(scp) -#define _edi_ (scp->edi) -#define _esi_ (scp->esi) -#define _ebp_ (scp->ebp) -#define _esp_ (scp->esp) -#define _ebx_ (scp->ebx) -#define _edx_ (scp->edx) -#define _ecx_ (scp->ecx) -#define _eax_ (scp->eax) -#define _eip_ (scp->eip) -#define _cs (scp->cs) -#define _cs_ (scp->cs) -#define _gs (scp->gs) -#define _fs (scp->fs) -#define _ss (scp->ss) -#define _err (scp->err) -#define _eflags (scp->eflags) -#define _eflags_ (scp->eflags) -#define _cr2 (scp->cr2) -#define _trapno (scp->trapno) +#define _edi_ (*(const uint32_t *)&scp->gregs[REG_EDI]) +#define _esi_ (*(const uint32_t *)&scp->gregs[REG_ESI]) +#define _ebp_ (*(const uint32_t *)&scp->gregs[REG_EBP]) +#define _esp_ (*(const uint32_t *)&scp->gregs[REG_ESP]) +#define _ebx_ (*(const uint32_t *)&scp->gregs[REG_EBX]) +#define _edx_ (*(const uint32_t *)&scp->gregs[REG_EDX]) +#define _ecx_ (*(const uint32_t *)&scp->gregs[REG_ECX]) +#define _eax_ (*(const uint32_t *)&scp->gregs[REG_EAX]) +#define _eip_ (*(const uint32_t *)&scp->gregs[REG_EIP]) +#define _cs (scp->gregs[REG_CS]) +#define _cs_ (scp->gregs[REG_CS]) +#define _gs (scp->gregs[REG_GS]) +#define _fs (scp->gregs[REG_FS]) +#define _ss (scp->gregs[REG_SS]) +#define _err (scp->gregs[REG_ERR]) +#define _eflags (scp->gregs[REG_EFL]) +#define _eflags_ (scp->gregs[REG_EFL]) +#define _cr2 (((union dword *)&scp->cr2)->d) +#define _trapno (((union g_reg *)&(scp->gregs[REG_TRAPNO]))->w[0]) +#define __fpstate (scp->fpregs) +#define PRI_RG PRIx32 +#endif +#ifdef __x86_64__ +#define get_edi(s) DWORD_(get_rdi(s)) +#define get_esi(s) DWORD_(get_rsi(s)) +#define get_ebp(s) DWORD_(get_rbp(s)) +#define get_esp(s) DWORD_(get_rsp(s)) +#define get_ebx(s) DWORD_(get_rbx(s)) +#define get_edx(s) DWORD_(get_rdx(s)) +#define get_ecx(s) DWORD_(get_rcx(s)) +#define get_eax(s) DWORD_(get_rax(s)) +#define get_eip(s) DWORD_(get_rip(s)) +#define get_eax(s) DWORD_(get_rax(s)) +#define get_eip(s) DWORD_(get_rip(s)) +#define get_eflags(s) DWORD_(get_rflags(s)) +#define _edi DWORD_(get_rdi(scp)) +#define _esi DWORD_(get_rsi(scp)) +#define _ebp DWORD_(get_rbp(scp)) +#define _esp DWORD_(get_rsp(scp)) +#define _ebx DWORD_(get_rbx(scp)) +#define _edx DWORD_(get_rdx(scp)) +#define _ecx DWORD_(get_rcx(scp)) +#define _eax DWORD_(get_rax(scp)) +#define _eip DWORD_(get_rip(scp)) +#define _eax DWORD_(get_rax(scp)) +#define _eip DWORD_(get_rip(scp)) +#define _edi_ DWORD__(_rdi, const) +#define _esi_ DWORD__(_rsi, const) +#define _ebp_ DWORD__(_rbp, const) +#define _esp_ DWORD__(_rsp, const) +#define _ebx_ DWORD__(_rbx, const) +#define _edx_ DWORD__(_rdx, const) +#define _ecx_ DWORD__(_rcx, const) +#define _eax_ DWORD__(_rax, const) +#define _eip_ DWORD__(_rip, const) +#define _eax_ DWORD__(_rax, const) +#define _eip_ DWORD__(_rip, const) +#else /* compatibility */ #define _rdi _edi #define _rsi _esi @@ -540,17 +694,20 @@ typedef struct pm_regs cpuctx_t; #define _rip _eip #define _rax _eax #define _rip _eip +#endif void show_regs(void); void show_ints(int, int); char *emu_disasm(unsigned int ip); void dump_state(void); -int cpu_trap_0f (unsigned char *, cpuctx_t *); +int cpu_trap_0f (unsigned char *, sigcontext_t *); -#define _PAGE_MASK (~(PAGE_SIZE-1)) +#ifndef PAGE_MASK +#define PAGE_MASK (~(PAGE_SIZE-1)) +#endif /* to align the pointer to the (next) page boundary */ -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&_PAGE_MASK) +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) enum { es_INDEX, cs_INDEX, ss_INDEX, ds_INDEX, fs_INDEX, gs_INDEX, eax_INDEX, ebx_INDEX, ecx_INDEX, edx_INDEX, esi_INDEX, edi_INDEX, diff --git a/src/include/disks.h b/src/include/disks.h index 0d9918d..42faf4b 100644 --- a/src/include/disks.h +++ b/src/include/disks.h @@ -8,13 +8,11 @@ #include "fatfs.h" #define PART_INFO_START 0x1be /* offset in MBR for partition table */ #define PART_INFO_LEN 0x10 /* size of each partition record */ -#define MBR_SIG 0xaa55 /* magic signature */ -#define VBR_SIG 0xaa55 /* magic signature */ +#define PART_SIG 0x55aa /* magic signature */ #define PART_NOBOOT 0 #define PART_BOOT 0x80 -#include #include #include #include @@ -62,41 +60,6 @@ struct on_disk_bpb { char v400_vol_label[11]; char v400_fat_type[8]; } __attribute__((packed)); -static_assert(sizeof(struct on_disk_bpb) == 51, - "on_disk_bpb size is incorrect"); - -struct on_disk_bpb7 { - uint16_t bytes_per_sector; - uint8_t sectors_per_cluster; - uint16_t reserved_sectors; - uint8_t num_fats; - uint16_t num_root_entries; - uint16_t num_sectors_small; - uint8_t media_type; - uint16_t sectors_per_fat; - uint16_t sectors_per_track; - uint16_t num_heads; - uint32_t hidden_sectors; - uint32_t num_sectors_large; // this and above are v3.31 equivalent - - uint32_t logical_sectors_per_fat; - uint16_t mirroring_flags; - uint16_t version; - uint32_t root_directory_cluster; - uint16_t information_sector; - uint16_t backup_sector; - char boot_file_name[12]; - uint8_t drive_number; - uint8_t flags; -#define BPB_SIG_V7_SHORT 0x28 -#define BPB_SIG_V7_LONG 0x29 - uint8_t signature; - uint32_t serial_number; - char long_vol_label[11]; - char long_fat_type[8]; -} __attribute__((packed)); -static_assert(sizeof(struct on_disk_bpb7) == 79, - "on_disk_bpb7 size is incorrect"); #define PTBL_HL_SET(p, f, v) do { \ (p)->f##_hi = (v) >> 8; \ @@ -117,34 +80,11 @@ struct on_disk_partition { unsigned int num_sect_preceding; /* starting sector counting from 0 */ unsigned int num_sectors; /* nr of sectors in partition */ } __attribute__((packed)); -static_assert(sizeof(struct on_disk_partition) == 16, - "on_disk_partition size is incorrect"); - -struct on_disk_mbr { - uint8_t code[PART_INFO_START]; - struct on_disk_partition partition[4]; - uint16_t signature; /* MBR_SIG 0xaa55 */ -} __attribute__((packed)); -static_assert(sizeof(struct on_disk_mbr) == 512, - "on_disk_mbr size is incorrect"); - -union ubpb { - struct on_disk_bpb bpb; - struct on_disk_bpb7 bpb7; -}; - -struct on_disk_vbr { - uint8_t code[0x0b]; - union ubpb u; - uint8_t pad[0x200 - 0x0b - sizeof(union ubpb) - 0x02]; - uint16_t signature; /* VBR_SIG 0xaa55 */ -} __attribute__((packed)); -static_assert(sizeof(struct on_disk_vbr) == 512, - "on_disk_vbr size is incorrect"); struct partition { int number; - struct on_disk_mbr mbr; /* fake Master Boot Record */ + unsigned char *mbr; /* fake Master Boot Record */ + int mbr_size; /* usu. 1 sector */ }; /* CMOS types for the floppies */ @@ -174,13 +114,12 @@ struct disk { disk_t type; /* type of file: image, partition, disk */ off_t header; /* compensation for opt. pre-disk header */ int fdesc; /* file descriptor */ - int removable; /* real removable drive, can disappear */ + int removeable; /* real removable drive, can disappear */ int floppy; /* emulating floppy */ int timeout; /* seconds between floppy timeouts */ struct partition part_info; /* neato partition info */ fatfs_t *fatfs; /* for FAT file system emulation */ int mfs_idx; - int part_image; /* partition image */ }; /* NOTE: the "header" element in the structure above can (and will) be diff --git a/src/include/dlmalloc.h b/src/include/dlmalloc.h index b307e14..334bec7 100644 --- a/src/include/dlmalloc.h +++ b/src/include/dlmalloc.h @@ -425,7 +425,7 @@ DEFAULT_MMAP_THRESHOLD default: 256K #include "/usr/include/malloc.h" #else /* HAVE_USR_INCLUDE_MALLOC_H */ -struct _mallinfo { +struct mallinfo { MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ MALLINFO_FIELD_TYPE smblks; /* always 0 */ @@ -457,7 +457,7 @@ extern "C" { #define dlrealloc realloc #define dlvalloc valloc #define dlpvalloc pvalloc -#define dlmallinfo _mallinfo +#define dlmallinfo mallinfo #define dlmallopt mallopt #define dlmalloc_trim malloc_trim #define dlmalloc_stats malloc_stats @@ -614,7 +614,7 @@ size_t dlmalloc_max_footprint(void); be kept as longs, the reported values may wrap around zero and thus be inaccurate. */ -struct _mallinfo dlmallinfo(void); +struct mallinfo dlmallinfo(void); #endif /* NO_MALLINFO */ /* @@ -913,7 +913,7 @@ size_t mspace_max_footprint(mspace msp); mspace_mallinfo behaves as mallinfo, but reports properties of the given space. */ -struct _mallinfo mspace_mallinfo(mspace msp); +struct mallinfo mspace_mallinfo(mspace msp); #endif /* NO_MALLINFO */ /* diff --git a/src/include/dnative.h b/src/include/dnative.h deleted file mode 100644 index 4d720f9..0000000 --- a/src/include/dnative.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include "../dosext/dpmi/dnative/dnative.h" diff --git a/src/include/dos.h b/src/include/dos.h deleted file mode 100644 index 83963f5..0000000 --- a/src/include/dos.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include "../dosext/dpmi/doslib/dos.h" diff --git a/src/include/dos2linux.h b/src/include/dos2linux.h index 0749e13..7aa2bcf 100644 --- a/src/include/dos2linux.h +++ b/src/include/dos2linux.h @@ -18,15 +18,6 @@ struct MCB { char name[8]; /* 8 */ } __attribute__((packed)); -#define HMCB_SIG 0x534d -struct HMCB { - uint16_t signature; // "MS" - uint16_t owner; // 0000=free, 0001=DOS, FF33=IO.SYS, FFFF=MSDOS.SYS - uint16_t size; // bytes not including this header - uint16_t next; // offset of next memory block in segment FFFFh, or 0000h if last - uint8_t reserved[8]; // unused (explicitly set to 0 for MS-DOS 7.10) -} __attribute__((packed)); - struct DSCB { char stype; /* 0 (subsegment type) 'D' device driver @@ -37,8 +28,7 @@ struct DSCB { 'C' BUFFERS EMS workspace area if BUFFERS /X is used 'B' BUFFERS= storage area 'L' LASTDRIVE= current directory structure array - 'S' STACKS= code/data area, if present (see below) - 'T' Transition code (Dos7book.pdf pg 603) */ + 'S' STACKS= code/data area, if present (see below) */ uint16_t start; /* 1 (segment) */ uint16_t size; /* 3 (paragraphs) */ char padding[3]; /* 5 */ @@ -180,12 +170,77 @@ struct lowstring { } __attribute__((packed)); typedef u_char *sdb_t; + +#define sdb_drive_letter(sdb) (*(u_char *)&sdb[sdb_drive_letter_off]) +#define sdb_template_name(sdb) ((char *)&sdb[sdb_template_name_off]) +#define sdb_template_ext(sdb) ((char *)&sdb[sdb_template_ext_off]) +#define sdb_attribute(sdb) (*(u_char *)&sdb[sdb_attribute_off]) +#define sdb_dir_entry(sdb) (*(u_short *)&sdb[sdb_dir_entry_off]) +#define sdb_p_cluster(sdb) (*(u_short *)&sdb[sdb_p_cluster_off]) +#define sdb_file_name(sdb) ((char *)&sdb[sdb_file_name_off]) +#define sdb_file_ext(sdb) ((char *)&sdb[sdb_file_ext_off]) +#define sdb_file_attr(sdb) (*(u_char *)&sdb[sdb_file_attr_off]) +#define sdb_file_time(sdb) (*(u_short *)&sdb[sdb_file_time_off]) +#define sdb_file_date(sdb) (*(u_short *)&sdb[sdb_file_date_off]) +#define sdb_file_st_cluster(sdb)(*(u_short *)&sdb[sdb_file_st_cluster_off]) +#define sdb_file_size(sdb) (*(u_int *)&sdb[sdb_file_size_off]) + typedef u_char *sft_t; + +#define sft_handle_cnt(sft) (*(u_short *)&sft[sft_handle_cnt_off]) +#define sft_open_mode(sft) (*(u_short *)&sft[sft_open_mode_off]) +#define sft_attribute_byte(sft) (*(u_char *)&sft[sft_attribute_byte_off]) +#define sft_device_info(sft) (*(u_short *)&sft[sft_device_info_off]) +#define sft_dev_drive_ptr(sft) (*(u_int *)&sft[sft_dev_drive_ptr_off]) +#define sft_start_cluster(sft) (*(u_short *)&sft[sft_start_cluster_off]) +#define sft_time(sft) (*(u_short *)&sft[sft_time_off]) +#define sft_date(sft) (*(u_short *)&sft[sft_date_off]) +#define sft_size(sft) (*(u_int *)&sft[sft_size_off]) +#define sft_position(sft) (*(u_int *)&sft[sft_position_off]) +#define sft_rel_cluster(sft) (*(u_short *)&sft[sft_rel_cluster_off]) +#define sft_abs_cluster(sft) (*(u_short *)&sft[sft_abs_cluster_off]) +#define sft_directory_sector(sft) (*(u_short *)&sft[sft_directory_sector_off]) +#define sft_directory_entry(sft) (*(u_char *)&sft[sft_directory_entry_off]) +#define sft_name(sft) ( (char *)&sft[sft_name_off]) +#define sft_ext(sft) ( (char *)&sft[sft_ext_off]) + +#define sft_fd(sft) (*(u_char *)&sft[sft_fd_off]) + typedef u_char *cds_t; -typedef u_short *psp_t; + typedef u_char *sda_t; extern sda_t sda; extern int sda_cur_drive_off; + +#define sda_current_dta(sda) (FARADDR((far_t *)&sda[sda_current_dta_off])) +#define sda_error_code(sda) (*(u_short *)&sda[4]) +#define sda_cur_psp(sda) (*(u_short *)&sda[sda_cur_psp_off]) +#define sda_cur_drive(sda) (*(u_char *)&sda[sda_cur_drive_off]) +#define sda_filename1(sda) ((char *)&sda[sda_filename1_off]) +#define sda_filename2(sda) ((char *)&sda[sda_filename2_off]) +#define sda_sdb(sda) ((sdb_t )&sda[sda_sdb_off]) +#define sda_cds(sda) ((cds_t)(uintptr_t)(FARPTR((far_t *)&sda[sda_cds_off]))) +#define sda_search_attribute(sda) (*(u_char *)&sda[sda_search_attribute_off]) +#define sda_open_mode(sda) (*(u_char *)&sda[sda_open_mode_off]) +#define sda_rename_source(sda) ((sdb_t )&sda[sda_rename_source_off]) +#define sda_user_stack(sda) ((char *)(uintptr_t)(FARPTR((far_t *)&sda[sda_user_stack_off]))) + +/* + * Data for extended open/create operations, DOS 4 or greater: + */ +#define sda_ext_act(sda) (*(u_short *)&sda[sda_ext_act_off]) +#define sda_ext_attr(sda) (*(u_short *)&sda[sda_ext_attr_off]) +#define sda_ext_mode(sda) (*(u_short *)&sda[sda_ext_mode_off]) + +#define psp_parent_psp(psp) (*(u_short *)&psp[0x16]) +#define psp_handles(psp) ((char *)(uintptr_t)(FARPTR((far_t *)&psp[0x34]))) + +#define lol_dpbfarptr(lol) (rFAR_FARt(READ_DWORD((lol)+lol_dpbfarptr_off))) +#define lol_cdsfarptr(lol) (rFAR_FARt(READ_DWORD((lol)+lol_cdsfarptr_off))) +#define lol_last_drive(lol) (READ_BYTE((lol)+lol_last_drive_off)) +#define lol_nuldev(lol) ((lol)+lol_nuldev_off) +#define lol_njoined(lol) ((lol)+lol_njoined_off) + extern int sdb_drive_letter_off; extern int sdb_template_name_off; extern int sdb_template_ext_off; @@ -248,76 +303,16 @@ typedef unsigned lol_t; extern lol_t lol; extern int lol_nuldev_off; -unsigned char sdb_drive_letter(sdb_t sdb); -char *sdb_template_name(sdb_t sdb); -char *sdb_template_ext(sdb_t sdb); -unsigned char sdb_attribute(sdb_t sdb); -unsigned short sdb_dir_entry(sdb_t sdb); -unsigned short sdb_p_cluster(sdb_t sdb); -char *sdb_file_name(sdb_t sdb); -char *sdb_file_ext(sdb_t sdb); -unsigned char sdb_file_attr(sdb_t sdb); -unsigned short sdb_file_time(sdb_t sdb); -unsigned short sdb_file_date(sdb_t sdb); -unsigned short sdb_file_st_cluster(sdb_t sdb); -Bit32u sdb_file_size(sdb_t sdb); - -unsigned short sft_handle_cnt(sft_t sft); -unsigned short sft_open_mode(sft_t sft); -unsigned char sft_attribute_byte(sft_t sft); -unsigned short sft_device_info(sft_t sft); -Bit32u sft_dev_drive_ptr(sft_t sft); -unsigned short sft_start_cluster(sft_t sft); -unsigned short sft_time(sft_t sft); -unsigned short sft_date(sft_t sft); -Bit32u sft_size(sft_t sft); -Bit32u sft_position(sft_t sft); -unsigned short sft_rel_cluster(sft_t sft); -unsigned short sft_abs_cluster(sft_t sft); -unsigned short sft_directory_sector(sft_t sft); -unsigned char sft_directory_entry(sft_t sft); -char *sft_name(sft_t sft); -char *sft_ext(sft_t sft); -unsigned short sft_fd(sft_t sft); - -dosaddr_t sda_current_dta(sda_t sda); -unsigned short sda_error_code(sda_t sda); -unsigned short sda_cur_psp(sda_t sda); -unsigned char sda_cur_drive(sda_t sda); -char *sda_filename1(sda_t sda); -char *sda_filename2(sda_t sda); -sdb_t sda_sdb(sda_t sda); -cds_t sda_cds(sda_t sda); -unsigned char sda_search_attribute(sda_t sda); -unsigned char sda_open_mode(sda_t sda); -sdb_t sda_rename_source(sda_t sda); -char *sda_user_stack(sda_t sda); - -/* - * Data for extended open/create operations, DOS 4 or greater: - */ -unsigned short sda_ext_act(sda_t sda); -unsigned short sda_ext_attr(sda_t sda); -unsigned short sda_ext_mode(sda_t sda); - -unsigned short psp_parent_psp(psp_t psp); -char *psp_handles(psp_t psp); - -far_t lol_dpbfarptr(lol_t lol); -far_t lol_cdsfarptr(lol_t lol); -char lol_last_drive(lol_t lol); - extern int com_errno; extern far_t get_nuldev(void); extern char *misc_e6_options (void); -extern void misc_e6_store_options(const char *str); +extern void misc_e6_store_options(char *str); -int run_unix_command(int argc, const char **argv, int bg); -int run_unix_secure(const char *prg); -int change_config(unsigned item, void *buf, int grab_active, - int kbd_grab_active, int clip_mode); +int run_unix_command(int argc, char **argv); +int run_unix_secure(char *prg); +extern int change_config(unsigned item, void *buf, int grab_active, int kbd_grab_active); void show_welcome_screen(void); @@ -361,12 +356,11 @@ int com_fprintf(int dosfilefd, const char *format, ...) FORMAT(printf, 2, 3); int com_printf(const char *format, ...) FORMAT(printf, 1, 2); int com_puts(const char *s); char *skip_white_and_delim(char *s, int delim); -#define pre_msdos() do { struct vm86_regs _saved_regs = REGS; int _is_tf +#define pre_msdos() do { struct vm86_regs _saved_regs = REGS; #define _post_msdos() REGS = _saved_regs -#define post_msdos() _is_tf = isset_TF(); REGS = _saved_regs; \ - if (_is_tf) set_TF(); } while(0) +#define post_msdos() REGS = _saved_regs; } while(0) void call_msdos(void); -int com_doswrite(int dosfilefd, const char *buf32, u_short size); +int com_doswrite(int dosfilefd, char *buf32, u_short size); int com_dosread(int dosfilefd, char *buf32, u_short size); int com_dosreadcon(char *buf32, u_short size); int com_doswritecon(const char *buf32, u_short size); @@ -385,15 +379,13 @@ extern unsigned short dos_to_unicode_table[0x100]; #define toupperDOS(c) (upperDOS_table[(unsigned char)(c)]) #define tolowerDOS(c) (lowerDOS_table[(unsigned char)(c)]) char *strupperDOS(char *s); -char *strnupperDOS(char *s, int n); char *strlowerDOS(char *s); -char *strnlowerDOS(char *s, int n); #define iscntrlDOS(c) (((unsigned char)(c)) < 0x20) int strequalDOS(const char *s1, const char *s2); char *strstrDOS(char *haystack, const char *upneedle); int name_ufs_to_dos(char *dest, const char *src); -void dos2tty_init(void); +int dos2tty_init(void); void dos2tty_done(void); #endif /* DOS2LINUX_H */ diff --git a/src/include/dosemu_config.h b/src/include/dosemu_config.h index 30b89e8..dd57842 100644 --- a/src/include/dosemu_config.h +++ b/src/include/dosemu_config.h @@ -47,32 +47,27 @@ extern int config_check_only; #define FREEDOS_DIR "freedos" /* freedos dir name */ #define FDBOOT_DIR "fdboot" /* freedos boot dir name */ #define XBAT_DIR "bat" /* extras */ -#define DOSEMULIB_DEFAULT "share/dosemu" +#define DOSEMULIB_DEFAULT DATADIR "/dosemu" #define DOSEMUCMDS_DEFAULT DOSEMULIB_DEFAULT "/" CMDS_SUFF -#define DOSEMUEXEC_DEFAULT LIBEXECDIR "/dosemu" +#define DOSEMULIBEXEC_DEFAULT LIBEXECDIR "/dosemu" #define DOSEMUIMAGE_DEFAULT "~/" LOCALDIR_BASE_NAME -#define DRIVE_C_DIR "drive_c" -#define DRIVE_C_DEFAULT DOSEMUIMAGE_DEFAULT "/" DRIVE_C_DIR +#define DRIVE_C_DEFAULT DOSEMUIMAGE_DEFAULT "/drive_c" #define DOSEMU_DRIVES_DIR "drives" -#define RUNDIR_PREFIX "/var/run/user" -#define DOSEMU_CONF_DIR SYSCONFDIR "/" CONFSUBDIR -#define DOSEMUPLUGINDIR "lib/dosemu" extern const char *config_script_name; extern const char *dosemu_loglevel_file_path; -extern char *dosemu_rundir_path; -extern char *dosemu_localdir_path; +extern const char *dosemu_rundir_path; +extern const char *dosemu_localdir_path; extern char *fddir_default; extern char *comcom_dir; extern char *fddir_boot; extern char *xbat_dir; -extern char *commands_path; -extern char *dosemu_lib_dir_path; -extern const char *dosemu_exec_dir_path; -extern char *dosemu_plugin_dir_path; -extern char *dosemu_image_dir_path; -extern char *dosemu_drive_c_path; +extern const char *commands_path; +extern const char *dosemu_lib_dir_path; +extern const char *dosemu_plugin_dir_path; +extern const char *dosemu_image_dir_path; +extern const char *dosemu_drive_c_path; extern char keymaploadbase_default[]; extern char *keymap_load_base_path; extern const char *keymap_dir_path; @@ -85,6 +80,19 @@ extern const char *dosemu_midi_in_path; extern struct cfg_string_store cfg_store; #define CFG_STORE (struct string_store *)&cfg_store +#define DOSEMU_LOGLEVEL_FILE dosemu_loglevel_file_path +#define RUNDIR dosemu_rundir_path +#define LOCALDIR dosemu_localdir_path +#define KEYMAP_LOAD_BASE_PATH keymap_load_base_path +#define KEYMAP_DIR keymap_dir_path +#define OWNER_LOCKS owner_tty_locks +#define PATH_LOCKD tty_locks_dir_path +#define NAME_LOCKF tty_locks_name_path +#define DOSEMU_MAP_PATH dosemu_map_file_name +#define DOSEMU_MIDI_PATH dosemu_midi_path +#define DOSEMU_MIDI_IN_PATH dosemu_midi_in_path +#define DOSEMU_CONF_DIR SYSCONFDIR "/" CONFSUBDIR + extern char *dosemu_map_file_name; #endif diff --git a/src/include/dosemu_debug.h b/src/include/dosemu_debug.h index de73315..75de2ea 100644 --- a/src/include/dosemu_debug.h +++ b/src/include/dosemu_debug.h @@ -73,8 +73,6 @@ extern int shut_debug; /* unconditional message into debug log */ #define dbug_printf(f,a...) ifprintf(10,f,##a) -/* error() is defined by glibc, so add underscores */ -#define error __error /* unconditional message into debug log and stderr */ void error(const char *fmt, ...) FORMAT(printf, 1, 2); #define error_once(s, ... ) do { \ diff --git a/src/include/doshelpers.h b/src/include/doshelpers.h index 60c8512..6d33c8b 100644 --- a/src/include/doshelpers.h +++ b/src/include/doshelpers.h @@ -33,7 +33,7 @@ */ #define DOS_HELPER_INT 0xE6 /* The interrupt we use */ -#define DOS_HELPER_MAGIC 0xaa55 +#define DOS_HELPER_MAGIC 0xaa55 #define DOS_HELPER_DOSEMU_CHECK 0x00 #define DOS_HELPER_SHOW_REGS 0x01 @@ -44,13 +44,11 @@ #define DOS_HELPER_INSERT_INTO_KEYBUFFER 0x06 /* OLD, depreciated */ #define DOS_HELPER_GET_BIOS_KEY 0x07 /* OLD, depreciated */ #define DOS_HELPER_VIDEO_INIT 0x08 -#define DOS_HELPER_PRESTROKES_START 0x09 #define DOS_HELPER_GET_DEBUG_STRING 0x10 #define DOS_HELPER_SET_DEBUG_STRING 0x11 #define DOS_HELPER_SET_HOGTHRESHOLD 0x12 #define DOS_HELPER_PRINT_STRING 0x13 /* ES:DX point to a NULL terminated string */ -#define DOS_HELPER_TEST_MODE 0x14 #define DOS_HELPER_MFS_HELPER 0x20 #define DOS_SUBHELPER_MFS_EMUFS_INIT 0 @@ -75,8 +73,6 @@ #define DOS_SUBHELPER_SERIAL_FOSSIL_CHECK 0 #define DOS_SUBHELPER_SERIAL_TSR_INSTALL 1 #define DOS_SUBHELPER_SERIAL_FOSSIL_INIT 2 -#define DOS_SUBHELPER_SERIAL_COMREDIR_INIT 3 - #define DOS_ERROR_SERIAL_ALREADY_INSTALLED 1 #define DOS_ERROR_SERIAL_CONFIG_DISABLED 2 #define DOS_ERROR_SERIAL_TSR_INVALID 3 diff --git a/src/include/dpmi.h b/src/include/dpmi.h deleted file mode 100644 index 5f471d2..0000000 --- a/src/include/dpmi.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include "../dosext/dpmi/doslib/dpmi.h" diff --git a/src/include/emm.h b/src/include/emm.h index 60e1be7..9b15a26 100644 --- a/src/include/emm.h +++ b/src/include/emm.h @@ -1,17 +1,7 @@ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * for details see file COPYING in the DOSEMU distribution */ #ifndef __EMS_H diff --git a/src/include/emu-ldt.h b/src/include/emu-ldt.h index e7787db..e6892af 100644 --- a/src/include/emu-ldt.h +++ b/src/include/emu-ldt.h @@ -29,7 +29,12 @@ #define DT_LIMIT(dp) ((uint32_t)((dp)->limit_hi<<16) | ((dp)->limit_lo)) #define DT_BASE(dp) (((uint32_t)(dp)->base_hi<<24) | ((dp)->base_mid<<16) | ((dp)->base_lo)) +#if defined(i386)||defined(__i386)||defined(__i386__)||defined(__x86_64__) #define DT_FLAGS(dp) (*((unsigned short *)(((char *)(dp))+5))&0xf0ff) +#endif +#if defined(ppc)||defined(__ppc)||defined(__ppc__) +#define DT_FLAGS(dp) (((char *)(dp))[5] | (unsigned int)(((char *)(dp))[6]&0xf0)<<8) +#endif #define MKLIMIT(dp,l) {(dp)->limit_lo=(l),(dp)->limit_hi=(l)>>16;} #define MKBASE(dp,b) {(dp)->base_lo=(b),(dp)->base_mid=(b)>>16,(dp)->base_hi=(b)>>24;} @@ -116,6 +121,10 @@ typedef struct { unsigned short IOmapbase; /* 66 */ } Task; +extern Descriptor *GDT; +extern Descriptor *LDT; +extern Gatedesc *IDT; + int emu_modify_ldt(int func, void *ptr, unsigned long bytecount); unsigned short GetSelectorXfer(unsigned short w); diff --git a/src/include/emu.h b/src/include/emu.h index c4243d9..a29a808 100644 --- a/src/include/emu.h +++ b/src/include/emu.h @@ -8,34 +8,31 @@ #include #include -/* androind NDK hack */ -#ifdef HAVE_BTHREAD_H -#include -#include -#endif #include "types.h" #include "cpu.h" #include "priv.h" #include "mouse.h" #include "dosemu_config.h" -#define MULTICORE_EXAMPLE 0 -#if MULTICORE_EXAMPLE -#define __TLS __thread -#else -#define __TLS -#endif - extern char * const *dosemu_envp; +struct eflags_fs_gs { + unsigned long eflags; + unsigned short fs, gs; +#ifdef __x86_64__ + unsigned char *fsbase, *gsbase; + unsigned short ds, es, ss; +#endif +}; + +extern struct eflags_fs_gs eflags_fs_gs; + int vm86_init(void); int vm86_fault(unsigned trapno, unsigned err, dosaddr_t cr2); -#ifdef __i386__ -void true_vm86_fault(sigcontext_t *scp); -#endif #define BIT(x) (1< IRQ3 .. IRQ15) */ @@ -329,12 +328,10 @@ typedef struct config_info { uint16_t mpu401_base; int mpu401_irq; int mpu401_irq_mt32; - uint16_t mpu401_base_mt32; + int mpu401_uart_irq_mt32; char *midi_synth; char *sound_driver; char *midi_driver; - char *fluid_sfont; - int fluid_volume; char *munt_roms_dir; char *snd_plugin_params; boolean pcm_hpf; @@ -364,9 +361,6 @@ typedef struct config_info { char *opl2lpt_device; int opl2lpt_type; - - int timer_tweaks; - int test_mode; } config_t; @@ -390,30 +384,23 @@ extern void parent_nextscan(void); extern void disk_close(void); extern void cpu_setup(void); extern void cpu_reset(void); -extern void raise_fpu_irq(void); extern void real_run_int(int); +#define run_int real_run_int extern void mfs_reset(void); -extern void mfs_done(void); extern int mfs_redirector(struct vm86_regs *regs, char *stk, int revect); extern int mfs_fat32(void); extern int mfs_lfn(void); extern int int10(void); extern int int13(void); -extern int ___int16(void); +extern int int16(void); extern int int17(void); -extern void irq_select(void); +extern void io_select(void); extern int pd_receive_packet(void); extern int printer_tick(u_long); extern void floppy_tick(void); -#ifdef __linux__ extern void open_kmem(void); extern void close_kmem(void); -#else -static inline void open_kmem(void) {} -static inline void close_kmem(void) {} -#endif -extern int parse_config(const char *, const char *, int); -extern void move_dosemu_local_dir(void); +extern int parse_config(const char *, const char *); extern void disk_init(void); extern void disk_reset(void); extern void serial_init(void); @@ -442,6 +429,12 @@ extern void leavedos_from_thread(int code); #define _leavedos_main(n, s) __leavedos_main_wrp(n, s, __func__, __LINE__) extern void __leavedos_main_wrp(int code, int sig, const char *s, int num); extern void check_leavedos(void); +extern void add_to_io_select_new(int, void(*)(void *), void *, + const char *name); +#define add_to_io_select(fd, func, arg) \ + add_to_io_select_new(fd, func, arg, #func) +extern void remove_from_io_select(int); +extern void ioselect_done(void); /* * DANG_BEGIN_REMARK @@ -470,8 +463,9 @@ extern void memory_init(void); extern void map_video_bios(void); extern void map_custom_bios(void); extern void stdio_init(void); +extern void time_setting_init(void); extern void timer_interrupt_init(void); -extern void map_memory_space(void); +extern void low_mem_init(void); extern void print_version(void); extern void keyboard_flags_init(void); extern void video_config_init(void); @@ -495,6 +489,7 @@ extern unsigned short detach (void); extern void disallocate_vt (void); extern void restore_vt (unsigned short vt); extern void HMA_init(void); +extern void HMA_MAP(int HMA); extern void hardware_run(void); extern int register_exit_handler(void (*handler)(void)); @@ -505,6 +500,4 @@ extern int hlt_unregister_handler_vm86(Bit16u start_addr); extern const char *Path_cdrom[]; -extern struct mempool main_pool; - #endif /* EMU_H */ diff --git a/src/include/emudpmi.h b/src/include/emudpmi.h index 803c899..8c2f3d7 100644 --- a/src/include/emudpmi.h +++ b/src/include/emudpmi.h @@ -1,16 +1,6 @@ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * for details see file COPYING in the DOSEMU distribution */ #include "../dosext/dpmi/emudpmi.h" diff --git a/src/include/evtimer.h b/src/include/evtimer.h deleted file mode 100644 index ceab6ec..0000000 --- a/src/include/evtimer.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef EVTIMER_H -#define EVTIMER_H - -#include - -#define NANOSECONDS_PER_SECOND 1000000000LL - -#define SCALE_MS 1000000LL -#define SCALE_US 1000LL -#define SCALE_NS 1LL - -void *evtimer_create(void (*cbk)(int ticks, void *), void *arg); -void evtimer_delete(void *tmr); -void evtimer_set_rel(void *tmr, uint64_t ns, int periodic); -uint64_t evtimer_gettime(void *tmr); -void evtimer_stop(void *tmr); -void evtimer_block(void *tmr); -void evtimer_unblock(void *tmr); - -#endif diff --git a/src/include/fls.h b/src/include/fls.h deleted file mode 100644 index e3c7b4d..0000000 --- a/src/include/fls.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_GENERIC_BITOPS_FLS_H_ -#define _ASM_GENERIC_BITOPS_FLS_H_ - -/** - * fls - find last (most-significant) bit set - * @x: the word to search - * - * This is defined the same way as ffs. - * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. - */ -#ifndef HAVE_FLS -static inline int fls(unsigned int x) -{ - int r = 32; - - if (!x) - return 0; - if (!(x & 0xffff0000u)) { - x <<= 16; - r -= 16; - } - if (!(x & 0xff000000u)) { - x <<= 8; - r -= 8; - } - if (!(x & 0xf0000000u)) { - x <<= 4; - r -= 4; - } - if (!(x & 0xc0000000u)) { - x <<= 2; - r -= 2; - } - if (!(x & 0x80000000u)) { - x <<= 1; - r -= 1; - } - return r; -} -#endif - -#endif /* _ASM_GENERIC_BITOPS_FLS_H_ */ diff --git a/src/include/generic-non-atomic.h b/src/include/generic-non-atomic.h deleted file mode 100644 index 7e444a5..0000000 --- a/src/include/generic-non-atomic.h +++ /dev/null @@ -1,171 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H -#define __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H - -#include - -#ifdef __LP64__ -#define BITS_PER_LONG 64 -#else -#define BITS_PER_LONG 32 -#endif -#define BIT_ULL(nr) (ULL(1) << (nr)) -#define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG)) -#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) -#define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG)) -#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) -#define BITS_PER_BYTE 8 -#define UL(x) ((unsigned long)(x)) - -/* - * Generic definitions for bit operations, should not be used in regular code - * directly. - */ - -/** - * generic___set_bit - Set a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - * - * Unlike set_bit(), this function is non-atomic and may be reordered. - * If it's called on the same region of memory simultaneously, the effect - * may be that only one operation succeeds. - */ -static inline void -generic___set_bit(unsigned long nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); - - *p |= mask; -} - -static inline void -generic___clear_bit(unsigned long nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); - - *p &= ~mask; -} - -/** - * generic___change_bit - Toggle a bit in memory - * @nr: the bit to change - * @addr: the address to start counting from - * - * Unlike change_bit(), this function is non-atomic and may be reordered. - * If it's called on the same region of memory simultaneously, the effect - * may be that only one operation succeeds. - */ -static inline void -generic___change_bit(unsigned long nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); - - *p ^= mask; -} - -/** - * generic___test_and_set_bit - Set a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is non-atomic and can be reordered. - * If two examples of this operation race, one can appear to succeed - * but actually fail. You must protect multiple accesses with a lock. - */ -static inline bool -generic___test_and_set_bit(unsigned long nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); - unsigned long old = *p; - - *p = old | mask; - return (old & mask) != 0; -} - -/** - * generic___test_and_clear_bit - Clear a bit and return its old value - * @nr: Bit to clear - * @addr: Address to count from - * - * This operation is non-atomic and can be reordered. - * If two examples of this operation race, one can appear to succeed - * but actually fail. You must protect multiple accesses with a lock. - */ -static inline bool -generic___test_and_clear_bit(unsigned long nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); - unsigned long old = *p; - - *p = old & ~mask; - return (old & mask) != 0; -} - -/* WARNING: non atomic and it can be reordered! */ -static inline bool -generic___test_and_change_bit(unsigned long nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); - unsigned long old = *p; - - *p = old ^ mask; - return (old & mask) != 0; -} - -/** - * generic_test_bit - Determine whether a bit is set - * @nr: bit number to test - * @addr: Address to start counting from - */ -static inline bool -generic_test_bit(unsigned long nr, const unsigned long *addr) -{ - /* - * Unlike the bitops with the '__' prefix above, this one *is* atomic, - * so `volatile` must always stay here with no cast-aways. See - * `Documentation/atomic_bitops.txt` for the details. - */ - return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); -} - -/* - * const_*() definitions provide good compile-time optimizations when - * the passed arguments can be resolved at compile time. - */ -#define const___set_bit generic___set_bit -#define const___clear_bit generic___clear_bit -#define const___change_bit generic___change_bit -#define const___test_and_set_bit generic___test_and_set_bit -#define const___test_and_clear_bit generic___test_and_clear_bit -#define const___test_and_change_bit generic___test_and_change_bit -#define const_test_bit_acquire generic_test_bit_acquire - -/** - * const_test_bit - Determine whether a bit is set - * @nr: bit number to test - * @addr: Address to start counting from - * - * A version of generic_test_bit() which discards the `volatile` qualifier to - * allow a compiler to optimize code harder. Non-atomic and to be called only - * for testing compile-time constants, e.g. by the corresponding macros, not - * directly from "regular" code. - */ -static inline bool -const_test_bit(unsigned long nr, const unsigned long *addr) -{ - const unsigned long *p = (const unsigned long *)addr + BIT_WORD(nr); - unsigned long mask = BIT_MASK(nr); - unsigned long val = *p; - - return !!(val & mask); -} - -#endif /* __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H */ diff --git a/src/include/hma.h b/src/include/hma.h index 4c85f04..3e4afed 100644 --- a/src/include/hma.h +++ b/src/include/hma.h @@ -8,6 +8,8 @@ #define __HMA_H extern int a20; +extern unsigned char *ext_mem_base; void set_a20(int); +void extmem_copy(unsigned dst, unsigned src, unsigned len); #endif diff --git a/src/include/instremu.h b/src/include/instremu.h index 0daa3e1..91a3eff 100644 --- a/src/include/instremu.h +++ b/src/include/instremu.h @@ -1,8 +1,15 @@ #ifndef INSTREMU_H #define INSTREMU_H -int instr_len(unsigned char *ptr, int is_32); -int decode_modify_segreg_insn(cpuctx_t *scp, int pmode, +int instr_len(unsigned char *, int); +int instr_emu(sigcontext_t *scp, int pmode, int cnt); +int decode_modify_segreg_insn(sigcontext_t *scp, int pmode, unsigned int *new_val); +unsigned char instr_binary_byte(unsigned char op, unsigned char op1, + unsigned char op2, unsigned *eflags); +unsigned instr_binary_word(unsigned op, unsigned op1, + unsigned op2, unsigned *eflags); +unsigned instr_binary_dword(unsigned op, unsigned op1, + unsigned op2, unsigned *eflags); #endif diff --git a/src/include/int.h b/src/include/int.h index 545e37d..25628ff 100644 --- a/src/include/int.h +++ b/src/include/int.h @@ -25,7 +25,6 @@ void fake_retf(void); void fake_iret(void); void do_eoi_iret(void); void do_eoi2_iret(void); -void do_iret(void); void jmp_to(int cs, int ip); void setup_interrupts(void); void version_init(void); @@ -41,8 +40,7 @@ void update_xtitle(void); void int42_hook(void); -void add_syscom_drive(char *path, uint8_t *user); -void add_syscom_user(uint8_t *user); +int *add_syscom_drive(char *path); int add_extra_drive(char *path, int ro, int cd, int grp); int find_free_drive(void); uint16_t get_redirection(uint16_t redirIndex, char *deviceStr, int deviceSize, diff --git a/src/include/iodev.h b/src/include/iodev.h index 21eb1ff..928f3d2 100644 --- a/src/include/iodev.h +++ b/src/include/iodev.h @@ -19,9 +19,23 @@ extern void iodev_register(const char *name, void (*init_func)(void), void (*reset_func)(void), void (*term_func)(void)); void iodev_unregister(const char *name); void iodev_add_device(const char *dev_name); +/******************************************************************* + * Programmable Interrupt Timer (PIT) chip * + *******************************************************************/ + +typedef struct { + Bit16u read_state; + Bit16u write_state; + Bit8u mode, outpin; + Bit32u read_latch; + Bit16u write_latch; + Bit32s cntr; + hitimer_u time; +} pit_latch_struct; + +extern pit_latch_struct pit[PIT_TIMERS]; extern void pit_init(void); -extern void pit_done(void); extern void pit_reset(void); /******************************************************************* @@ -50,7 +64,6 @@ extern void pit_reset(void); #define SECS_PER_YEAR 31557600 /* any trivia buffs? */ extern void rtc_init(void); -extern void rtc_setup(void); extern void rtc_reset(void); extern void rtc_update(void); @@ -88,8 +101,4 @@ extern void hdisk_reset(void); extern void floppy_init(void); extern void floppy_reset(void); -void mt32_init(void); -void mt32_reset(void); -void mt32_done(void); - #endif /* _EMU_IODEV_H */ diff --git a/src/include/ioselect.h b/src/include/ioselect.h deleted file mode 100644 index a28ea0f..0000000 --- a/src/include/ioselect.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef IOSELECT_H -#define IOSELECT_H - -#define IOFLG_IMMED 1 -#define IOFLG_MASKED 2 -extern void add_to_io_select_new(int, void(*)(int, void *), void *, - unsigned flags, const char *name); -#define add_to_io_select(fd, func, arg) \ - add_to_io_select_new(fd, func, arg, 0, #func) -#define add_to_io_select_threaded(fd, func, arg) \ - add_to_io_select_new(fd, func, arg, IOFLG_IMMED, #func) -#define add_to_io_select_masked(fd, func, arg) \ - add_to_io_select_new(fd, func, arg, IOFLG_IMMED | IOFLG_MASKED, #func) -extern void remove_from_io_select(int); -extern void ioselect_complete(int fd); -extern void ioselect_block(int fd); -extern void ioselect_unblock(int fd); -extern void ioselect_init(void); -extern void ioselect_done(void); - -#endif diff --git a/src/include/ipx.h b/src/include/ipx.h index 3890b47..98aeda5 100644 --- a/src/include/ipx.h +++ b/src/include/ipx.h @@ -120,6 +120,8 @@ ipx_socket_t; extern void ipx_init(void); extern int IPXInt2FHandler(void); +extern int ipx_receive(int ilevel); +extern int IPXCheckForAESReady(int ilevel); extern void ipx_send_esr_call(void); extern int IPXGetLocalTarget( unsigned long network, int *hops, int *ticks ); extern void ipx_close(void); diff --git a/src/include/joystick.h b/src/include/joystick.h index ff35af4..05a0432 100644 --- a/src/include/joystick.h +++ b/src/include/joystick.h @@ -12,8 +12,6 @@ #ifndef JOYSTICK_H #define JOYSTICK_H -#ifdef __linux__ - /* init functions */ void joy_init (void); void joy_uninit (void); @@ -24,15 +22,4 @@ void joy_reset (void); int joy_exist (void); /* used by src/base/init/init.c */ int joy_bios_read (void); /* used by src/base/async/int.c */ -#else - -static inline void joy_init(void) {} -static inline void joy_uninit(void) {} -static inline void joy_term(void) {} -static inline void joy_reset(void) {} -static inline int joy_exist(void) { return 0; } -static inline int joy_bios_read(void) { return 0; } - -#endif - #endif /* JOYSTICK_H */ diff --git a/src/include/keyboard/keyb_clients.h b/src/include/keyboard/keyb_clients.h index 706d6af..f8ae41e 100644 --- a/src/include/keyboard/keyb_clients.h +++ b/src/include/keyboard/keyb_clients.h @@ -38,7 +38,6 @@ void register_keyboard_client(struct keyboard_client *keyboard); extern struct keyboard_client *Keyboard; extern struct keyboard_client Keyboard_raw; extern struct keyboard_client Keyboard_slang; -extern struct keyboard_client Keyboard_stdio; extern struct keyboard_client Keyboard_none; extern void dos_slang_redraw(void); diff --git a/src/include/keyboard/keyb_server.h b/src/include/keyboard/keyb_server.h index 82b1ae6..58abe27 100644 --- a/src/include/keyboard/keyb_server.h +++ b/src/include/keyboard/keyb_server.h @@ -18,8 +18,8 @@ * these are needed in some other modules, e.g. ports.c */ -Bit8u keyb_io_read(ioport_t port, void *arg); -void keyb_io_write(ioport_t port, Bit8u value, void *arg); +Bit8u keyb_io_read(ioport_t port); +void keyb_io_write(ioport_t port, Bit8u value); void keyb_8042_init(void); void keyb_8042_reset(void); @@ -69,7 +69,6 @@ void backend_reset(void); #define SP_PAUSE 0xff01 #define SP_BREAK 0xff02 -#define SP_CC 0x2e03 #define SP_PRTSCR 0xff03 #define SP_SYSRQ_MAKE 0xff04 #define SP_SYSRQ_BREAK 0xff05 diff --git a/src/include/keyboard/keyboard.h b/src/include/keyboard/keyboard.h index 79cf084..c97fe2d 100644 --- a/src/include/keyboard/keyboard.h +++ b/src/include/keyboard/keyboard.h @@ -66,7 +66,6 @@ void set_shiftstate(t_modifiers s); t_modifiers get_shiftstate(void); int type_in_pre_strokes(void); void append_pre_strokes(char *s); -void start_pre_strokes(void); struct char_set; void keyb_priv_init(void); diff --git a/src/include/kvm.h b/src/include/kvm.h index e397eec..59ee722 100644 --- a/src/include/kvm.h +++ b/src/include/kvm.h @@ -19,46 +19,34 @@ #include "emu.h" -#ifdef USE_KVM +#ifdef __linux__ /* kvm functions */ int init_kvm_cpu(void); +void init_kvm_monitor(void); int kvm_vm86(struct vm86_struct *info); -int kvm_dpmi(cpuctx_t *scp); +int kvm_dpmi(sigcontext_t *scp); void mprotect_kvm(int cap, dosaddr_t targ, size_t mapsize, int protect); -void mmap_kvm(int cap, unsigned phys_addr, size_t mapsize, void *addr, dosaddr_t targ, int protect); +void mmap_kvm(int cap, void *addr, size_t mapsize, int protect); +void munmap_kvm(int cap, dosaddr_t targ, size_t mapsize); void set_kvm_memory_regions(void); -void kvm_set_mmio(dosaddr_t base, dosaddr_t size, int on); -void kvm_set_dirty_log(dosaddr_t base, dosaddr_t size); -void kvm_get_dirty_map(dosaddr_t base, unsigned char *bitmap); void kvm_set_idt_default(int i); void kvm_set_idt(int i, uint16_t sel, uint32_t offs, int is_32, int tg); -void kvm_enter(int pm); -void kvm_leave(int pm); -void kvm_update_fpu(void); -void kvm_get_fpu(void); - void kvm_done(void); #else -static inline int init_kvm_cpu(void) { return 0; } +static inline int init_kvm_cpu(void) { return -1; } +static inline void init_kvm_monitor(void) {} static inline int kvm_vm86(struct vm86_struct *info) { return -1; } -static inline int kvm_dpmi(cpuctx_t *scp) { return -1; } +static inline int kvm_dpmi(sigcontext_t *scp) { return -1; } static inline void mprotect_kvm(int cap, dosaddr_t targ, size_t mapsize, int protect) {} -static inline void mmap_kvm(int cap, unsigned phys_addr, size_t mapsize, void *addr, dosaddr_t targ, int protect) {} +static inline void mmap_kvm(int cap, void *addr, size_t mapsize, int protect) {} static inline void munmap_kvm(int cap, dosaddr_t targ, size_t mapsize) {} static inline void set_kvm_memory_regions(void) {} -static inline void kvm_set_mmio(dosaddr_t base, dosaddr_t size, int on) {} -static inline void kvm_set_dirty_log(dosaddr_t base, dosaddr_t size) {} -static inline void kvm_get_dirty_map(dosaddr_t base, unsigned char *bitmap) {} static inline void kvm_set_idt_default(int i) {} static inline void kvm_set_idt(int i, uint16_t sel, uint32_t offs, int is_32, int tg) {} -static inline void kvm_enter(int pm) {} -static inline void kvm_leave(int pm) {} -static inline void kvm_update_fpu(void) {} -static inline void kvm_get_fpu(void) {} static inline void kvm_done(void) {} #endif diff --git a/src/include/lowmem.h b/src/include/lowmem.h index d2b9313..fe49a67 100644 --- a/src/include/lowmem.h +++ b/src/include/lowmem.h @@ -1,17 +1,7 @@ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * for details see file COPYING in the DOSEMU distribution */ #ifndef __LOWMEM_H diff --git a/src/include/mapping.h b/src/include/mapping.h index 89898bb..b3f6dcd 100644 --- a/src/include/mapping.h +++ b/src/include/mapping.h @@ -14,7 +14,6 @@ #include #include "memory.h" -#include "cpu-emu.h" #ifndef PAGE_SIZE #define PAGE_SIZE 4096 @@ -24,10 +23,6 @@ #endif #define EMM_PAGE_SIZE (16*1024) -#define HUGE_PAGE_SIZE ((uintptr_t)(2*1024*1024)) -#define HUGE_PAGE_MASK (~(HUGE_PAGE_SIZE-1)) -#define HUGE_PAGE_ALIGN(addr) (((addr)+HUGE_PAGE_SIZE-1)&HUGE_PAGE_MASK) - #define Q__printf(f,cap,a...) ({\ Q_printf(f,decode_mapping_cap(cap),##a); \ }) @@ -48,7 +43,9 @@ #define MAPPING_INIT_LOWRAM 0x000200 #define MAPPING_EXTMEM 0x000400 #define MAPPING_KVM 0x000800 -#define MAPPING_CPUEMU 0x001000 +#define MAPPING_IMMEDIATE 0x001000 +#define MAPPING_CPUEMU 0x002000 +#define MAPPING_KVM_UC 0x004000 /* usage as: (kind of mapping required) */ #define MAPPING_KMEM 0x010000 @@ -58,40 +55,34 @@ #define MAPPING_NULL 0x100000 #define MAPPING_NOOVERLAP 0x200000 -#ifdef __x86_64__ -#define _MAP_32BIT ((config.cpu_vm_dpmi == CPUVM_NATIVE) ? MAP_32BIT : 0) -#else -#define _MAP_32BIT 0 -#endif - typedef int open_mapping_type(int cap); int open_mapping (int cap); typedef void close_mapping_type(int cap); void close_mapping(int cap); -typedef void *alloc_mapping_type(int cap, size_t mapsize, void *target); +typedef void *alloc_mapping_type(int cap, size_t mapsize); void *alloc_mapping (int cap, size_t mapsize); -void *alloc_mapping_huge_page_aligned (int cap, size_t mapsize); typedef void free_mapping_type(int cap, void *addr, size_t mapsize); void free_mapping (int cap, void *addr, size_t mapsize); -typedef void *resize_mapping_type(int cap, void *addr, size_t oldsize, size_t newsize); +typedef void *realloc_mapping_type(int cap, void *addr, size_t oldsize, size_t newsize); void *realloc_mapping (int cap, void *addr, size_t oldsize, size_t newsize); -void *mmap_mapping_huge_page_aligned(int cap, size_t mapsize, int protect); -void *mmap_mapping(int cap, void *target, size_t mapsize, int protect); +void *mmap_mapping(int cap, dosaddr_t targ, size_t mapsize, int protect); +void *mremap_mapping(int cap, dosaddr_t from, size_t old_size, + size_t new_size); +void *mmap_mapping_ux(int cap, void *target, size_t mapsize, int protect); +void *mmap_file_ux(int cap, void *target, size_t mapsize, int protect, + int flags, int fd); typedef void *alias_mapping_type(int cap, void *target, size_t mapsize, int protect, void *source); int alias_mapping(int cap, dosaddr_t targ, size_t mapsize, int protect, void *source); -int alias_mapping_pa(int cap, unsigned addr, size_t mapsize, int protect, void *source); -int unalias_mapping_pa(int cap, unsigned addr, size_t mapsize); -void *alias_mapping_ux(int cap, size_t mapsize, int protect, void *source); +void *alias_mapping_high(int cap, size_t mapsize, int protect, void *source); int munmap_mapping(int cap, dosaddr_t targ, size_t mapsize); int mprotect_mapping(int cap, dosaddr_t targ, size_t mapsize, int protect); -int restore_mapping(int cap, dosaddr_t targ, size_t mapsize); struct mappingdrivers { const char *key; @@ -100,15 +91,15 @@ struct mappingdrivers { close_mapping_type *close; alloc_mapping_type *alloc; free_mapping_type *free; - resize_mapping_type *resize; + realloc_mapping_type *realloc; alias_mapping_type *alias; }; char *decode_mapping_cap(int cap); extern struct mappingdrivers mappingdriver_shm; extern struct mappingdrivers mappingdriver_mshm; -extern struct mappingdrivers mappingdriver_file; extern struct mappingdrivers mappingdriver_ashm; +extern struct mappingdrivers mappingdriver_file; extern int have_mremap_fixed; @@ -116,19 +107,13 @@ void mapping_init(void); void mapping_close(void); void init_hardware_ram(void); -int register_hardware_ram(int type, dosaddr_t base, unsigned size); -void register_hardware_ram_virtual(int type, unsigned base, unsigned size, - dosaddr_t va); -void register_hardware_ram_virtual2(int type, unsigned base, unsigned size, - void *uaddr, dosaddr_t va); -int unregister_hardware_ram_virtual(dosaddr_t base); -dosaddr_t get_hardware_ram(unsigned addr, uint32_t size); -void *get_hardware_uaddr(unsigned addr); +int map_hardware_ram(char type); +int map_hardware_ram_manual(size_t base, dosaddr_t vbase); +int unmap_hardware_ram(char type); +int register_hardware_ram(int type, unsigned base, unsigned size); +unsigned get_hardware_ram(unsigned addr, uint32_t size); void list_hardware_ram(void (*print)(const char *, ...)); void *mapping_find_hole(unsigned long start, unsigned long stop, unsigned long size); -int mcommit(void *ptr, size_t size); -int muncommit(void *ptr, size_t size); - #endif /* _MAPPING_H_ */ diff --git a/src/include/memory.h b/src/include/memory.h index e206250..7ec4685 100644 --- a/src/include/memory.h +++ b/src/include/memory.h @@ -27,13 +27,14 @@ /* don't change these for now, they're hardwired! */ #define Mouse_SEG (BIOSSEG-1) #define Mouse_INT_OFF (MOUSE_INT33_OFF + 0x10) +#define Mouse_ROUTINE ((BIOSSEG << 4)+Mouse_ROUTINE_OFF) /* intercept-stub for dosdebugger (catches INT21/AX=4B00 */ #define DBGload_SEG BIOSSEG #define DOSEMU_LMHEAP_SEG BIOSSEG -#define DOSEMU_LMHEAP_OFF lmheap_off() -#define DOSEMU_LMHEAP_SIZE lmheap_size() +#define DOSEMU_LMHEAP_OFF 0xa000 +#define DOSEMU_LMHEAP_SIZE 0x4000 #ifndef ROMBIOSSEG #define ROMBIOSSEG 0xf800 @@ -43,6 +44,9 @@ #define EMM_SEGMENT (config.ems_frame) +#define IPX_SEG BIOSSEG +#define IPX_ADD ((IPX_SEG << 4) + IPX_OFF) + #define INT08_SEG BIOSSEG #define INT08_ADD ((INT08_SEG << 4) + INT08_OFF) @@ -139,8 +143,6 @@ #define HMASIZE (64*1024) #define LOWMEM_SIZE 0x100000 #define EXTMEM_SIZE ((unsigned)(config.ext_mem << 10)) -#define XMS_SIZE ((unsigned)(config.xms_size << 10)) -#define xms_base (LOWMEM_SIZE + HMASIZE + EXTMEM_SIZE) #ifndef __ASSEMBLER__ @@ -154,10 +156,6 @@ u_short INT_OFF(u_char i); #define CBACK_SEG SREG(cs) #define CBACK_OFF LWORD(eip) -uint16_t lmheap_off(void); -uint16_t lmheap_size(void); -#define FDPP_LMHEAP_ADD (1024 * 3) - /* memcheck memory conflict finder definitions */ int memcheck_addtype(unsigned char map_char, const char *name); void memcheck_reserve(unsigned char map_char, dosaddr_t addr_start, @@ -172,20 +170,12 @@ int memcheck_findhole(dosaddr_t *start_addr, uint32_t min_size, uint32_t max_size); int memcheck_is_reserved(dosaddr_t addr_start, uint32_t size, unsigned char map_char); -int memcheck_is_rom(dosaddr_t addr); -int memcheck_is_hardware_ram(dosaddr_t addr); -int memcheck_is_system_ram(dosaddr_t addr); void memcheck_dump(void); void memcheck_type_init(void); extern struct system_memory_map *system_memory_map; extern size_t system_memory_map_size; void *dosaddr_to_unixaddr(dosaddr_t addr); -void *physaddr_to_unixaddr(unsigned addr); -dosaddr_t physaddr_to_dosaddr(unsigned addr, int len); - -#ifndef MAP_FAILED -#define MAP_FAILED (void*)-1 -#endif +void *physaddr_to_unixaddr(dosaddr_t addr); //void *lowmemp(const unsigned char *ptr); /* This is the global mem_base pointer: *all* memory is with respect @@ -194,18 +184,12 @@ dosaddr_t physaddr_to_dosaddr(unsigned addr, int len); give NULL pointer protection. */ extern unsigned char *mem_base; -extern uintptr_t mem_base_mask; #define LINP(a) ((unsigned char *)(uintptr_t)(a)) -static inline unsigned char *MEM_BASE32(dosaddr_t a) { -#if defined(__i386__) - /* we want to wrap around 4G; &mem_base[a] may cause issues with UBSAN */ - return LINP((uintptr_t)mem_base + a); -#elif defined(__x86_64__) - return LINP(((uintptr_t)mem_base + a) & mem_base_mask); -#else - return &mem_base[a]; -#endif +static inline unsigned char *MEM_BASE32(dosaddr_t a) +{ + uint32_t off = (uint32_t)((uintptr_t)mem_base + a); + return LINP(off); } static inline dosaddr_t DOSADDR_REL(const unsigned char *a) { diff --git a/src/include/mhpdbg.h b/src/include/mhpdbg.h index 7671fe7..698f45b 100644 --- a/src/include/mhpdbg.h +++ b/src/include/mhpdbg.h @@ -39,7 +39,7 @@ extern unsigned long dosdebug_flags; #define DBGF_IN_LEAVEDOS 0x40000000 -unsigned int mhp_debug(unsigned, unsigned int, unsigned int); +unsigned int mhp_debug(enum dosdebug_event, unsigned int, unsigned int); void mhp_send(void); void mhp_input(void); void mhp_close(void); @@ -54,20 +54,13 @@ int mhpdbg_is_stopped(void); int mhp_usermap_move_block(uint16_t oldseg, uint16_t newseg, uint16_t startoff, uint32_t blklen); int mhp_usermap_load_gnuld(const char *fname, uint16_t origin); -void mhpdbgc_init(void); -void mhp_init_hma(void); -void mhp_reset_hma(void); #ifdef USE_MHPDBG int mhp_revectored(int inum); -void mhp_adjust_revectored(int inum); #else static inline int mhp_revectored(int inum) { return 0; } -static inline void mhp_adjust_revectored(int inum) -{ -} #endif int vmhp_log_intercept(int flg, const char *fmt, va_list args); @@ -86,7 +79,7 @@ struct mhpdbg unsigned char intxxtab[32]; }; -extern __TLS struct mhpdbg mhpdbg; +extern struct mhpdbg mhpdbg; #ifdef MHP_PRIVATE @@ -94,7 +87,7 @@ extern __TLS struct mhpdbg mhpdbg; #define DBG_ARG(val) ((val) >> 8) #define SRSIZE MHP_BUFFERSIZE #define MYPORT 3456 -#define IBUFS 0x100 +#define IBUFS 100 #define MAXARG 16 #define MAXBP 64 @@ -138,7 +131,7 @@ struct mhpdbgc { int stopped; int want_to_stop; - unsigned currcode; + enum dosdebug_event currcode; int trapcmd; int trapip; /* ip that we were on when we started the "tracei" command */ int bpload; diff --git a/src/include/mouse.h b/src/include/mouse.h index e263bb2..07a2beb 100644 --- a/src/include/mouse.h +++ b/src/include/mouse.h @@ -5,8 +5,6 @@ #define MOUSE_H #include -#include -#include "cpu.h" #define MOUSE_BASE_VERSION 0x0700 /* minimum driver version 7.00 */ #define MOUSE_EMU_VERSION 0x0005 /* my driver version 0.05 */ @@ -38,10 +36,9 @@ enum { MOUSE_NONE = -1, #define DELTA_LEFTBUP 4 /* released */ #define DELTA_RIGHTBDOWN 8 #define DELTA_RIGHTBUP 16 -#define DELTA_MIDDLEBDOWN 32 -#define DELTA_MIDDLEBUP 64 +#define DELTA_MIDDLEBDOWN 32 +#define DELTA_MIDDLEBUP 64 #define DELTA_WHEEL 128 -#define DELTA_ABSOLUTE 256 #define HEIGHT 16 #define PLANES 4 @@ -54,19 +51,18 @@ typedef struct { int type; int dev_type; int flags; - bool intdrv; + boolean intdrv; /* whether we use the native DOS cursor, or the system cursor (X, GPM) */ - bool native_cursor; - bool emulate3buttons; - bool has3buttons; - bool cleardtr; + boolean native_cursor; + boolean emulate3buttons; + boolean has3buttons; + boolean cleardtr; int baudRate; int sampleRate; int lastButtons; int chordMiddle; int init_speed_x, init_speed_y; int ignorevesa; - int ignore_speed; struct termios *oldset; } mouse_t; @@ -74,7 +70,7 @@ typedef struct { /* this entire structure gets saved on a driver state save */ /* therefore we try to keep it small where appropriate */ struct mouse_struct { - bool enabled; + boolean enabled; unsigned char lbutton, mbutton, rbutton; int lpcount, lrcount, mpcount, mrcount, rpcount, rrcount; int16_t wmcount; @@ -85,7 +81,7 @@ struct mouse_struct { int wmx, wmy; /* TRUE if we're in a graphics mode */ - bool gfx_cursor; + boolean gfx_cursor; unsigned char xshift, yshift; @@ -129,7 +125,7 @@ struct mouse_struct { unsigned short mask; /* true if mouse has three buttons (third might be emulated) */ - bool threebuttons; + boolean threebuttons; int display_page; @@ -139,7 +135,7 @@ struct mouse_struct { int win31_mode; struct { - bool state; + boolean state; unsigned short pkg; unsigned short cs, ip; } ps2; @@ -164,7 +160,7 @@ void mouse_client_reset(void); extern struct mouse_client Mouse_raw; #include "keyboard/keyboard.h" -void mouse_keyboard(bool make, t_keysym key); +void mouse_keyboard(Boolean make, t_keysym key); extern void mouse_priv_init(void); extern void dosemu_mouse_init(void); @@ -195,10 +191,7 @@ struct mouse_drv { }; void register_mouse_driver(struct mouse_drv *mouse); -void register_mouse_driver_buffered(struct mouse_drv *mouse, - void (*callback)(void *)); void mousedrv_set_udata(const char *name, void *udata); -int mousedrv_process_fifo(const char *name); void mouse_move_button(int num, int press, int from); void mouse_move_buttons(int lbutton, int mbutton, int rbutton, int from); diff --git a/src/include/msdoshlp.h b/src/include/msdoshlp.h deleted file mode 100644 index c5b3768..0000000 --- a/src/include/msdoshlp.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include "../dosext/dpmi/msdoshlp.h" diff --git a/src/include/ne2000.h b/src/include/ne2000.h index a83caf1..15fae4b 100644 --- a/src/include/ne2000.h +++ b/src/include/ne2000.h @@ -1,5 +1,6 @@ +void ne2000_priv_init(void); void ne2000_init(void); void ne2000_reset(void); void ne2000_done(void); diff --git a/src/include/pci.h b/src/include/pci.h index 0c44722..5d6fdc2 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -91,7 +91,6 @@ struct pci_funcs { void pci_bios(void); int pcibios_init(void); pciRec *pcibios_find_class(unsigned long cls, int num); -pciRec *pcibios_find_primary_vga(void); pciRec *pcibios_find_bdf(unsigned short bdf); struct pci_funcs *pci_check_conf(void); diff --git a/src/include/pgalloc.h b/src/include/pgalloc.h deleted file mode 100644 index e312aeb..0000000 --- a/src/include/pgalloc.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef PGALLOC_H -#define PGALLOC_H - -void *pgainit(unsigned npages); -void pgadone(void *pool); -void pgareset(void *pool); -int pgaalloc(void *pool, unsigned npages, unsigned id); -void pgafree(void *pool, unsigned page); -int pgaresize(void *pool, unsigned page, unsigned oldpages, unsigned newpages); -int pgaavail_largest(void *pool); -struct pgrm { - int id; - int pgoff; -}; -struct pgrm pgarmap(void *pool, unsigned page); - -#endif diff --git a/src/include/pic.h b/src/include/pic.h index 5dc3b03..71e785c 100644 --- a/src/include/pic.h +++ b/src/include/pic.h @@ -1,17 +1,107 @@ #ifndef PIC_H #define PIC_H -#include "types.h" +/* Priority Interrupt Controller Emulation + Copyright (C) 1994, J. Lawrence Stephan jlarry@delanet.com -Bit8u pic0_get_base(void); -Bit8u pic1_get_base(void); -unsigned pic_get_isr(void); + This software is distributed under the terms of the GNU General Public + License, there are NO WARRANTIES, expressed or implied. Use at your own + risk. Use of this software as a part of any product is permitted only + if that product is also distributed under the terms of the GNU General + Public License. + + + + Definitions for 8259A programmable Interrupt Controller Emulation + + + IRQ priority levels. These are in order of priority, lowest number has + highest priority. Levels 16 - 30 are available for use, but currently + have no fixed assignment. They are extras for the convenience of dosemu. + 31 is tentatively reserved for a watchdog timer (stall alarm). + + IRQ2 does not exist. A PCs IRQ2 line is actually connected to IRQ9. The + bios for IRQ9 does an int1a, then sends an EOI to the second PIC. ( This + is simulated in the PIC code if IRQ9 points to the bios segment.) For + this reason there is no PIC_IRQ2. + +*/ + +/* Values from 16 - 31 are available for assignment if not already + * assigned below. They can be used to activate dos interrupts not + * associated to the hardware pic controllers, or simply to activate + * other dosemu code. This is best used to initiate non-signal dosemu + * code from within a signal handler. + */ + + +#include "types.h" +#define NEVER 0x8000000000000000ULL +#define PIC_NMI 0 /* non-maskable interrupt 0x02 */ +#define PIC_IRQ0 1 /* timer - usually int 0x08 */ +#define PIC_IRQ1 2 /* keyboard - usually int 0x09 */ +#define PIC_IRQ8 3 /* real-time clock " int 0x70 */ +#define PIC_IRQ9 4 /* int 0x71 revectors to 0x0a */ +#define PIC_IRQ10 5 /* usually int 0x72 */ +#define PIC_IRQ11 6 /* usually int 0x73 */ +#define PIC_IRQ12 7 /* PS/2 mouse,usually int 0x74 */ +#define PIC_IRQ13 8 /* usually int 0x75 */ +#define PIC_IRQ14 9 /* disk usually int 0x76 */ +#define PIC_IRQ15 10 /* usually int 0x77 */ +#define PIC_IRQ3 11 /* COM 2 usually int 0x0b */ +#define PIC_IRQ4 12 /* COM 1 usually int 0x0c */ +#define PIC_IRQ5 13 /* LPT 2 usually int 0x0d */ +#define PIC_IRQ6 14 /* floppy usually int 0x0e */ +#define PIC_IRQ7 15 /* LPT 1 usually int 0x0f */ +#define PIC_NET 16 /* packet receive check - no dos equivalent */ +#define PIC_IPX 17 /* IPX Signal */ +#define PIC_IPX_AES 18 /* IPX AES Signal */ + +#define PIC_IMOUSE PIC_IRQ12 /* internal mouse driver */ +extern unsigned long pic_irq_list[16]; +extern hitimer_t pic_dos_time; /* dos time of last interrupt,1193047/sec.*/ +extern hitimer_t pic_sys_time; /* system time set by pic_watch */ +extern hitimer_t pic_itime[33]; + +/* IRQ definitions. Each entry specifies the emulator routine to call, and + the dos interrupt vector to use. pic_iinfo.func is set by pic_seti(), + as are the interrupt vectors for all but [1] through [15], which may be + changed by the ICW2 command from dos. (Some dos extenders do this.) */ + +struct lvldef { + int (*func)(int); + void (*callback)(void); + int ivec; +}; + +/* function definitions - level refers to irq priority level defined above */ +/* port = 0 or 1 value = 0 - 0xff level = 0 - 31 ivec = 0 - 0xff */ + +void write_pic0(ioport_t port, Bit8u value); /* write to PIC 0 */ +void write_pic1(ioport_t port, Bit8u value); /* write to PIC 1 */ +Bit8u read_pic0(ioport_t port); /* read from PIC 0 */ +Bit8u read_pic1(ioport_t port); /* read from PIC 1 */ +void pic_seti(unsigned int, int (*)(int), unsigned int, void (*)(void)); /* set function and interrupt vector */ -void pic_request(int inum); /* interrupt trigger */ +void run_irqs(void); /* run requested irqs */ +#define pic_run() run_irqs() /* the right way to call run_irqs */ + +#define PIC_REQ_NOP 0 +#define PIC_REQ_OK 1 +#define PIC_REQ_LOST (-2) +#define PIC_REQ_PEND (-1) +int pic_request(int inum); /* interrupt trigger */ void pic_untrigger(int inum); /* interrupt untrigger */ +void pic_watch(hitimer_u *s_time); /* interrupt pending watchdog timer */ int pic_pending(void); /* inform caller if interrupt is pending */ int pic_irq_active(int num); -int pic_get_inum(void); +int pic_irq_masked(int num); +void pic_sched(int ilevel, int interval); /* schedule an interrupt */ +/* The following are too simple to be anything but in-line */ + +#define pic_set_mask pic_imr=(pic0_imr|pic1_imr|pic_iflag) + +int CAN_SLEEP(void); extern void pic_reset(void); extern void pic_init(void); diff --git a/src/include/pktdrvr.h b/src/include/pktdrvr.h index 6457253..122e439 100644 --- a/src/include/pktdrvr.h +++ b/src/include/pktdrvr.h @@ -14,7 +14,6 @@ enum { VNET_TYPE_NONE, VNET_TYPE_AUTO, - VNET_TYPE_SOCK, VNET_TYPE_ETH, VNET_TYPE_TAP, VNET_TYPE_SLIRP, @@ -76,16 +75,17 @@ struct pkt_param { /* return structure for GET_STATS */ struct pkt_statistics { - uint32_t packets_in; /* Totals across all handles */ - uint32_t packets_out; - uint32_t bytes_in; /* Including MAC headers */ - uint32_t bytes_out; - uint32_t errors_in; /* Totals across all error types */ - uint32_t errors_out; - uint32_t packets_lost; /* No buffer from receiver(), card */ + unsigned long packets_in; /* Totals across all handles */ + unsigned long packets_out; + unsigned long bytes_in; /* Including MAC headers */ + unsigned long bytes_out; + unsigned long errors_in; /* Totals across all error types */ + unsigned long errors_out; + unsigned long packets_lost; /* No buffer from receiver(), card */ /* out of resources, etc. */ }; +extern void pkt_priv_init (void); extern void pkt_init (void); extern void pkt_reset (void); extern void pkt_term (void); @@ -98,8 +98,6 @@ struct pkt_ops { int (*get_MTU)(void); ssize_t (*pkt_read)(int fd, void *buf, size_t count); ssize_t (*pkt_write)(int fd, const void *buf, size_t count); -#define PFLG_ASYNC 1 - unsigned flags; }; extern int pkt_register_backend(struct pkt_ops *o); diff --git a/src/include/port.h b/src/include/port.h index 1181a76..4a168b3 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -6,9 +6,6 @@ #ifndef _PORT_H #define _PORT_H -#ifdef HAVE_SYS_IO_H -#include -#endif #include "types.h" #include "priv.h" @@ -17,67 +14,80 @@ #define IO_WRITE 2 #define IO_RDWR (IO_READ | IO_WRITE) + +/* + * number of IRQ lines supported. In an ISA PC there are two + * PIC chips cascaded together. each has 8 IRQ lines, so there + * should be 16 IRQ's total + */ +#define EMU_MAX_IRQS 16 + +#define EMU_NO_IRQ 0xffff + /* Hey, stranger, there is one too many of us in this town! */ typedef struct { - Bit8u (* read_portb)(ioport_t port, void *arg); - void (* write_portb)(ioport_t port, Bit8u byte, void *arg); - Bit16u (* read_portw)(ioport_t port, void *arg); - void (* write_portw)(ioport_t port, Bit16u word, void *arg); - Bit32u (* read_portd)(ioport_t port, void *arg); - void (* write_portd)(ioport_t port, Bit32u word, void *arg); - const char *handler_name; + Bit8u (* read_portb)(ioport_t port); + void (* write_portb)(ioport_t port, Bit8u byte); + Bit16u (* read_portw)(ioport_t port); + void (* write_portw)(ioport_t port, Bit16u word); + Bit32u (* read_portd)(ioport_t port); + void (* write_portd)(ioport_t port, Bit32u word); + const char *handler_name; ioport_t start_addr; ioport_t end_addr; - void *arg; -} emu_iodev_t, _port_handler; + int irq, fd; +} emu_iodev_t; + +typedef struct { + Bit8u (*read_portb) (ioport_t port_addr); + void (*write_portb) (ioport_t port_addr, Bit8u byte); + Bit16u (*read_portw) (ioport_t port_addr); + void (*write_portw) (ioport_t port_addr, Bit16u word); + Bit32u (*read_portd) (ioport_t port_addr); + void (*write_portd) (ioport_t port_addr, Bit32u dword); + const char *handler_name; + int irq, fd; +} _port_handler; extern int in_crit_section; static __inline__ void port_real_outb(ioport_t port, Bit8u value) { -#ifdef HAVE_SYS_IO_H - outb(value, port); -#endif + __asm__ __volatile__ ("outb %0,%1" + ::"a" ((Bit8u) value), "d"((Bit16u) port)); } static __inline__ Bit8u port_real_inb(ioport_t port) { - Bit8u _v = 0; -#ifdef HAVE_SYS_IO_H - _v = inb(port); -#endif + Bit8u _v; + __asm__ __volatile__ ("inb %1,%0" + :"=a" (_v):"d"((Bit16u) port)); return _v; } static __inline__ void port_real_outw(ioport_t port, Bit16u value) { -#ifdef HAVE_SYS_IO_H - outw(value, port); -#endif + __asm__ __volatile__ ("outw %0,%1" :: "a" ((Bit16u) value), + "d" ((Bit16u) port)); } static __inline__ Bit16u port_real_inw(ioport_t port) { - Bit16u _v = 0; -#ifdef HAVE_SYS_IO_H - _v = inw(port); -#endif + Bit16u _v; + __asm__ __volatile__ ("inw %1,%0":"=a" (_v) : "d" ((Bit16u) port)); return _v; } static __inline__ void port_real_outd(ioport_t port, Bit32u value) { -#ifdef HAVE_SYS_IO_H - outl(value, port); -#endif + __asm__ __volatile__ ("outl %0,%1" : : "a" (value), + "d" ((Bit16u) port)); } static __inline__ Bit32u port_real_ind(ioport_t port) { - Bit32u _v = 0; -#ifdef HAVE_SYS_IO_H - _v = inl(port); -#endif + Bit32u _v; + __asm__ __volatile__ ("inl %1,%0":"=a" (_v) : "d" ((Bit16u) port)); return _v; } @@ -117,6 +127,26 @@ extern void port_exit(void); extern unsigned char emu_io_bitmap[]; +/* avoid potential clashes with */ +#undef inb +#undef inw +#undef ind +#undef outb +#undef outw +#undef outd +#define inb port_inb +#define inw port_inw +#define ind port_ind +#define outb port_outb +#define outw port_outw +#define outd port_outd +#define safe_port_in_byte std_port_inb +#define safe_port_out_byte std_port_outb +#define port_safe_inb std_port_inb +#define port_safe_outb std_port_outb +#define port_safe_inw std_port_inw +#define port_safe_outw std_port_outw + extern int extra_port_init(void); extern void release_ports(void); @@ -154,7 +184,7 @@ extern unsigned char port_ormask[]; extern int port_init(void); extern int port_register_handler(emu_iodev_t info, int); -extern Boolean port_allow_io(ioport_t, Bit16u, int, Bit8u, Bit8u, int); +extern Boolean port_allow_io(ioport_t, Bit16u, int, Bit8u, Bit8u, int, char *); extern int set_ioperm(int start, int size, int flag); extern void init_port_traceing(void); diff --git a/src/include/priv.h b/src/include/priv.h index 14127d4..1831cdc 100644 --- a/src/include/priv.h +++ b/src/include/priv.h @@ -42,6 +42,7 @@ uid_t get_orig_uid(void); /* get the uid that was present at start of dosemu */ uid_t get_orig_euid(void); /* get the euid that was present at start of dosemu */ gid_t get_orig_gid(void); /* get the gid that was present at start of dosemu */ int priv_drop(void); +int is_in_groups(gid_t gid); /* The 'priv stuff' works as follows: diff --git a/src/include/ringbuf.h b/src/include/ringbuf.h index 3be15c1..8da91bb 100644 --- a/src/include/ringbuf.h +++ b/src/include/ringbuf.h @@ -17,9 +17,6 @@ #ifndef RINGBUF_H #define RINGBUF_H -#include -#include - /* Ring buffer API */ struct rng_s { diff --git a/src/include/sequencr.h b/src/include/sequencr.h deleted file mode 100644 index ff81edb..0000000 --- a/src/include/sequencr.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SEQUENCR_H -#define SEQUENCR_H - -void *sequencer_init(void); -void sequencer_done(void *handle); -void sequencer_clear(void *handle); -struct seq_item_s; -struct seq_item_s *sequencer_add(void *handle, unsigned long long tstamp); -void *sequencer_get(void *handle); -unsigned long long sequencer_get_next(void *handle); - -void sequencer_add_tag(struct seq_item_s *i, int tag, int data); -void sequencer_free(struct seq_item_s *item); -int sequencer_find(struct seq_item_s *item, int tag); - -#endif diff --git a/src/include/serial.h b/src/include/serial.h index a999c33..93c9834 100644 --- a/src/include/serial.h +++ b/src/include/serial.h @@ -25,19 +25,12 @@ #ifndef SERIAL_H #define SERIAL_H -#include - #define MAX_SER 16 #define NUM_COMS 4 typedef struct { /* MAIN VARIABLES */ char *dev; /* String to hold path to device file */ - char *exec; /* cmd to execute */ - char *pts; /* pts name */ - char *wrfile; - boolean ro; - int nullmm; int real_comport; /* The actual COMx port number. 0 for invalid */ ioport_t base_port; /* Base port address handled by device */ ioport_t end_port; /* Base port address handled by device */ @@ -52,7 +45,7 @@ typedef struct { ioport_t dmx_port; Bit8u dmx_mask; int dmx_shift; - unsigned int dmx_val:1; + int dmx_val:1; } serial_t; enum { SER_CUSTOM_NONE, SER_CUSTOM_PCCOM }; diff --git a/src/include/shlock.h b/src/include/shlock.h deleted file mode 100644 index b423260..0000000 --- a/src/include/shlock.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef SHLOCK_H -#define SHLOCK_H - -void *shlock_open(const char *dir, const char *name, int excl, int block); -int shlock_close(void *handle); - -#endif diff --git a/src/include/sig.h b/src/include/sig.h index 9a5feeb..966cdeb 100644 --- a/src/include/sig.h +++ b/src/include/sig.h @@ -39,130 +39,30 @@ static inline int dosemu_arch_prctl(int code, void *addr) } #endif +#if defined(__linux__) +/* replace sigaltstack() to avoid musl bugs */ +static inline int dosemu_sigaltstack(const stack_t *ss, stack_t *oss) +{ + return syscall(SYS_sigaltstack, ss, oss); +} +#else +static inline int dosemu_sigaltstack(const stack_t *ss, stack_t *oss) +{ + return sigaltstack(ss, oss); +} +#endif + extern void add_thread_callback(void (*cb)(void *), void *arg, const char *name); extern void SIG_init(void); extern void SIG_close(void); -/* signals for Linux's process control of consoles - Note: on macOS, SIGRTMIN doesn't exist, but neither do Linux consoles, so - we can just use SIGUSR1 then for SIG_THREAD_NOTIFY - */ -#ifdef SIGRTMIN +/* signals for Linux's process control of consoles */ #define SIG_RELEASE SIGUSR1 #define SIG_ACQUIRE SIGUSR2 #define SIG_THREAD_NOTIFY (SIGRTMIN + 0) -#else -#define SIG_THREAD_NOTIFY SIGUSR1 -#endif typedef mcontext_t sigcontext_t; -#if defined(__FreeBSD__) -#ifdef __x86_64__ -#define _scp_eax DWORD_(scp->mc_rax) -#define _scp_ebx DWORD_(scp->mc_rbx) -#define _scp_ecx DWORD_(scp->mc_rcx) -#define _scp_edx DWORD_(scp->mc_rdx) -#define _scp_ebp DWORD_(scp->mc_rbp) -#define _scp_esp DWORD_(scp->mc_rsp) -#define _scp_esi DWORD_(scp->mc_rsi) -#define _scp_edi DWORD_(scp->mc_rdi) -#define _scp_eip DWORD_(scp->mc_rip) -#define _scp_eflags (*(unsigned *)&scp->mc_rflags) -#define _scp_eflags_ (*(const unsigned *)&scp->mc_rflags) -#define _scp_cr2 scp->mc_addr -#define _scp_rip scp->mc_rip -#define _scp_rsp scp->mc_rsp -#define PRI_RG PRIx64 -#else -#define _scp_eax scp->mc_eax -#define _scp_ebx scp->mc_ebx -#define _scp_ecx scp->mc_ecx -#define _scp_edx scp->mc_edx -#define _scp_ebp scp->mc_ebp -#define _scp_esp scp->mc_esp -#define _scp_esi scp->mc_esi -#define _scp_edi scp->mc_edi -#define _scp_eip scp->mc_eip -#define _scp_eflags scp->mc_eflags -#define _scp_eflags_ scp->mc_eflags -#define _scp_cr2 scp->mc_addr -#define PRI_RG PRIx32 -#endif -#define _scp_cs (*(unsigned *)&scp->mc_cs) -#define _scp_ds (*(unsigned *)&scp->mc_ds) -#define _scp_es (*(unsigned *)&scp->mc_es) -#define _scp_ds_ (*(const unsigned *)&scp->mc_ds) -#define _scp_es_ (*(const unsigned *)&scp->mc_es) -#define _scp_fs (*(unsigned *)&scp->mc_fs) -#define _scp_gs (*(unsigned *)&scp->mc_gs) -#define _scp_ss (*(unsigned *)&scp->mc_ss) -#define _scp_trapno scp->mc_trapno -#define _scp_err (*(unsigned *)&scp->mc_err) -#define _scp_fpstate scp->mc_fpstate -#elif defined(__APPLE__) -#define _scp_eax DWORD_((*scp)->__ss.__rax) -#define _scp_edx DWORD_((*scp)->__ss.__rdx) -#define _scp_cs ((*scp)->__ss.__cs) -#define _scp_eflags ((*scp)->__ss.__rflags) -#define _scp_rip ((*scp)->__ss.__rip) -#define _scp_rsp ((*scp)->__ss.__rsp) -#define _scp_cr2 ((*scp)->__es.__faultvaddr) -#define _scp_trapno ((*scp)->__es.__trapno) -#define _scp_err ((*scp)->__es.__err) -#define PRI_RG PRIx64 -#elif defined(__linux__) -#define _scp_fpstate (scp->fpregs) -#ifdef __x86_64__ -#define _scp_es HI_WORD(scp->gregs[REG_TRAPNO]) -#define _scp_ds (((union g_reg *)&(scp->gregs[REG_TRAPNO]))->w[2]) -#define _scp_rip (scp->gregs[REG_RIP]) -#define _scp_rsp (scp->gregs[REG_RSP]) -#define _scp_edi DWORD_(scp->gregs[REG_RDI]) -#define _scp_esi DWORD_(scp->gregs[REG_RSI]) -#define _scp_ebp DWORD_(scp->gregs[REG_RBP]) -#define _scp_ebx DWORD_(scp->gregs[REG_RBX]) -#define _scp_edx DWORD_(scp->gregs[REG_RDX]) -#define _scp_ecx DWORD_(scp->gregs[REG_RCX]) -#define _scp_eax DWORD_(scp->gregs[REG_RAX]) -#define _scp_eip DWORD_(_scp_rip) -#define _scp_esp DWORD_(_scp_rsp) -#define _scp_err LO_WORD(scp->gregs[REG_ERR]) -#define _scp_trapno LO_WORD(scp->gregs[REG_TRAPNO]) -#define _scp_cs (((union g_reg *)&scp->gregs[REG_CSGSFS])->w[0]) -#define _scp_gs (((union g_reg *)&scp->gregs[REG_CSGSFS])->w[1]) -#define _scp_fs (((union g_reg *)&scp->gregs[REG_CSGSFS])->w[2]) -#define _scp_ss (((union g_reg *)&scp->gregs[REG_CSGSFS])->w[3]) -#define _scp_eflags LO_WORD(scp->gregs[REG_EFL]) -#define _scp_cr2 (scp->gregs[REG_CR2]) -#define PRI_RG "llx" -#else -#define _scp_es (scp->gregs[REG_ES]) -#define _scp_ds (scp->gregs[REG_DS]) -#define _scp_edi (scp->gregs[REG_EDI]) -#define _scp_esi (scp->gregs[REG_ESI]) -#define _scp_ebp (scp->gregs[REG_EBP]) -#define _scp_esp (scp->gregs[REG_ESP]) -#define _scp_ebx (scp->gregs[REG_EBX]) -#define _scp_edx (scp->gregs[REG_EDX]) -#define _scp_ecx (scp->gregs[REG_ECX]) -#define _scp_eax (scp->gregs[REG_EAX]) -#define _scp_eip (scp->gregs[REG_EIP]) -#define _scp_cs (scp->gregs[REG_CS]) -#define _scp_gs (scp->gregs[REG_GS]) -#define _scp_fs (scp->gregs[REG_FS]) -#define _scp_ss (scp->gregs[REG_SS]) -#define _scp_err (scp->gregs[REG_ERR]) -#define _scp_trapno (scp->gregs[REG_TRAPNO]) -#define _scp_eflags (scp->gregs[REG_EFL]) -#define _scp_cr2 (((union dword *)&scp->cr2)->d) -#define PRI_RG PRIx32 -/* some compat */ -#define _scp_rip _scp_eip -#define _scp_rsp _scp_esp -#endif -#endif // __linux__ - extern void SIGNAL_save( void (*signal_call)(void *), void *arg, size_t size, const char *name ); extern void handle_signals(void); @@ -170,60 +70,27 @@ extern void do_periodic_stuff(void); extern void sig_ctx_prepare(int tid, void *arg, void *arg2); extern void sig_ctx_restore(int tid, void *arg, void *arg2); -extern int sigchld_register_handler(pid_t pid, void (*handler)(void*), - void *arg); +extern int sigchld_register_handler(pid_t pid, void (*handler)(void)); extern int sigchld_enable_cleanup(pid_t pid); extern int sigchld_enable_handler(pid_t pid, int on); extern int sigalrm_register_handler(void (*handler)(void)); -extern void registersig(int sig, void (*handler)(siginfo_t *)); +extern void registersig(int sig, void (*handler)(sigcontext_t *, + siginfo_t *)); extern void registersig_std(int sig, void (*handler)(void *)); +extern void init_handler(sigcontext_t *scp, unsigned long uc_flags); extern void deinit_handler(sigcontext_t *scp, unsigned long *uc_flags); -void signal_block_async_nosig(sigset_t *old_mask); -void signal_unblock_fatal_sigs(void); -void signal_unblock_async_sigs(void); -void signal_restore_async_sigs(void); -void leavedos_sig(int sig); +extern void dosemu_fault(int, siginfo_t *, void *); +extern void signal_switch_to_dosemu(void); +extern void signal_switch_to_dpmi(void); +extern void signal_return_to_dosemu(void); +extern void signal_return_to_dpmi(void); +extern void signal_unblock_async_sigs(void); +extern void signal_restore_async_sigs(void); +extern void signal_set_altstack(int on); +extern void print_exception_info(sigcontext_t *scp); +extern void signal_block_async_nosig(sigset_t *old_mask); extern pthread_t dosemu_pthread_self; -extern sigset_t q_mask; -extern sigset_t nonfatal_q_mask; -extern int sig_threads_wa; - -#ifdef DNATIVE -void signal_switch_to_dosemu(void); -void signal_switch_to_dpmi(void); -void signal_return_to_dosemu(void); -void signal_return_to_dpmi(void); -void signal_set_altstack(int on); -void signative_init(void); -void signative_pre_init(void); -void signative_sigbreak(void *uc); -void signative_start(void); -void signative_stop(void); -void unsetsig(int sig); -#else -static inline void signal_switch_to_dosemu(void) {} -static inline void signal_switch_to_dpmi(void) {} -static inline void signal_return_to_dosemu(void) {} -static inline void signal_return_to_dpmi(void) {} -static inline void signal_set_altstack(int on) {} -static inline void signative_init(void) {} -static inline void signative_pre_init(void) {} -static inline void signative_sigbreak(void *uc) {} -static inline void signative_start(void) {} -static inline void signative_stop(void) {} -static inline void unsetsig(int sig) {} -#endif - -/* On glibc SIGRTMAX is not a constant but NSIG covers rt signals. - * On bsd its all the other way around. */ -#if defined(__GLIBC__) || !defined(SIGRTMAX) -#define SIGMAX NSIG -#elif defined(__FreeBSD__) -#define SIGMAX SIGRTMAX -#else -#define SIGMAX 64 -#endif #endif diff --git a/src/include/smalloc.h b/src/include/smalloc.h index 2b80682..3014952 100644 --- a/src/include/smalloc.h +++ b/src/include/smalloc.h @@ -1,17 +1,7 @@ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * for details see file COPYING in the DOSEMU distribution */ #ifndef __SMALLOC_H @@ -43,22 +33,14 @@ void *smalloc(struct mempool *mp, size_t size); void *smalloc_fixed(struct mempool *mp, void *ptr, size_t size); int smfree(struct mempool *mp, void *ptr); void *smalloc_aligned(struct mempool *mp, size_t align, size_t size); -void *smalloc_topdown(struct mempool *mp, size_t size); -void *smalloc_aligned_topdown(struct mempool *mp, unsigned char *top, - size_t align, size_t size); void *smrealloc(struct mempool *mp, void *ptr, size_t size); -void *smrealloc_aligned(struct mempool *mp, void *ptr, int align, size_t size); int sminit(struct mempool *mp, void *start, size_t size); int sminit_com(struct mempool *mp, void *start, size_t size, int (*commit)(void *area, size_t size), int (*uncommit)(void *area, size_t size)); -int sminit_comu(struct mempool *mp, void *start, size_t size, - int (*commit)(void *area, size_t size), - int (*uncommit)(void *area, size_t size)); void smfree_all(struct mempool *mp); int smdestroy(struct mempool *mp); size_t smget_free_space(struct mempool *mp); -size_t smget_free_space_upto(struct mempool *mp, unsigned char *top); size_t smget_largest_free_area(struct mempool *mp); int smget_area_size(struct mempool *mp, void *ptr); void *smget_base_addr(struct mempool *mp); diff --git a/src/include/sound/midi.h b/src/include/sound/midi.h index 314f9be..791075b 100644 --- a/src/include/sound/midi.h +++ b/src/include/sound/midi.h @@ -57,7 +57,7 @@ struct midi_in_plugin { #endif }; -extern void midi_write(unsigned char val, enum SynthType type); +extern void midi_write(unsigned char val); extern void midi_init(void); extern void midi_done(void); extern void midi_stop(void); diff --git a/src/include/sound/oplplug.h b/src/include/sound/oplplug.h index e65a4bf..7267ab9 100644 --- a/src/include/sound/oplplug.h +++ b/src/include/sound/oplplug.h @@ -7,8 +7,7 @@ struct opl_ops { uint8_t (*PortRead)(void *impl, uint16_t port); void (*PortWrite)(void *impl, uint16_t port, uint8_t val ); void *(*Create)(int opl3_rate); - void (*Generate)(int total, int16_t output[][2], double beg, - double period); + void (*Generate)(int total, int16_t output[][2]); }; void opl_register_ops(struct opl_ops *ops); diff --git a/src/include/sound/sound.h b/src/include/sound/sound.h index 0b29dd8..c3ab4ce 100644 --- a/src/include/sound/sound.h +++ b/src/include/sound/sound.h @@ -63,7 +63,6 @@ typedef struct pcm_base_s { } pcm_base; #define PCM_CF_ENABLED 1 -#define PCM_CF_DISABLED 2 typedef #ifdef __cplusplus @@ -87,8 +86,8 @@ struct pcm_plugin_base_s { struct pcm_holder { const pcm_base *plugin; void *arg; - unsigned int opened:1; - unsigned int failed:1; + int opened:1; + int failed:1; int cfg_flags; void *priv; }; diff --git a/src/include/spscq.h b/src/include/spscq.h deleted file mode 100644 index d9c6982..0000000 --- a/src/include/spscq.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef SPSCQ_H -#define SPSCQ_H - -void *spscq_init(unsigned size); -void spscq_done(void *arg); -void *spscq_write_area(void *arg, unsigned *r_len); -void spscq_commit_write(void *arg, unsigned len); -int spscq_read(void *arg, void *buf, unsigned len); - -#endif diff --git a/src/include/timers.h b/src/include/timers.h index 0fa1a0c..2ac6e5f 100644 --- a/src/include/timers.h +++ b/src/include/timers.h @@ -10,8 +10,8 @@ #define TIMER_DIVISOR 6 extern void timer_tick(void); -extern Bit8u pit_inp(ioport_t, void *); -extern void pit_outp(ioport_t, Bit8u, void *); +extern Bit8u pit_inp(ioport_t); +extern void pit_outp(ioport_t, Bit8u); /* The divisor used to time faster-than-1sec activities (floppy,printer, * IPX) - see signal.c @@ -47,17 +47,11 @@ extern void pit_outp(ioport_t, Bit8u, void *); void reset_idle(int val); void alarm_idle(void); void trigger_idle(void); -void untrigger_idle(void); -void idle(int threshold1, int threshold, int threshold2, const char *who); -void idle_enable(int threshold, int threshold2, const char *who); -void idle_enable2(int threshold1, int threshold, int threshold2, +int idle(int threshold1, int threshold, int threshold2, const char *who); +int idle_enable(int threshold1, int threshold, int threshold2, const char *who); void dosemu_sleep(void); void cpu_idle(void); -int timer_get_vpend(int timer); -void pit_late_init(void); - -int CAN_SLEEP(void); /* --------------------------------------------------------------------- */ /* New unified timing macros with/without Pentium rdtsc - AV 8/97 */ @@ -97,24 +91,23 @@ static __inline__ hitimer_t _mul64x32_(hitimer_t v, unsigned long f) /* --------------------------------------------------------------------- */ +extern void update_cputime_TSCBase(void); extern hitimer_u ZeroTimeBase; extern hitimer_t t_vretrace; -static inline hitimer_t GETTSC(void) -{ +static inline hitimer_t GETTSC(void) { hitimer_t d; -#if defined(__x86_64__) +#ifdef __x86_64__ unsigned int lo, hi; asm volatile("rdtsc" : "=a" (lo), "=d" (hi)); d = lo | ((unsigned long)hi << 32); -#elif defined(__i386__) - __asm__ __volatile__ ("rdtsc" : "=A" (d)); #else - d = 0; + __asm__ __volatile__ ("rdtsc" : "=A" (d)); #endif return d; } +#define CPUtoUS() _mul64x32_(GETTSC(), config.cpu_spd) #define TSCtoUS(t) _mul64x32_(t, config.cpu_spd) /* 1 us granularity */ @@ -127,6 +120,7 @@ extern hitimer_t GETtickTIME(int sc); int stop_cputime (int); int restart_cputime (int); extern int cpu_time_stop; /* for dosdebug */ +int bogospeed(unsigned long *spus, unsigned long *sptick); void uncache_time(void); void freeze_dosemu_manual(void); @@ -134,12 +128,12 @@ void freeze_dosemu(void); void unfreeze_dosemu(void); extern int dosemu_frozen; extern int dosemu_user_froze; -extern hitimer_t pic_sys_time; /* --------------------------------------------------------------------- */ -extern Bit8u pit_control_inp(ioport_t, void *); -extern void pit_control_outp(ioport_t port, Bit8u val, void *); +extern Bit8u pit_control_inp(ioport_t); +extern void pit_control_outp(ioport_t port, Bit8u val); +extern void initialize_timers(void); extern void get_time_init(void); extern void cputime_late_init(void); extern void do_sound(Bit16u period); diff --git a/src/include/translate/translate.h b/src/include/translate/translate.h index 04ae759..79077f4 100644 --- a/src/include/translate/translate.h +++ b/src/include/translate/translate.h @@ -4,6 +4,8 @@ #include #include +#include "init.h" + #define HAVE_UNICODE_TRANSLATION 1 typedef unsigned int t_unicode; diff --git a/src/include/utilities.h b/src/include/utilities.h index 562a63a..f1512b1 100644 --- a/src/include/utilities.h +++ b/src/include/utilities.h @@ -2,42 +2,58 @@ #define UTILITIES_H #include -#include #include "dosemu_debug.h" +struct cmd_db { + char cmdname[12]; + void (*cmdproc)(int, char *[]); +}; + extern char *logptr, *logbuf; extern int logbuf_size, logfile_limit; int argparse(char *s, char *argvx[], int maxarg); +typedef void cmdprintf_func(const char *fmt, ...); +void call_cmd(const char *cmd, int maxargs, const struct cmd_db *cmdtab, + cmdprintf_func *printf); void sigalarm_onoff(int on); char *strprintable(char *s); char *chrprintable(char c); int is_printable(const char *s); -int open_proc_scan(const char *name); +void open_proc_scan(const char *name); void close_proc_scan(void); char *get_proc_string_by_key(const char *key); void advance_proc_bufferptr(void); void reset_proc_bufferptr(void); int get_proc_intvalue_by_key(const char *key); +int integer_sqrt(int x); int exists_dir(const char *name); int exists_file(const char *name); void subst_file_ext(char *ptr); char *strcatdup(char *s1, char *s2); -int tempname(char *tmpl, size_t x_suffix_len); char *assemble_path(const char *dir, const char *file); char *expand_path(const char *dir); char *concat_dir(const char *s1, const char *s2); -char *mkdir_under(const char *basedir, const char *dir); +const char *mkdir_under(const char *basedir, const char *dir); char *get_path_in_HOME(const char *path); -char *get_dosemu_local_home(void); +const char *get_dosemu_local_home(void); char *readlink_malloc (const char *filename); void dosemu_error(const char *fmt, ...) FORMAT(printf, 1, 2); void *load_plugin(const char *plugin_name); void close_plugin(void *handle); -char *prefix(const char *suffix); -int mktmp_in(char *dir_tmpl, const char *fname, mode_t mode); +/* returns y = sqrt(x), for y*y beeing a power of 2 below x + */ +static __inline__ int power_of_2_sqrt(int val) +{ + register int res; + __asm__ __volatile__(" \ + bsrl %2,%0\n \ + " : "=r" (res) : "0" ((int)-1), "r" (val) ); + if (res <0) return 0; + return 1 << (res >> 1); +} #define _min(x,y) ({ \ typeof(x) _x = (x); \ @@ -79,7 +95,7 @@ int popen2(const char *cmdline, struct popen2 *childinfo); int popen2_custom(const char *cmdline, struct popen2 *childinfo); int pclose2(struct popen2 *childinfo); -const char *findprog(const char *prog, const char *path); +char *findprog(char *prog, const char *path); #define DLSYM_ASSERT(h, s) ({ \ void *__sym = dlsym(h, s); \ @@ -99,9 +115,8 @@ struct string_store { }; int replace_string(struct string_store *store, const char *old, char *str); -#ifdef HAVE_FOPENCOOKIE + FILE *fstream_tee(FILE *orig, FILE *copy); -#endif #define cond_wait(c, m) { \ pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock, m); \ @@ -109,42 +124,4 @@ FILE *fstream_tee(FILE *orig, FILE *copy); pthread_cleanup_pop(0); \ } -typedef sem_t *pshared_sem_t; -static inline int pshared_sem_post(pshared_sem_t sem) -{ - return sem_post(sem); -} -static inline int pshared_sem_wait(pshared_sem_t sem) -{ - return sem_wait(sem); -} - -/* macOS doesn't support sem_init(), so use Mach semaphores instead */ -#ifdef __APPLE__ -#include -#include -#include -#undef PAGE_SIZE -#define PAGE_SIZE 4096 -#define sem_t semaphore_t -#define sem_init(x,y,z) semaphore_create(mach_task_self(), (x), SYNC_POLICY_FIFO, (z)) -#define sem_post(x) semaphore_signal(*(x)) -#define sem_wait(x) do { if (semaphore_wait(*(x)) == KERN_ABORTED) pthread_exit(NULL); } while(0) -#define sem_destroy(x) semaphore_destroy(mach_task_self(), *(x)) -#endif - -pid_t run_external_command(const char *path, int argc, - const char **argv, - int use_stdin, int close_from, int pty_fd); - -#ifdef HAVE_OPTRESET -/* needs to set both to 1, no idea why optreset alone isn't enough! */ -#define GETOPT_RESET() \ - optreset = 1; \ - optind = 1 -#else -#define GETOPT_RESET() \ - optind = 0 -#endif - #endif /* UTILITIES_H */ diff --git a/src/include/vgaemu.h b/src/include/vgaemu.h index 8189017..79a72eb 100644 --- a/src/include/vgaemu.h +++ b/src/include/vgaemu.h @@ -49,8 +49,6 @@ #if !defined __VGAEMU_H #define __VGAEMU_H -#include -#include "cpu.h" /* * Definition of video mode classes. @@ -243,12 +241,6 @@ typedef struct { #define VGAEMU_MAP_BANK_MODE 0 #define VGAEMU_MAP_LFB_MODE 1 -/* Physical LFB base. With KVM this is actually used; without KVM this is - just a cookie, reported by the VESA VBE interface, that can be mapped using DPMI - int31/ax=0x0800 */ -#define VGAEMU_PHYS_LFB_BASE 0xe0000000 - -#define VGA_EMU_INST_EMU_COUNT 150 typedef struct { unsigned base_page; /* base address (in 4k) of mapping */ @@ -270,13 +262,12 @@ typedef struct { unsigned bank_len; /* banked length in bytes */ unsigned graph_base; /* graphics base, normally 0xa0000 */ unsigned graph_size; /* graphics size, normally 0x20000 */ - dosaddr_t lfb_base; /* base address for lfb, 0 if no lfb */ + unsigned char *lfb_base; /* base address for lfb, NULL if no lfb */ unsigned lfb_base_page; /* lfb base page, 0 -> no lfb support */ vga_mapping_type map[VGAEMU_MAX_MAPPINGS]; /* all the mappings */ unsigned bank_pages; /* size of a bank in pages */ unsigned bank; /* selected bank */ unsigned char *dirty_map; /* 1 == dirty */ - unsigned char *dirty_bitmap; /* filled in by KVM */ unsigned char *prot_map0, *prot_map1; /* prot flags per page */ int planes; /* 4 for PL4 and ModeX, 1 otherwise */ int plane_pages; /* pages per plane */ @@ -445,7 +436,6 @@ typedef struct { vga_gfx_type gfx; vga_misc_type misc; vga_herc_type herc; - uint8_t backup_font[256 * 32]; } vga_type; @@ -480,9 +470,11 @@ struct ColorSpaceDesc; * Functions defined in env/video/vgaemu.c. */ -int VGA_emulate_outb(ioport_t, Bit8u, void *arg); -int VGA_emulate_inb(ioport_t, void *arg); -int vga_emu_fault(dosaddr_t, unsigned, cpuctx_t *); +int VGA_emulate_outb(ioport_t, Bit8u); +int VGA_emulate_outw(ioport_t, Bit16u); +Bit8u VGA_emulate_inb(ioport_t); +Bit16u VGA_emulate_inw(ioport_t); +int vga_emu_fault(dosaddr_t, unsigned, sigcontext_t *); int vga_emu_pre_init(void); int vga_emu_init(int src_modes, struct ColorSpaceDesc *); void vga_emu_done(void); @@ -667,11 +659,13 @@ extern unsigned char vga_rom_16_alt[1]; * vbe_init() to setup the struct vgaemu_bios which holds all relevant * info about our BIOS. */ -extern char _binary_vesabios_o_bin_end[] asm("_binary_vesabios_o_bin_end"); -extern char _binary_vesabios_o_bin_start[] asm("_binary_vesabios_o_bin_start"); -extern char _binary_vesabios_pm_o_bin_end[] asm("_binary_vesabios_pm_o_bin_end"); -extern char _binary_vesabios_pm_o_bin_start[] asm("_binary_vesabios_pm_o_bin_start"); +extern void vgaemu_bios_start(void); +extern void vgaemu_bios_prod_name(void); +extern void vgaemu_bios_win_func(void); +extern void vgaemu_bios_end(void); +extern void vgaemu_bios_pm_interface(void); +extern void vgaemu_bios_pm_interface_end(void); #ifdef __cplusplus }; diff --git a/src/include/vgatext.h b/src/include/vgatext.h index 864d522..4de5324 100644 --- a/src/include/vgatext.h +++ b/src/include/vgatext.h @@ -42,6 +42,7 @@ struct bitmap_desc draw_bitmap_cursor(int x, int y, Bit8u attr, int start, struct bitmap_desc draw_bitmap_line(int x, int y, float ul, int len, Bit8u attr); void blink_cursor(void); +void reset_redraw_text_screen(void); void dirty_text_screen(void); int text_is_dirty(void); void init_text_mapper(int image_mode, int features, ColorSpaceDesc *csd); @@ -59,7 +60,7 @@ void text_unlock(void); /* for selections */ t_unicode* end_selection(void); void clear_if_in_selection(void); -void start_selection(int col, int row, int rect); +void start_selection(int col, int row); void start_extend_selection(int col, int row); void clear_selection_data(void); void extend_selection(int col, int row); diff --git a/src/include/video.h b/src/include/video.h index 45055c9..664cd70 100644 --- a/src/include/video.h +++ b/src/include/video.h @@ -1,8 +1,6 @@ #ifndef VIDEO_H #define VIDEO_H -#include - extern void gettermcap(int,int *, int *); /* if you set this to 1, then you will be able to use your MDA + monitor @@ -23,8 +21,8 @@ extern void gettermcap(int,int *, int *); * and the BIOS really can't handle more than these numbers of rows and * columns (128*255*2 < 65535) */ -#define MAX_COLUMNS 160 -#define MAX_LINES 100 +#define MAX_COLUMNS 255 +#define MAX_LINES 128 /***********************************************************************/ @@ -84,7 +82,7 @@ extern int video_mode; extern int video_combo; extern int video_initialized; -extern bool set_video_mode(int); +extern boolean set_video_mode(int); extern unsigned screen_adr(int page); /* Various defines for all common video adapters */ diff --git a/src/include/vint.h b/src/include/vint.h deleted file mode 100644 index c34b5d4..0000000 --- a/src/include/vint.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef VINT_H -#define VINT_H - -void vint_init(void); -void vint_setup(void); -int vint_is_masked(int vi_num, uint8_t *imr); -void vint_post_irq_dpmi(int vi_num, int masked); -int vint_register(void (*ack_handler)(int, int), - void (*mask_handler)(int, int), - int irq, int orig_irq, int inum); -void vint_set_tweaked(int vi_num, int on, unsigned flags); - -#endif diff --git a/src/include/virq.h b/src/include/virq.h deleted file mode 100644 index 922fe63..0000000 --- a/src/include/virq.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef VIRQ_H -#define VIRQ_H - -enum { VIRQ_MOUSE, VIRQ_PKT, VIRQ_IPX, VIRQ_IPX_AES, VIRQ_MAX }; -enum VirqHwRet { VIRQ_HWRET_DONE, VIRQ_HWRET_CONT }; -enum VirqSwRet { VIRQ_SWRET_DONE, VIRQ_SWRET_BH }; - -void virq_init(void); -void virq_reset(void); -void virq_setup(void); -void virq_raise(int virq_num); -void virq_register(int virq_num, enum VirqHwRet (*hw_handler)(void *), - enum VirqSwRet (*sw_handler)(void *), void *arg); -void virq_unregister(int virq_num); - -#endif diff --git a/src/include/vm86_compat.h b/src/include/vm86_compat.h index 152d8df..735a66d 100644 --- a/src/include/vm86_compat.h +++ b/src/include/vm86_compat.h @@ -1,7 +1,12 @@ #ifndef _VM86_COMPAT_H #define _VM86_COMPAT_H -#include +#ifdef __i386__ +#include +#else +#ifdef __linux__ +#include +#endif /* * I'm guessing at the VIF/VIP flag usage, but hope that this is how @@ -61,22 +66,22 @@ struct vm86_regs { /* * normal regs, with special meaning for the segment descriptors.. */ - unsigned ebx; - unsigned ecx; - unsigned edx; - unsigned esi; - unsigned edi; - unsigned ebp; - unsigned eax; - unsigned __null_ds; - unsigned __null_es; - unsigned __null_fs; - unsigned __null_gs; - unsigned orig_eax; - unsigned eip; + int ebx; + int ecx; + int edx; + int esi; + int edi; + int ebp; + int eax; + int __null_ds; + int __null_es; + int __null_fs; + int __null_gs; + int orig_eax; + int eip; unsigned short cs, __csh; - unsigned eflags; - unsigned esp; + int eflags; + int esp; unsigned short ss, __ssh; /* * these are specific to v86 mode: @@ -137,3 +142,5 @@ struct vm86plus_struct { #define VIP_MASK 0x00100000 /* virtual interrupt pending */ #define ID_MASK 0x00200000 #endif + +#endif diff --git a/src/include/vtmr.h b/src/include/vtmr.h deleted file mode 100644 index 8e32255..0000000 --- a/src/include/vtmr.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef VTMR_H -#define VTMR_H - -enum { VTMR_PIT, VTMR_RTC, VTMR_MAX }; - -void vtmr_init(void); -void vtmr_done(void); -void vtmr_reset(void); -void vtmr_raise(int vtmr_num); -void vtmr_latch(int vtmr_num); -void vtmr_sync(int vtmr_num); -void vtmr_register(int timer, int (*handler)(int)); -void vtmr_register_latch(int timer, int (*handler)(void)); -void vtmr_set_tweaked(int timer, int on, unsigned flags); - -int vtmr_pre_irq_dpmi(uint8_t *imr); -void vtmr_post_irq_dpmi(int masked); -int vrtc_pre_irq_dpmi(uint8_t *imr); -void vrtc_post_irq_dpmi(int masked); - -#define VTMR_IRQ 0xb -#define VTMR_INTERRUPT 0x73 - -#define VRTC_IRQ 0xe -#define VRTC_INTERRUPT 0x76 - -#endif diff --git a/src/include/xms.h b/src/include/xms.h index 3613722..89986cd 100644 --- a/src/include/xms.h +++ b/src/include/xms.h @@ -29,15 +29,32 @@ #define NEWXMS 2 #ifndef __ASSEMBLER__ +struct __attribute__ ((__packed__)) EMM { + unsigned int Length; + unsigned short SourceHandle; + unsigned int SourceOffset; + unsigned short DestHandle; + unsigned int DestOffset; +} ; + +struct Handle { + unsigned short int num; + unsigned int addr; + unsigned int size; + int valid; + int lockcount; +}; + +struct UMB { + unsigned short segment, size; + int used; +}; + void xms_init(void); -void xms_done(void); void xms_reset(void); void xms_helper(void); void xms_control(void); int xms_intdrv(void); -uint16_t xms_install_check(void); -int xms_helper_init_ext(void); -void *xms_resolve_physaddr(unsigned addr); #endif #endif /* XMS_H */ diff --git a/src/plugin/X/Makefile b/src/plugin/X/Makefile index c0b2915..a79b399 100644 --- a/src/plugin/X/Makefile +++ b/src/plugin/X/Makefile @@ -10,7 +10,7 @@ include ../plugins.mak CFILES = X.c screen.c keyb_X.c keyb_X_keycode.c X_speaker.c X_font.c GENHDRS = x_config.hh -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_X.so ALL_CFLAGS += -fPIC endif @@ -19,13 +19,13 @@ include $(REALTOPDIR)/src/Makefile.common.post ALL_CFLAGS+=$(DL_CFLAGS) -I$(srcdir)/include $(X_CFLAGS) -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_X.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(X_LIBS) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(X_LIBS) endif _x_config.h.in: $(srcdir)/configure.ac - autoheader -f + autoheader x_config.hh: _x_config.h.in configure ./configure diff --git a/src/plugin/X/X.c b/src/plugin/X/X.c index cae0c4c..b01013a 100644 --- a/src/plugin/X/X.c +++ b/src/plugin/X/X.c @@ -137,7 +137,7 @@ * 1998/12/12: Palette/font changes in text modes improved. * -- sw * - * 1999/01/05: Split X_update_screen() into two separate parts. + * 1999/01/05: Splitted X_update_screen() into two separate parts. * -- sw * * 1998/11/07: Updated Steffen's code to newest X.c : @@ -231,7 +231,6 @@ #include #include /* root@sjoerd:for mprotect*/ -#include "init.h" #include "emu.h" #include "timers.h" #include "bios.h" @@ -391,35 +390,6 @@ static int X_unmap_mode = -1; static Atom comm_atom = None; static Boolean kdos_client = FALSE; /* started by kdos */ -/* Hints used by Motif compliant window managers */ -enum { - MWM_HINTS_FUNCTIONS = (1L << 0), - - MWM_FUNC_ALL = (1L << 0), - MWM_FUNC_RESIZE = (1L << 1), - MWM_FUNC_MOVE = (1L << 2), - MWM_FUNC_MINIMIZE = (1L << 3), - MWM_FUNC_MAXIMIZE = (1L << 4), - MWM_FUNC_CLOSE = (1L << 5), - - MWM_HINTS_DECORATIONS = (1L << 1), - - MWM_DECOR_ALL = (1L << 0), - MWM_DECOR_BORDER = (1L << 1), - MWM_DECOR_RESIZEH = (1L << 2), - MWM_DECOR_TITLE = (1L << 3), - MWM_DECOR_MENU = (1L << 4), - MWM_DECOR_MINIMIZE = (1L << 5), - MWM_DECOR_MAXIMIZE = (1L << 6), -}; - -struct MWMHints { - unsigned long flags; - unsigned long functions; - unsigned long decorations; - long input_mode; - unsigned long status; -}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -459,8 +429,6 @@ static void create_ximage(void); static void destroy_ximage(void); static void put_ximage(int, int, unsigned, unsigned); static void resize_ximage(unsigned, unsigned); -static void X_set_resizable(Display *display, Window window, int on, - int x_res, int y_res); /* video mode set/modify stuff */ static int X_set_videomode(struct vid_mode_params vmp); @@ -575,20 +543,6 @@ void X_register_speaker(Display *display) #endif } -static void SetWindowMotifOptions(Display *display, Window window) -{ - Atom wm_hints = XInternAtom(display, "_MOTIF_WM_HINTS", True); - if (wm_hints != None && config.X_noclose) { - struct MWMHints hints = {0}; - - hints.flags = MWM_HINTS_FUNCTIONS; - hints.functions = (MWM_FUNC_RESIZE | MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE); - XChangeProperty(display, window, wm_hints, wm_hints, 32, - PropModeReplace, (unsigned char *)&hints, - sizeof(hints) / sizeof(long)); - } -} - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* @@ -599,7 +553,7 @@ static void SetWindowMotifOptions(Display *display, Window window) * * DANG_END_FUNCTION */ -int X_init(void) +int X_init() { XGCValues gcv; XClassHint xch; @@ -746,9 +700,6 @@ int X_init(void) XChangeWindowAttributes(display, mainwindow, CWEventMask, &attr); XChangeWindowAttributes(display, fullscreenwindow, CWEventMask, &attr); - - SetWindowMotifOptions(display, mainwindow); - attr.event_mask = ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | @@ -833,7 +784,6 @@ int X_init(void) } lock_window_size(w_x_res, w_y_res); - X_set_resizable(display, normalwindow, !config.X_noresize, w_x_res, w_y_res); /* don't map window if set */ if(getenv("DOSEMU_HIDE_WINDOW") == NULL) { if (config.X_fullscreen) { @@ -871,7 +821,7 @@ int X_init(void) * * DANG_END_FUNCTION */ -void X_close(void) +void X_close() { X_printf("X: X_close\n"); @@ -934,7 +884,7 @@ void X_close(void) /* * Collect some information about the X server. */ -void X_get_screen_info(void) +void X_get_screen_info() { XImage *xi; const char *s; @@ -1019,7 +969,7 @@ void X_get_screen_info(void) * * DANG_END_FUNCTION */ -void X_shm_init(void) +void X_shm_init() { int event_base, error_base, major_version, minor_version; Bool shared_pixmaps; @@ -1054,7 +1004,7 @@ void X_shm_init(void) * * DANG_END_FUNCTION */ -void X_shm_done(void) +void X_shm_done() { shm_ok = 0; } @@ -1171,7 +1121,7 @@ static int X_change_config(unsigned item, void *buf) case CHG_WINSIZE: case CHG_BACKGROUND_PAUSE: case GET_TITLE_APPNAME: - change_config(item, buf, grab_active, kbd_grab_active, 0); + change_config(item, buf, grab_active, kbd_grab_active); break; case CHG_FONT: @@ -1575,8 +1525,7 @@ static int __X_handle_events(XEvent *e) */ if(e->xclient.message_type == proto_atom && *e->xclient.data.l == delete_atom) { X_printf("X: got window delete message\n"); - if (config.X_noclose) - break; + /* XXX - Is it ok to call this from a SIGALRM handler? */ return -1; } @@ -1655,7 +1604,7 @@ static int __X_handle_events(XEvent *e) if (vga.mode_class == TEXT && !grab_active) { if (e->xbutton.button == Button1) start_selection(x_to_col(e->xbutton.x, w_x_res), - y_to_row(e->xbutton.y, w_y_res), 0); + y_to_row(e->xbutton.y, w_y_res)); else if (e->xbutton.button == Button3) start_extend_selection(x_to_col(e->xbutton.x, w_x_res), y_to_row(e->xbutton.y, w_y_res)); @@ -1846,7 +1795,7 @@ static void *X_handle_events(void *arg) * allocation of a shared map fails for some reason, the code still tries * to get a private map (and will likely fail). -- sw */ -void graphics_cmap_init(void) +void graphics_cmap_init() { /* Note: should really deallocate and reallocate our colours every time we switch graphic modes... --adm */ @@ -1895,7 +1844,7 @@ void graphics_cmap_init(void) /* * Create a private colormap. The colormap is *not* initialized. */ -int MakePrivateColormap(void) +int MakePrivateColormap() { int i; unsigned long pixels[256]; /* ok, cmap_colors always <= 256 */ @@ -1916,7 +1865,7 @@ int MakePrivateColormap(void) * Create a shared colormap. The colormap's features are * described with a ColorSpaceDesc object (cf. graphics_cmap_init). */ -ColorSpaceDesc MakeSharedColormap(void) +ColorSpaceDesc MakeSharedColormap() { ColorSpaceDesc csd; int i, j; @@ -1993,7 +1942,7 @@ int try_cube(unsigned long *p, c_cube *c) * Create an image. Will use shared memory, if available. * The image is used in graphics modes only. */ -void create_ximage(void) +void create_ximage() { #ifdef HAVE_MITSHM if(shm_ok) { @@ -2011,7 +1960,7 @@ void create_ximage(void) shm_ok = 0; } else { - shminfo.shmid = shmget(IPC_PRIVATE, ximage->bytes_per_line * w_y_res, IPC_CREAT | 0600); + shminfo.shmid = shmget(IPC_PRIVATE, ximage->bytes_per_line * w_y_res, IPC_CREAT | 0777); if(shminfo.shmid < 0) { X_printf("X: shmget() failed\n"); XDestroyImage(ximage); @@ -2065,7 +2014,7 @@ void create_ximage(void) /* * Destroy an image. */ -void destroy_ximage(void) +void destroy_ximage() { if(ximage == NULL) return; @@ -2110,7 +2059,7 @@ void resize_ximage(unsigned width, unsigned height) create_ximage(); } -static void X_set_resizable(Display *display, Window window, int on, +void X_set_resizable(Display *display, Window window, int on, int x_res, int y_res) { XSizeHints sh; @@ -2143,7 +2092,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res) sh.base_width = sh.width = sh.min_width = sh.max_width = wx_res; sh.base_height = sh.height = sh.min_height = sh.max_height = wy_res; - sh.flags = PSize | PBaseSize; + sh.flags = PSize | PMinSize | PMaxSize | PBaseSize; if(config.X_fixed_aspect || config.X_aspect_43) sh.flags |= PAspect; if (use_bitmap_font) { #if 0 @@ -2154,6 +2103,10 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res) sh.flags &= ~PAspect; #endif sh.flags |= PResizeInc; + sh.max_width = 32767; + sh.max_height = 32767; + sh.min_width = 0; + sh.min_height = 0; sh.width_inc = 1; sh.height_inc = 1; } @@ -2161,9 +2114,6 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res) sh.min_aspect.y = wy_res; sh.max_aspect = sh.min_aspect; XSetNormalHints(display, normalwindow, &sh); - /* Seems XSetNormalHints() resets PMinSize|PMaxSize even if not asked to! - * Update them by hands. */ - X_set_resizable(display, normalwindow, !config.X_noresize, w_x_res, w_y_res); x_fill = wx_res; y_fill = wy_res; @@ -2334,7 +2284,7 @@ int X_set_videomode(struct vid_mode_params vmp) /* * Resize the X display to the appropriate size. */ -void X_resize_text_screen(void) +void X_resize_text_screen() { if (!use_bitmap_font) { w_x_res = x_res = vga.text_width * font_width; @@ -2442,7 +2392,7 @@ static void X_vidmode(int w, int h, int *new_width, int *new_height) *new_height = nh; } -void X_redraw_text_screen(void) +void X_redraw_text_screen() { if(!is_mapped) return; redraw_text_screen(); @@ -2451,7 +2401,7 @@ void X_redraw_text_screen(void) /* * Load the mouse cursor shapes. */ -void load_cursor_shapes(void) +void load_cursor_shapes() { Colormap cmap; XColor fg, bg; @@ -2485,7 +2435,7 @@ void load_cursor_shapes(void) /* * Makes an invisible cursor (to be used when no cursor should be drawn). */ -Cursor create_invisible_cursor(void) +Cursor create_invisible_cursor() { Pixmap mask; Cursor cursor; @@ -2603,7 +2553,7 @@ void kdos_send_msg(char *buf) XSendEvent(display, parentwindow, False, 0, &e); } -void kdos_close_msg(void) +void kdos_close_msg() { char m[20] = { KDOS_CLOSE_MSG, }; kdos_send_msg(m); diff --git a/src/plugin/X/X.h b/src/plugin/X/X.h index f0ec3e8..85bb80e 100644 --- a/src/plugin/X/X.h +++ b/src/plugin/X/X.h @@ -31,6 +31,8 @@ int X_load_text_font(Display *dpy, int private_dpy, Window, const char *p, int *w, int *h); void X_close_text_display(void); int X_handle_text_expose(void); +void X_set_resizable(Display *display, Window window, int on, + int x_res, int y_res); void X_force_mouse_cursor(int yes); #ifdef __cplusplus diff --git a/src/plugin/X/X_speaker.c b/src/plugin/X/X_speaker.c index 4f68f96..3dd9fc6 100644 --- a/src/plugin/X/X_speaker.c +++ b/src/plugin/X/X_speaker.c @@ -18,7 +18,7 @@ void X_speaker_on(void *gp, unsigned ms, unsigned short period) Display *display = gp; #if 0 - /* Turn off the previous sound, I hope */ + /* Turn off the previos sound, I hope */ new_state.bell_pitch = 0; new_state.bell_duration = 0; XChangeKeyboardControl(display, KBBellDuration | KBBellPitch, &new_state); @@ -28,7 +28,7 @@ void X_speaker_on(void *gp, unsigned ms, unsigned short period) /* Make the sound I want */ new_state.bell_pitch = speaker_period_to_Hz(period); /* Prohibit a crashing X server by not allowing to go higher than - * 32767 kHz. Since the X server interprets the pitch as a short int + * 32767 kHz. Since the X server interpretes the pitch as a short int */ if (new_state.bell_pitch >= 0x8000) new_state.bell_pitch = 0x7fff; new_state.bell_duration = ms; diff --git a/src/plugin/X/configure.ac b/src/plugin/X/configure.ac index ab750ad..39af2f2 100644 --- a/src/plugin/X/configure.ac +++ b/src/plugin/X/configure.ac @@ -1,16 +1,20 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT -AC_CONFIG_HEADERS([_x_config.h]) +AC_CONFIG_HEADER([_x_config.h]) AC_CONFIG_FILES([Makefile.conf]) PKG_CHECK_MODULES([X11], [x11],, AC_MSG_ERROR([X development libraries not installed])) AC_MSG_NOTICE(Compiling with X support...) +AC_SUBST(X11_CFLAGS) +AC_SUBST(X11_LIBS) dnl Check for the MITSHM extention to speed up VGAemu PKG_CHECK_MODULES([XEXT], [xext], [ AC_DEFINE(HAVE_MITSHM,1) + AC_SUBST(XEXT_CFLAGS) + AC_SUBST(XEXT_LIBS) ], AC_MSG_NOTICE(Compiling without the MITSHM X extension)) @@ -22,6 +26,8 @@ fi if test "$enable_vidmode" = "yes"; then AC_MSG_NOTICE(Compiling with the XF86 video mode extension) AC_DEFINE(HAVE_XVIDMODE,1) + AC_SUBST(XVM_CFLAGS) + AC_SUBST(XVM_LIBS) fi dnl Check for the XKB extension to get reliable keyboard handling diff --git a/src/plugin/X/keyb_X.c b/src/plugin/X/keyb_X.c index 97a3183..c072e59 100644 --- a/src/plugin/X/keyb_X.c +++ b/src/plugin/X/keyb_X.c @@ -31,7 +31,6 @@ Since this code has been totally rewritten the pcemu license no longer applies #include #endif -#include "init.h" #include "X.h" #include "emu.h" #include "keyboard/keyb_clients.h" @@ -192,7 +191,7 @@ void X_sync_shiftstate(Boolean make, KeyCode kc, unsigned int e_state) /* caps&num&scroll lock are special in the core X protocol: press/release means turning lock on/off, not pressing/releasing the key. - With XKB they are no longer special. To handle it correctly every time, + With XKB they are no longer special. To handle it correclty every time, and to make the code simple we just sync up the shiftstates before the keys are pressed. Note: @@ -294,7 +293,7 @@ void map_X_event(Display *display, XKeyEvent *e, struct mapped_X_event *result) #ifdef HAVE_XKB else { xkey = XK_VoidSymbol; - modifiers = 0; /* get set to the modifiers to clear... */ + modifiers = 0; /* get set to the modifers to clear... */ XkbLookupKeySym(display, e->keycode, e->state, &modifiers, &xkey); modifiers = e->state & (~modifiers); diff --git a/src/plugin/Xkmaps/Makefile b/src/plugin/Xkmaps/Makefile index 6a37103..368c348 100644 --- a/src/plugin/Xkmaps/Makefile +++ b/src/plugin/Xkmaps/Makefile @@ -10,7 +10,7 @@ include ../plugins.mak CFILES = X_keymaps.c X_keysyms.c GENHDRS = x_config.hh -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_XKmaps.so ALL_CFLAGS += -fPIC endif @@ -19,13 +19,13 @@ include $(REALTOPDIR)/src/Makefile.common.post ALL_CFLAGS+=$(DL_CFLAGS) -I$(srcdir)/include $(X_CFLAGS) -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_XKmaps.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(X_LIBS) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(X_LIBS) endif _x_config.h.in: $(srcdir)/configure.ac - autoheader -f + autoheader x_config.hh: _x_config.h.in configure ./configure diff --git a/src/plugin/Xkmaps/X_keymaps.c b/src/plugin/Xkmaps/X_keymaps.c index 1c4e785..0f7b55e 100644 --- a/src/plugin/Xkmaps/X_keymaps.c +++ b/src/plugin/Xkmaps/X_keymaps.c @@ -14,7 +14,6 @@ #include #endif -#include "init.h" #include "emu.h" #include "utilities.h" #include "keyboard/keyboard.h" diff --git a/src/plugin/Xkmaps/X_keysyms.c b/src/plugin/Xkmaps/X_keysyms.c index 2affff3..f510c10 100644 --- a/src/plugin/Xkmaps/X_keysyms.c +++ b/src/plugin/Xkmaps/X_keysyms.c @@ -25,7 +25,6 @@ #define XK_GEORGIAN #define XK_CURRENCY #include -#include "init.h" #include "translate/unicode_symbols.h" #include "translate/translate.h" #include "keyboard/keyboard.h" @@ -158,7 +157,7 @@ static struct xkey_to_dosemu_key keysym_map[] = { { XK_Eisu_Shift, DKY_VOID }, { XK_Eisu_toggle, DKY_VOID }, -/* 0xFF31 through 0xFF3F are under XK_KOREAN */ +/* 0xFF31 thru 0xFF3F are under XK_KOREAN */ /* Cursor control & motion */ @@ -238,7 +237,7 @@ static struct xkey_to_dosemu_key keysym_map[] = { { XK_KP_9, DKY_PAD_9 }, /* - * Auxiliary Functions; note the duplicate definitions for left and right + * Auxilliary Functions; note the duplicate definitions for left and right * function keys; Sun keyboards and a few other manufactures have such * function key groups on the left and/or right sides of the keyboard. * We've not found a keyboard with more than 35 function keys total. diff --git a/src/plugin/Xkmaps/configure.ac b/src/plugin/Xkmaps/configure.ac index 85a3708..0fb68a1 100644 --- a/src/plugin/Xkmaps/configure.ac +++ b/src/plugin/Xkmaps/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT -AC_CONFIG_HEADERS([_x_config.h]) +AC_CONFIG_HEADER([_x_config.h]) AC_CONFIG_FILES([Makefile.conf]) dnl Check for the XKB extension to get reliable keyboard handling @@ -9,6 +9,8 @@ AC_CHECK_HEADER(X11/XKBlib.h, AC_DEFINE(HAVE_XKB,1)) PKG_CHECK_MODULES([X11], [x11],, AC_MSG_ERROR([X development libraries not installed])) AC_MSG_NOTICE(Compiling with X support...) +AC_SUBST(X11_CFLAGS) +AC_SUBST(X11_LIBS) AC_OUTPUT diff --git a/src/plugin/alsa/Makefile b/src/plugin/alsa/Makefile index 387bc0d..47ed991 100644 --- a/src/plugin/alsa/Makefile +++ b/src/plugin/alsa/Makefile @@ -9,14 +9,14 @@ include ../plugins.mak ALL_CFLAGS+=$(DL_CFLAGS) $(ALSACFLAGS) CFILES=mid_o_alsa.c snd_i_alsa.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_alsa.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_alsa.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(ALSALIB) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(ALSALIB) endif diff --git a/src/plugin/alsa/configure.ac b/src/plugin/alsa/configure.ac index b4f46ff..5dfda94 100644 --- a/src/plugin/alsa/configure.ac +++ b/src/plugin/alsa/configure.ac @@ -1,6 +1,8 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT AC_CONFIG_FILES([Makefile.conf]) -PKG_CHECK_MODULES([ALSA], [alsa],, +AM_PATH_ALSA(0,, AC_MSG_ERROR([alsa development libs not found])) +AC_SUBST(ALSA_CFLAGS) +AC_SUBST(ALSA_LIBS) AC_OUTPUT diff --git a/src/plugin/alsa/m4/alsa.m4 b/src/plugin/alsa/m4/alsa.m4 new file mode 100644 index 0000000..e12310d --- /dev/null +++ b/src/plugin/alsa/m4/alsa.m4 @@ -0,0 +1,143 @@ +dnl Configure Paths for Alsa +dnl Some modifications by Richard Boulton +dnl Christopher Lansdown +dnl Jaroslav Kysela +dnl Last modification: $Id: alsa.m4,v 1.24 2004/09/15 18:48:07 tiwai Exp $ +dnl AM_PATH_ALSA([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for libasound, and define ALSA_CFLAGS and ALSA_LIBS as appropriate. +dnl enables arguments --with-alsa-prefix= +dnl --with-alsa-enc-prefix= +dnl --disable-alsatest +dnl +dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified, +dnl and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result. +dnl +AC_DEFUN([AM_PATH_ALSA], +[dnl Save the original CFLAGS, LDFLAGS, and LIBS +alsa_save_CFLAGS="$CFLAGS" +alsa_save_LDFLAGS="$LDFLAGS" +alsa_save_LIBS="$LIBS" +alsa_found=yes + +dnl +dnl Get the cflags and libraries for alsa +dnl +AC_ARG_WITH(alsa-prefix, +[ --with-alsa-prefix=PFX Prefix where Alsa library is installed(optional)], +[alsa_prefix="$withval"], [alsa_prefix=""]) + +AC_ARG_WITH(alsa-inc-prefix, +[ --with-alsa-inc-prefix=PFX Prefix where include libraries are (optional)], +[alsa_inc_prefix="$withval"], [alsa_inc_prefix=""]) + +dnl FIXME: this is not yet implemented +AC_ARG_ENABLE(alsatest, +[ --disable-alsatest Do not try to compile and run a test Alsa program], +[enable_alsatest="$enableval"], +[enable_alsatest=yes]) + +dnl Add any special include directories +AC_MSG_CHECKING(for ALSA CFLAGS) +if test "$alsa_inc_prefix" != "" ; then + ALSA_CFLAGS="$ALSA_CFLAGS -I$alsa_inc_prefix" + CFLAGS="$CFLAGS -I$alsa_inc_prefix" +fi +AC_MSG_RESULT($ALSA_CFLAGS) + +dnl add any special lib dirs +AC_MSG_CHECKING(for ALSA LDFLAGS) +if test "$alsa_prefix" != "" ; then + ALSA_LIBS="$ALSA_LIBS -L$alsa_prefix" + LDFLAGS="$LDFLAGS $ALSA_LIBS" +fi + +dnl add the alsa library +ALSA_LIBS="$ALSA_LIBS -lasound -lm -ldl -lpthread" +LIBS="$ALSA_LIBS $LIBS" +AC_MSG_RESULT($ALSA_LIBS) + +dnl Check for a working version of libasound that is of the right version. +if test "x$enable_alsatest" = "xyes"; then +min_alsa_version=ifelse([$1], ,0.1.1,$1) +AC_MSG_CHECKING(for libasound headers version >= $min_alsa_version) +no_alsa="" + alsa_min_major_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + alsa_min_minor_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + alsa_min_micro_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + +AC_LANG_SAVE +AC_LANG_C +AC_TRY_COMPILE([ +#include +], [ +/* ensure backward compatibility */ +#if !defined(SND_LIB_MAJOR) && defined(SOUNDLIB_VERSION_MAJOR) +#define SND_LIB_MAJOR SOUNDLIB_VERSION_MAJOR +#endif +#if !defined(SND_LIB_MINOR) && defined(SOUNDLIB_VERSION_MINOR) +#define SND_LIB_MINOR SOUNDLIB_VERSION_MINOR +#endif +#if !defined(SND_LIB_SUBMINOR) && defined(SOUNDLIB_VERSION_SUBMINOR) +#define SND_LIB_SUBMINOR SOUNDLIB_VERSION_SUBMINOR +#endif + +# if(SND_LIB_MAJOR > $alsa_min_major_version) + exit(0); +# else +# if(SND_LIB_MAJOR < $alsa_min_major_version) +# error not present +# endif + +# if(SND_LIB_MINOR > $alsa_min_minor_version) + exit(0); +# else +# if(SND_LIB_MINOR < $alsa_min_minor_version) +# error not present +# endif + +# if(SND_LIB_SUBMINOR < $alsa_min_micro_version) +# error not present +# endif +# endif +# endif +exit(0); +], + [AC_MSG_RESULT(found.)], + [AC_MSG_RESULT(not present.) + ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of libasound not found.)]) + alsa_found=no] +) +AC_LANG_RESTORE +fi + +dnl Now that we know that we have the right version, let's see if we have the library and not just the headers. +if test "x$enable_alsatest" = "xyes"; then +AC_CHECK_LIB([asound], [snd_ctl_open],, + [ifelse([$3], , [AC_MSG_ERROR(No linkable libasound was found.)]) + alsa_found=no] +) +fi + +if test "x$alsa_found" = "xyes" ; then + ifelse([$2], , :, [$2]) + LIBS=`echo $LIBS | sed 's/-lasound//g'` + LIBS=`echo $LIBS | sed 's/ //'` + LIBS="-lasound $LIBS" +fi +if test "x$alsa_found" = "xno" ; then + ifelse([$3], , :, [$3]) + CFLAGS="$alsa_save_CFLAGS" + LDFLAGS="$alsa_save_LDFLAGS" + LIBS="$alsa_save_LIBS" + ALSA_CFLAGS="" + ALSA_LIBS="" +fi + +dnl That should be it. Now just export out symbols: +AC_SUBST(ALSA_CFLAGS) +AC_SUBST(ALSA_LIBS) +]) + diff --git a/src/plugin/alsa/mid_o_alsa.c b/src/plugin/alsa/mid_o_alsa.c index 2bde323..f804ba7 100644 --- a/src/plugin/alsa/mid_o_alsa.c +++ b/src/plugin/alsa/mid_o_alsa.c @@ -34,22 +34,15 @@ static snd_rawmidi_t *handle, *handle_v; static const char *device_name_param = "dev_name"; static const char *device = "default"; static const char *device_v = "virtual"; -static const char *cur_dev; static int midoalsa_open(snd_rawmidi_t **handle_p, const char *dev_name) { int err; - cur_dev = dev_name; // for logging only err = snd_rawmidi_open(NULL, handle_p, dev_name, SND_RAWMIDI_NONBLOCK | SND_RAWMIDI_SYNC); if (err) { S_printf("%s: unable to open %s for writing: %s\n", midoalsa_name, dev_name, snd_strerror(err)); - if (err == -2) { - error("@snd-virmidi module not loaded or device \"%s\" not configured\n", - dev_name); - error("@see \"amidi -l\" for the list of midi devices\n"); - } return 0; } /* NONBLOCK flag is needed only so that open() not to block forever */ @@ -66,18 +59,18 @@ static void alsa_log_handler(const char *file, int line, const char *function, va_start(arg, fmt); - l = snprintf(s, sizeof(s), "%s:%s (ALSA err %i): ", - midoalsa_name, cur_dev, err); + l = snprintf(s, sizeof(s), "%s (ALSA lib): %s:%i:(%s) ", + midoalsa_name, file, line, function); + if(err && l >= 0) + l += snprintf(s+l, sizeof(s)-l, ": %s ", snd_strerror(err)); if (l >= 0) l += vsnprintf(s+l, sizeof(s)-l, fmt, arg); - if(err && l >= 0) - l += snprintf(s+l, sizeof(s)-l, ": %s", snd_strerror(err)); s[sizeof(s)-1] = '\0'; va_end(arg); - if (/*err && */!config.quiet) + if (err && !config.quiet) error("%s\n", s); else warn("%s\n", s); @@ -172,35 +165,29 @@ static void midoalsav_write(unsigned char val) snd_rawmidi_write(handle_v, &val, 1); } -static int midoalsav_cfg(void *arg) -{ - return pcm_parse_cfg(config.midi_driver, midoalsav_name); -} - static const struct midi_out_plugin midoalsa_v #ifdef __cplusplus { midoalsav_name, midoalsav_longname, - midoalsav_cfg, + midoalsa_cfg, midoalsav_init, midoalsav_done, 0, midoalsav_write, NULL, NULL, ST_MT32, - PCM_F_EXPLICIT + 0 }; #else = { .name = midoalsav_name, .longname = midoalsav_longname, - .get_cfg = midoalsav_cfg, + .get_cfg = midoalsa_cfg, .open = midoalsav_init, .close = midoalsav_done, .write = midoalsav_write, .stype = ST_MT32, - .flags = PCM_F_EXPLICIT }; #endif diff --git a/src/plugin/alsa/snd_i_alsa.c b/src/plugin/alsa/snd_i_alsa.c index 6141ee2..e38e1b5 100644 --- a/src/plugin/alsa/snd_i_alsa.c +++ b/src/plugin/alsa/snd_i_alsa.c @@ -20,8 +20,6 @@ * Author: Stas Sergeev */ -#include "ioselect.h" -#include "dosemu_debug.h" #include "emu.h" #include "init.h" #include "sound/sound.h" @@ -45,7 +43,7 @@ static int num_pfds; #define _FMT(x) SND_##x #define FMT(x) _FMT(x) -static void alsain_async(int fd, void *arg) +static void alsain_async(void *arg) { sndbuf_t buf[16384][SNDBUF_CHANS]; int n, pollret; @@ -71,7 +69,6 @@ static void alsain_async(int fd, void *arg) } if (pollret < 0 && errno != EINTR) error("ALSA: poll returned %i, %s\n", pollret, strerror(errno)); - ioselect_complete(fd); } static int alsain_open(void *arg) diff --git a/src/plugin/charsets/GB2312.c b/src/plugin/charsets/GB2312.c index bfae002..08460e8 100644 --- a/src/plugin/charsets/GB2312.c +++ b/src/plugin/charsets/GB2312.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode GB2312_1980_chars[] = { diff --git a/src/plugin/charsets/JIS0201.c b/src/plugin/charsets/JIS0201.c index f019e2b..e148bbf 100644 --- a/src/plugin/charsets/JIS0201.c +++ b/src/plugin/charsets/JIS0201.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode JIS0201_g0_chars[] = { diff --git a/src/plugin/charsets/JIS0208.c b/src/plugin/charsets/JIS0208.c index 981c526..cd21ef6 100644 --- a/src/plugin/charsets/JIS0208.c +++ b/src/plugin/charsets/JIS0208.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode JIS_X0208_1983_chars[] = { diff --git a/src/plugin/charsets/KSX1001.c b/src/plugin/charsets/KSX1001.c index de67004..d7c55f2 100644 --- a/src/plugin/charsets/KSX1001.c +++ b/src/plugin/charsets/KSX1001.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode KS_X1001_1992_chars[] = { diff --git a/src/plugin/charsets/ascii.c b/src/plugin/charsets/ascii.c index 0125561..137047f 100644 --- a/src/plugin/charsets/ascii.c +++ b/src/plugin/charsets/ascii.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" #include "unicode_symbols.h" diff --git a/src/plugin/charsets/cp437.c b/src/plugin/charsets/cp437.c index 71fadce..9e7c6c9 100644 --- a/src/plugin/charsets/cp437.c +++ b/src/plugin/charsets/cp437.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode cp437_c1_chars[] = { diff --git a/src/plugin/charsets/cp850.c b/src/plugin/charsets/cp850.c index 825c512..9e98162 100644 --- a/src/plugin/charsets/cp850.c +++ b/src/plugin/charsets/cp850.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode cp850_c1_chars[] = { diff --git a/src/plugin/charsets/cp852.c b/src/plugin/charsets/cp852.c index 72de948..6b3fb65 100644 --- a/src/plugin/charsets/cp852.c +++ b/src/plugin/charsets/cp852.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode cp852_c1_chars[] = { diff --git a/src/plugin/charsets/ibm_ascii.c b/src/plugin/charsets/ibm_ascii.c index da6bfbb..4c39509 100644 --- a/src/plugin/charsets/ibm_ascii.c +++ b/src/plugin/charsets/ibm_ascii.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode ibm_ascii_c0_chars[] = { diff --git a/src/plugin/charsets/iso2022.c b/src/plugin/charsets/iso2022.c index ae0cfe0..a89a0c4 100644 --- a/src/plugin/charsets/iso2022.c +++ b/src/plugin/charsets/iso2022.c @@ -1,7 +1,6 @@ #include #include #include -#include "init.h" #include "translate.h" #include "unicode_symbols.h" diff --git a/src/plugin/charsets/iso8859-1.c b/src/plugin/charsets/iso8859-1.c index 2535e06..41a9f6e 100644 --- a/src/plugin/charsets/iso8859-1.c +++ b/src/plugin/charsets/iso8859-1.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode iso8859_1_g1_chars[] = { diff --git a/src/plugin/charsets/iso8859-2.c b/src/plugin/charsets/iso8859-2.c index 9320ccf..700f594 100644 --- a/src/plugin/charsets/iso8859-2.c +++ b/src/plugin/charsets/iso8859-2.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode iso8859_2_g1_chars[] = { diff --git a/src/plugin/charsets/iso8859-3.c b/src/plugin/charsets/iso8859-3.c index d1a4389..7b91204 100644 --- a/src/plugin/charsets/iso8859-3.c +++ b/src/plugin/charsets/iso8859-3.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode iso8859_3_g1_chars[] = { diff --git a/src/plugin/charsets/iso8859-4.c b/src/plugin/charsets/iso8859-4.c index 4138f45..3cfb09e 100644 --- a/src/plugin/charsets/iso8859-4.c +++ b/src/plugin/charsets/iso8859-4.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode iso8859_4_g1_chars[] = { diff --git a/src/plugin/charsets/iso8859-5.c b/src/plugin/charsets/iso8859-5.c index bc8e0fd..2f9fc6e 100644 --- a/src/plugin/charsets/iso8859-5.c +++ b/src/plugin/charsets/iso8859-5.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode iso8859_5_g1_chars[] = { diff --git a/src/plugin/charsets/iso8859-6.c b/src/plugin/charsets/iso8859-6.c index 4a9874a..912d5bc 100644 --- a/src/plugin/charsets/iso8859-6.c +++ b/src/plugin/charsets/iso8859-6.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode iso8859_6_g1_chars[] = { diff --git a/src/plugin/charsets/iso8859-7.c b/src/plugin/charsets/iso8859-7.c index 9c5c456..55c9f95 100644 --- a/src/plugin/charsets/iso8859-7.c +++ b/src/plugin/charsets/iso8859-7.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode iso8859_7_g1_chars[] = { diff --git a/src/plugin/charsets/iso8859-8.c b/src/plugin/charsets/iso8859-8.c index 57654c8..faed3ea 100644 --- a/src/plugin/charsets/iso8859-8.c +++ b/src/plugin/charsets/iso8859-8.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode iso8859_8_g1_chars[] = { diff --git a/src/plugin/charsets/iso8859-9.c b/src/plugin/charsets/iso8859-9.c index 480e245..cc772f0 100644 --- a/src/plugin/charsets/iso8859-9.c +++ b/src/plugin/charsets/iso8859-9.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" static const t_unicode iso8859_9_g1_chars[] = { diff --git a/src/plugin/charsets/multibyte.c b/src/plugin/charsets/multibyte.c index 8bf2d8c..485d27a 100644 --- a/src/plugin/charsets/multibyte.c +++ b/src/plugin/charsets/multibyte.c @@ -3,7 +3,6 @@ #include #include #include -#include "init.h" #include "translate.h" /* I assume wchar_t/wint_t is in unicode ... */ diff --git a/src/plugin/charsets/utf8.c b/src/plugin/charsets/utf8.c index 731822e..8e36ddf 100644 --- a/src/plugin/charsets/utf8.c +++ b/src/plugin/charsets/utf8.c @@ -1,6 +1,5 @@ #include #include -#include "init.h" #include "translate.h" /* utf8 */ diff --git a/src/plugin/charsets/vt100.c b/src/plugin/charsets/vt100.c index 9b6d67e..9ecc25a 100644 --- a/src/plugin/charsets/vt100.c +++ b/src/plugin/charsets/vt100.c @@ -1,4 +1,3 @@ -#include "init.h" #include "translate.h" /* table from Linux kernel */ diff --git a/src/plugin/console/Makefile b/src/plugin/console/Makefile index a8e81cd..604e520 100644 --- a/src/plugin/console/Makefile +++ b/src/plugin/console/Makefile @@ -9,14 +9,14 @@ include ../plugins_simp.mak ALL_CFLAGS+=$(DL_CFLAGS) CFILES = vc.c vga.c vbe.c $(VCFILES) console.c detach.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_console.so $(LIB) ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_console.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ endif diff --git a/src/plugin/console/console.c b/src/plugin/console/console.c index 03e55f8..b48ee98 100644 --- a/src/plugin/console/console.c +++ b/src/plugin/console/console.c @@ -4,7 +4,7 @@ #include #include #ifdef __linux__ -#include "Sys/kd.h" +#include #include #endif @@ -54,7 +54,7 @@ static void console_update_cursor(void) fprintf(stdout,"\033[%d;%dH",ypos+1,xpos+1); } else { - /* Disable blinking if it hasn't already */ + /* Disable blinking if it hasnt already */ if (oldblink) fprintf(stdout,"\033[?25l"); } @@ -75,6 +75,7 @@ static int console_post_init(void) vc_post_init(); set_vc_screen_page(); + set_process_control(); k_printf("KBD: Taking mouse control\n"); /* Actually only in KD_GRAPHICS... */ /* Some escape sequences don't work in KD_GRAPHICS... */ kdmode = config.vga? KD_GRAPHICS: KD_TEXT; @@ -160,7 +161,6 @@ static int console_init(void) if (config.detach) consolenum = detach(); - set_process_control(); return 0; } diff --git a/src/plugin/console/detach.c b/src/plugin/console/detach.c index c93cef6..b0fd5e5 100644 --- a/src/plugin/console/detach.c +++ b/src/plugin/console/detach.c @@ -4,7 +4,7 @@ #include #ifdef __linux__ #include -#include "Sys/kd.h" +#include #endif #include #include diff --git a/src/plugin/console/vbe.c b/src/plugin/console/vbe.c index 8c42163..e80503c 100644 --- a/src/plugin/console/vbe.c +++ b/src/plugin/console/vbe.c @@ -52,6 +52,9 @@ struct VBE_vi_vm { #define VESA_SAVE_BITMAP 0xf /* save everything */ +#define RM_STACK_SIZE 0x200 +static void *rm_stack = NULL; + static void do_int10_callback(struct vm86_regs *regs) { struct vm86_regs saved_regs; @@ -237,6 +240,7 @@ static void vesa_setbank_write(unsigned char bank) void vesa_init(void) { + rm_stack = lowmem_alloc(RM_STACK_SIZE); vesa_int10 = MK_FP16(ISEG(0x10), IOFF(0x10)); vesa_reinit(); /* This is all we need before booting. Memory info comes later */ diff --git a/src/plugin/console/vc.c b/src/plugin/console/vc.c index 4b73a17..f5a2596 100644 --- a/src/plugin/console/vc.c +++ b/src/plugin/console/vc.c @@ -35,7 +35,7 @@ #include #ifdef __linux__ #include -#include "Sys/kd.h" +#include #endif #define INIT_C2TRAP @@ -120,7 +120,7 @@ static void SIGACQUIRE_call(void *arg) int dos_has_vt = 1; -static void acquire_vt(siginfo_t *si) +static void acquire_vt(sigcontext_t *scp, siginfo_t *si) { dos_has_vt = 1; @@ -260,7 +260,7 @@ static void wait_for_active_vc(void) } while (errno == EINTR); } -static void release_vt(siginfo_t *si) +static void release_vt(sigcontext_t *scp, siginfo_t *si) { dos_has_vt = 0; @@ -305,9 +305,9 @@ static void tempsigvt(int sig) /* temporary signal handler between set_process_control and final setting of signals in signal_init() */ if (sig == SIG_RELEASE) - release_vt(NULL); + release_vt(NULL, NULL); else - acquire_vt(NULL); + acquire_vt(NULL, NULL); } /* this puts the VC under process control */ @@ -832,7 +832,7 @@ void vc_post_init(void) vcr_tid = coopth_create("vc release", __SIGRELEASE_call); coopth_set_permanent_post_handler(vc_tid, vc_switch_done); coopth_set_permanent_post_handler(vcr_tid, vc_switch_done); - /* we don't use detached thread here to avoid the DOS code + /* we dont use detached thread here to avoid the DOS code * from running concurrently with video mem saving. Another * solution (simpler one) is to rely on freeze_dosemu() and * use the detached thread here. */ diff --git a/src/plugin/console/vga.c b/src/plugin/console/vga.c index d679e27..e72eff0 100644 --- a/src/plugin/console/vga.c +++ b/src/plugin/console/vga.c @@ -8,7 +8,7 @@ #include #include #ifdef __linux__ -#include "Sys/kd.h" +#include #include #include #endif @@ -100,7 +100,7 @@ static void dosemu_vga_screenoff(void) port_out(0x00, SEQ_I); port_out(0x01, SEQ_D); - /* turn off screen for faster VGA memory access */ + /* turn off screen for faster VGA memory acces */ port_out(0x01, SEQ_I); port_out(port_in(SEQ_D) | 0x20, SEQ_D); @@ -508,7 +508,7 @@ static void pcivga_init(void) for VGA BIOSes to use */ pcirec = pciemu_setup(PCI_CLASS_DISPLAY_VGA << 8); else - pcirec = pcibios_find_primary_vga(); + pcirec = pcibios_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0); if (!pcirec) { /* only set pci_video=0 if no PCI is available. Otherwise it's set by default */ @@ -527,6 +527,8 @@ static void pcivga_init(void) v_printf("PCIVGA: found IO region at %#lx [%#lx]\n", base, size); /* register PCI VGA ports */ + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; io_device.handler_name = "std port io"; io_device.start_addr = base; io_device.end_addr = base + size; @@ -547,6 +549,8 @@ static int vga_ioperm(unsigned base, int len) error("ioperm() %x,%i failed\n", base, len); /* even if ioperm failed, we register handler that will forward * the requests to portserver */ + io_device.irq = EMU_NO_IRQ; + io_device.fd = -1; io_device.handler_name = "std port io"; io_device.start_addr = base; io_device.end_addr = base + len - 1; @@ -562,8 +566,6 @@ static void set_console_video(void) if (config.mapped_bios) { vga_ioperm(0x3b4, 0x3bc - 0x3b4 + 1); vga_ioperm(0x3c0, 0x3df - 0x3c0 + 1); - vga_ioperm(0x1ce, 4); // ATI, qemu - vga_ioperm(0x402, 1); // qemu } vga_ioperm(0x3bf, 1); } diff --git a/src/plugin/debugger/Makefile b/src/plugin/debugger/Makefile index fbcff6d..f0b574f 100644 --- a/src/plugin/debugger/Makefile +++ b/src/plugin/debugger/Makefile @@ -7,7 +7,15 @@ include ../plugins.mak #The C files, include files and dependancies here. -CFILES = mhpdbg.c mhpdbgc.c +CFILES = mhpdbg.c mhpdbgc.c dis8086.c dosdebug.c +DEPENDS = mhpdbg.d mhpdbgc.d dis8086.d dosdebug.d +HFILES = + +# Insert all source- and header-files here. +ALL = $(CFILES) $(HFILES) README.dosdebug README.recover Changelog + +# All object-files are included here. +OBJS = mhpdbg.o mhpdbgc.o dis8086.o all: lib $(BINPATH)/bin/dosdebug diff --git a/src/plugin/debugger/configure.ac b/src/plugin/debugger/configure.ac index 2e444a1..f489851 100644 --- a/src/plugin/debugger/configure.ac +++ b/src/plugin/debugger/configure.ac @@ -8,17 +8,6 @@ AC_CHECK_LIB(readline, main, [ ], [ AC_MSG_ERROR(Please install libreadline-dev for readline support in dosdebug) ]) -AC_CHECK_LIB(readline, rl_copy_text, [], [ - CPPFLAGS="$CPPFLAGS -I/usr/local/opt/readline/include" - LDFLAGS="$LDFLAGS -L/usr/local/opt/readline/lib" - AS_UNSET([ac_cv_lib_readline_rl_copy_text]) - AC_CHECK_LIB(readline, rl_copy_text, [ - DOSDEBUG_LIBS="$DOSDEBUG_LIBS -L/usr/local/opt/readline/lib" - DOSDEBUG_DEFS="$DOSDEBUG_DEFS -I/usr/local/opt/readline/include" - ], [ - AC_MSG_ERROR(If using a Mac, please brew install readline) - ]) -]) AC_SUBST(DOSDEBUG_LIBS) AC_SUBST(DOSDEBUG_DEFS) diff --git a/src/base/lib/misc/dis8086.c b/src/plugin/debugger/dis8086.c similarity index 99% rename from src/base/lib/misc/dis8086.c rename to src/plugin/debugger/dis8086.c index 23398d3..8d7b35b 100644 --- a/src/base/lib/misc/dis8086.c +++ b/src/plugin/debugger/dis8086.c @@ -1084,12 +1084,7 @@ static void ua_str(const char *str) else if (c == '%') { c = *str++; - if (!c) - break; - percent(c, *str); - if (!*str) - break; - str++; + percent(c, *str++); } else { uputchar(c); } diff --git a/src/plugin/debugger/dosdebug.c b/src/plugin/debugger/dosdebug.c index ceacd85..b5242bb 100644 --- a/src/plugin/debugger/dosdebug.c +++ b/src/plugin/debugger/dosdebug.c @@ -29,7 +29,7 @@ #include "utilities.h" -#define TMPFILE_VAR "/var/run/user/%i/dosemu2/dosemu." +#define TMPFILE_VAR "/var/run/dosemu." #define TMPFILE_HOME ".dosemu/run/dosemu." #define MHP_BUFFERSIZE 8192 @@ -43,7 +43,7 @@ const char *prompt = "dosdebug> "; int fdconin, fddbgin, fddbgout; FILE *fpconout; -static int running; +int running; static int check_pid(int pid); @@ -223,14 +223,6 @@ static COMMAND cmds[] = { "ADDR display the Device Driver Request Header at ADDR\n"}, {"dpbs", NULL, "[ADDR] display DPBs by walking the chain from LOL or ADDR\n"}, - {"injchar", NULL, - "ASCII_CODE inject character to console\n"}, - {"hookcbrk", NULL, - "[on | off] hook ^break handling\n"}, - {"dosbreak", NULL, - " command for testing\n"}, - {"reboot", NULL, - " reboot dosemu\n"}, {"kill", db_kill, " Kill the dosemu process\n"}, {"quit", db_quit, @@ -404,8 +396,9 @@ static int handle_dbg_input(int *retval) char buf[MHP_BUFFERSIZE], *p; int n; - *retval = 0; - n = read(fddbgin, buf, sizeof(buf)); + do { + n=read(fddbgin, buf, sizeof(buf)); + } while (n < 0 && errno == EAGAIN); if (n > 0) { if ((p = memchr(buf, 1, n)) != NULL) { @@ -442,10 +435,6 @@ static int handle_dbg_input(int *retval) *retval = 1; return 0; } - if (n == -1) { - *retval = 1; - return 1; - } return 1; } @@ -474,9 +463,7 @@ int main (int argc, char **argv) free(dosemu_tmpfile_pat); } if (dospid == -1) { - char fname[256]; - snprintf(fname, sizeof(fname), TMPFILE_VAR "dbgin.", getuid()); - dospid = find_dosemu_pid(fname, 0); + dospid=find_dosemu_pid(TMPFILE_VAR "dbgin.", 0); } } else dospid=strtol(argv[1], 0, 0); @@ -495,7 +482,7 @@ int main (int argc, char **argv) ret = asprintf(&pipename_out, "%s/%sdbgout.%d", home_p, TMPFILE_HOME, dospid); assert(ret != -1); - fddbgout = open(pipename_in, O_WRONLY | O_NONBLOCK | O_CLOEXEC); + fddbgout = open(pipename_in, O_RDWR | O_NONBLOCK | O_CLOEXEC); if (fddbgout == -1) { free(pipename_in); free(pipename_out); @@ -504,13 +491,13 @@ int main (int argc, char **argv) if (fddbgout == -1) { /* if we cannot open pipe and we were trying $HOME/.dosemu/run directory, try with /var/run/dosemu directory */ - ret = asprintf(&pipename_in, TMPFILE_VAR "dbgin.%d", getuid(), dospid); + ret = asprintf(&pipename_in, TMPFILE_VAR "dbgin.%d", dospid); assert(ret != -1); - ret = asprintf(&pipename_out, TMPFILE_VAR "dbgout.%d", getuid(), dospid); + ret = asprintf(&pipename_out, TMPFILE_VAR "dbgout.%d", dospid); assert(ret != -1); - fddbgout = open(pipename_in, O_WRONLY | O_NONBLOCK | O_CLOEXEC); + fddbgout = open(pipename_in, O_RDWR | O_NONBLOCK | O_CLOEXEC); } if (fddbgout == -1) { @@ -585,10 +572,6 @@ int main (int argc, char **argv) #endif if (!running) { - /* collect all remaining input */ - do - usleep(100000); - while (handle_dbg_input(&ret) && ret == 0); fputs("\n", fpconout); fflush(fpconout); break; diff --git a/src/plugin/debugger/mhpdbg.c b/src/plugin/debugger/mhpdbg.c index 1459e7e..9962ac1 100644 --- a/src/plugin/debugger/mhpdbg.c +++ b/src/plugin/debugger/mhpdbg.c @@ -24,7 +24,6 @@ #include "bitops.h" #include "emu.h" -#include "ioselect.h" #include "cpu.h" #include "bios.h" #include "coopth.h" @@ -35,7 +34,7 @@ #define MHP_PRIVATE #include "mhpdbg.h" -__TLS struct mhpdbg mhpdbg; +struct mhpdbg mhpdbg; unsigned long dosdebug_flags; static void vmhp_printf(const char *fmt, va_list args); @@ -56,16 +55,11 @@ struct mhpdbgc mhpdbgc ={0}; static void mhp_puts(char* s) { - int need_send = 0; for (;;){ if (*s == 0x00) break; - if (*s == '\n') - need_send++; mhp_putc (*s++); } - if (need_send) - mhp_send(); } void mhp_putc(char c1) @@ -136,7 +130,7 @@ int vmhp_log_intercept(int flg, const char *fmt, va_list args) return 0; } -static void mhp_input_async(int fd, void *arg) +static void mhp_input_async(void *arg) { mhp_input(); } @@ -154,10 +148,10 @@ static void mhp_init(void) memset(&mhpdbg.intxxtab, 0, sizeof(mhpdbg.intxxtab)); memset(&mhpdbgc.intxxalt, 0, sizeof(mhpdbgc.intxxalt)); - retval = asprintf(&pipename_in, "%s/dosemu.dbgin.%d", dosemu_rundir_path, getpid()); + retval = asprintf(&pipename_in, "%s/dosemu.dbgin.%d", RUNDIR, getpid()); assert(retval != -1); - retval = asprintf(&pipename_out, "%s/dosemu.dbgout.%d", dosemu_rundir_path, getpid()); + retval = asprintf(&pipename_out, "%s/dosemu.dbgout.%d", RUNDIR, getpid()); assert(retval != -1); retval = mkfifo(pipename_in, S_IFIFO | 0600); @@ -196,8 +190,6 @@ static void mhp_init(void) mhp_input(); } } - - mhpdbgc_init(); } static void reopen_fdin(void) @@ -209,13 +201,12 @@ static void reopen_fdin(void) add_to_io_select(mhpdbg.fdin, mhp_input_async, NULL); } -void mhp_input(void) +void mhp_input() { if (mhpdbg.fdin == -1) return; mhpdbg.nbytes = read(mhpdbg.fdin, mhpdbg.recvbuf, SRSIZE); - ioselect_complete(mhpdbg.fdin); if (mhpdbg.nbytes == -1) return; @@ -302,8 +293,7 @@ static void mhp_pre_vm86(void) { if (!mhpdbg.active) return; - if ((!in_dpmi_pm() && isset_TF()) || - (in_dpmi_pm() && dpmi_mhp_issetTF())) { + if (isset_TF() && !in_dpmi_pm()) { if (mhpdbgc.trapip != mhp_getcsip_value()) { mhpdbgc.trapcmd = 0; mhpdbgc.stopped = 1; @@ -377,6 +367,8 @@ void mhp_intercept(const char *msg, const char *logflags) mhp_cmd("r0"); mhp_send(); if (!(dosdebug_flags & DBGF_IN_LEAVEDOS)) { + if (in_dpmi_pm()) + dpmi_return_request(); if (logflags) mhp_intercept_log(logflags, 1); return; @@ -396,15 +388,10 @@ void mhp_exit_intercept(int errcode) int mhp_revectored(int inum) { - return test_bit(inum, mhpdbg.intxxtab); + return test_bit(inum, mhpdbgc.intxxalt); } -void mhp_adjust_revectored(int inum) -{ - set_bit(inum, mhpdbgc.intxxalt); -} - -unsigned int mhp_debug(unsigned code, unsigned int parm1, unsigned int parm2) +unsigned int mhp_debug(enum dosdebug_event code, unsigned int parm1, unsigned int parm2) { int rtncd = 0; #if 0 @@ -422,7 +409,7 @@ unsigned int mhp_debug(unsigned code, unsigned int parm1, unsigned int parm2) if (!mhpdbg.active) break; if (test_bit(DBG_ARG(mhpdbgc.currcode), mhpdbg.intxxtab)) { - if ((mhpdbgc.bpload==1) && (DBG_ARG(mhpdbgc.currcode) == 0x21) && ((LWORD(eax) & 0xff0f) == 0x4b00) ) { + if ((mhpdbgc.bpload==1) && (DBG_ARG(mhpdbgc.currcode) == 0x21) && (LWORD(eax) == 0x4b00) ) { mhpdbgc.bpload_bp = SEGOFF2LINEAR(SREG(cs), LWORD(eip)); if (mhp_setbp(mhpdbgc.bpload_bp)) { Bit16u int_op = READ_WORD(SEGOFF2LINEAR(SREG(cs), LWORD(eip) - 2)); @@ -454,7 +441,7 @@ unsigned int mhp_debug(unsigned code, unsigned int parm1, unsigned int parm2) clear_bit(i, mhpdbg.intxxtab); if (test_bit(i, mhpdbgc.intxxalt)) { clear_bit(i, mhpdbgc.intxxalt); - clear_bit(i, &vm86s.int_revectored); + reset_revectored(i, &vm86s.int_revectored); } } } diff --git a/src/plugin/debugger/mhpdbgc.c b/src/plugin/debugger/mhpdbgc.c index 3298064..92ff26c 100644 --- a/src/plugin/debugger/mhpdbgc.c +++ b/src/plugin/debugger/mhpdbgc.c @@ -16,7 +16,7 @@ * - now can set breakpoints in DPMI-client * - now has DPMI-INTx type breakpoints with matching for AX * - fixed disassembler and addresses to reflect - * segmented protected mode (linear mode wasn't usable for DPMI) + * segmented protected mode (linear mode wasn't useable for DPMI) * - ldt commando now skips NULL-entries. * * 19May96 Max Parke @@ -62,22 +62,13 @@ #include "bios_sym.h" #include "dis8086.h" #include "dos2linux.h" -#include "coopth.h" #include "kvm.h" -#include "Asm/ldt.h" #define MHP_PRIVATE #include "mhpdbg.h" #define makeaddr(x,y) ((((unsigned int)x) << 4) + (unsigned int)y) -static struct HMCB *hma_start; -static int ic_tid; -static int setbrk_tid; -static Bit16u cbrk_handler_hlt; -static far_t old_cbrk_hdlr; -static int old_cbrk_on; - /* prototypes */ static void mhp_regs (int, char *[]); static void mhp_r0 (int, char *[]); @@ -111,10 +102,6 @@ static void mhp_ddrh (int, char *[]); static void mhp_dpbs (int, char *[]); static void mhp_bplog (int, char *[]); static void mhp_bclog (int, char *[]); -static void mhp_reboot (int, char *[]); -static void mhp_injchar (int, char *[]); -static void mhp_hookcbrk (int, char *[]); -static void mhp_dosbreak (int, char *[]); static void print_log_breakpoints(void); static int bpchk(unsigned int a1); @@ -145,11 +132,6 @@ static int trapped_bp=-1, trapped_bp_; int traceloop=0; char loopbuf[4] = ""; -struct cmd_db { - char cmdname[12]; - void (*cmdproc)(int, char *[]); -}; - /* constants */ static const struct cmd_db cmdtab[] = { {"r0", mhp_r0}, @@ -185,10 +167,6 @@ static const struct cmd_db cmdtab[] = { {"devs", mhp_devs}, {"ddrh", mhp_ddrh}, {"dpbs", mhp_dpbs}, - {"reboot", mhp_reboot}, - {"injchar", mhp_injchar}, - {"hookcbrk", mhp_hookcbrk}, - {"dosbreak", mhp_dosbreak}, {"", NULL} }; @@ -391,29 +369,6 @@ static int check_for_stopped(void) return mhpdbgc.stopped; } -/* Interrogate DOS for HMA start (Win95+) */ -void mhp_init_hma(void) -{ - hma_start = NULL; - pre_msdos(); - - LWORD(eax) = 0x3306; - call_msdos(); - if (HI(dx) & 0x10) { - LWORD(eax) = 0x4a04; - do_int_call_back(0x2f); - if (LWORD(eax) == 0) - hma_start = MK_FP32(SREG(es), LWORD(edi)); - } - - post_msdos(); -} - -void mhp_reset_hma(void) -{ - hma_start = NULL; -} - int mhp_usermap_load_gnuld(const char *fname, uint16_t origin) { FILE *fp; @@ -1053,7 +1008,7 @@ static void mhp_dump(int argc, char * argv[]) } else { snprintf(lastd, sizeof(lastd), "%x:%x", seg, off + i); } - } else if (unixaddr) { + } else if (unix) { snprintf(lastd, sizeof(lastd), "%#x", seekval + i); } else { snprintf(lastd, sizeof(lastd), "%x", seekval + i); @@ -1089,7 +1044,7 @@ static void mhp_dump_to_file(int argc, char * argv[]) return; } - fd = open(argv[3], O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 00640); + fd = open(argv[3], O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 00775); if (fd < 0) { mhp_printf("cannot open/create file %s\n%s\n", argv[3], strerror(errno)); return; @@ -1115,7 +1070,7 @@ static const char *get_type_from_mcb(struct MCB *mcb) if (p1 == p2) return inv; - // Are we 1st descendant? + // Are we 1st decendant? p1 = MK_FP32(mcb->owner_psp - 1, 0); p2 = MK_FP32(p1->owner_psp - 1, 0); if (p1 == p2) { @@ -1153,19 +1108,19 @@ static const char *get_name_from_mcb(struct MCB *mcb, int *is_lnk) p1 = mcb; p2 = MK_FP32(p1->owner_psp - 1, 0); if (p1 == p2) { - strlcpy(name, p1->name, 8 + 1); // Source not null terminated if 8 chars - if (!is_printable(name)) + if (!is_printable(p1->name)) goto out; + strlcpy(name, p1->name, 8 + 1); // Source not null terminated if 8 chars return name; } - // Are we 1st descendant? + // Are we 1st decendant? p1 = MK_FP32(mcb->owner_psp - 1, 0); p2 = MK_FP32(p1->owner_psp - 1, 0); if (p1 == p2) { - strlcpy(name, p1->name, 8 + 1); // Source not null terminated if 8 chars - if (!is_printable(name)) + if (!is_printable(p1->name)) goto out; + strlcpy(name, p1->name, 8 + 1); // Source not null terminated if 8 chars strlcat(name, " - ", sizeof name); strlcat(name, get_type_from_mcb(mcb), sizeof name); return name; @@ -1295,7 +1250,7 @@ static void mhp_ivec(int argc, char *argv[]) } } -static void print_mcb(struct MCB *mcb, uint32_t seg) +static void print_mcb(struct MCB *mcb, uint16_t seg) { int lnk; const char *name = get_name_from_mcb(mcb, &lnk); @@ -1348,9 +1303,6 @@ static void print_dscb(struct DSCB *dscb) case 'S': stnam = "Stacks"; break; - case 'T': - stnam = "Transition Code"; - break; default: stnam = "Unknown Type"; break; @@ -1360,36 +1312,19 @@ static void print_dscb(struct DSCB *dscb) dscb->size, dscb->stype, stnam); } -static const char *hma_id_to_name(uint16_t id) -{ - switch (id) { - case 0x0000: - return "FREE"; - case 0x0001: - return "DOS"; - case 0xFF33: - return "IO.SYS"; - case 0xFFFF: - return "MSDOS.SYS"; - } - return NULL; -} - static void mhp_mcbs(int argc, char *argv[]) { struct MCB *mcb; - uint32_t seg; - int uma, hdr, cnt; + uint16_t seg; + int uma, hdr; struct DSCB *dscb; uint16_t dsseg; - struct HMCB *hmcb, *htmp; if (!lol) { mhp_printf("DOS's LOL not set\n"); return; } - // LOW and UMA for (seg = READ_WORD(lol - 2), mcb = MK_FP32(seg, 0), uma = 0, hdr = 1; mcb->id == 'M' || mcb->id == 'Z'; seg += (1 + mcb->size), mcb = MK_FP32(seg, 0)) { @@ -1416,37 +1351,6 @@ static void mhp_mcbs(int argc, char *argv[]) hdr = 1; } } - - // HMA - for (hmcb = hma_start, cnt = 0; hmcb && cnt < 50; cnt++) { - uint16_t hoff = (uintptr_t)hmcb - (uintptr_t)MK_FP32(0xffff, 0); - const char *name; - char buf[32]; - - if (hmcb->signature == HMCB_SIG && hmcb->next < 0xfff0) { - htmp = MK_FP32(0xffff, hmcb->next); - if (htmp->signature == HMCB_SIG) { - // Seemingly we have a valid HMA MCB - if (cnt == 0) { - mhp_printf("\nADDR(HMA) PARAS OWNER\n"); - } - - name = hma_id_to_name(hmcb->owner); - if (!name) - name = get_mcb_name_walk_chain(hmcb->owner, 0); - if (!name) { - snprintf(buf, sizeof buf, "%04x", hmcb->owner); - name = buf; - } - - mhp_printf("ffff:%04x 0x%04x [%s]\n", hoff, hmcb->size / 16, name); - } else if (hmcb->next == 0) { - mhp_printf("ffff:%04x (END)\n", hoff); - break; - } - hmcb = htmp; - } - } } static void mhp_devs(int argc, char *argv[]) @@ -1781,8 +1685,6 @@ static void mhp_disasm(int argc, char * argv[]) refseg = seg; rc = dis_8086(buf+bytesdone, frmtbuf, def_size, &ref, (IN_DPMI ? GetSegmentBase(refseg) : refseg * 16)); - if (bytesdone + rc > 256) - break; for (i=0;i limit && GetSegmentType(seg1) != MODIFY_LDT_CONTENTS_STACK) { + if (off1 >= limit) { mhp_printf("offset %x exceeds segment limit %x\n", off1, limit); return 0; } @@ -2208,7 +2110,7 @@ static void mhp_bpint(int argc, char * argv[]) set_bit(num, mhpdbg.intxxtab); if (!test_bit(num, &vm86s.int_revectored)) { set_bit(num, mhpdbgc.intxxalt); - set_bit(num, &vm86s.int_revectored); + set_revectored(num, &vm86s.int_revectored); } if (num == 0x21) mhpdbgc.int21_count++; @@ -2236,12 +2138,10 @@ static void mhp_bcint(int argc, char * argv[]) clear_bit(num, mhpdbg.intxxtab); if (test_bit(num, mhpdbgc.intxxalt)) { clear_bit(num, mhpdbgc.intxxalt); - clear_bit(num, &vm86s.int_revectored); - } - if (num == 0x21) { - mhpdbgc.int21_count--; - mhpdbgc.bpload = 0; + reset_revectored(num, &vm86s.int_revectored); } + if (num == 0x21) + mhpdbgc.int21_count--; return; } @@ -2329,11 +2229,11 @@ static void mhp_bpload(int argc, char * argv[]) } mhpdbgc.bpload=1; { - int i = 0x21; + volatile register int i=0x21; /* beware, set_bit-macro has wrong constraints */ set_bit(i, mhpdbg.intxxtab); if (!test_bit(i, &vm86s.int_revectored)) { set_bit(i, mhpdbgc.intxxalt); - set_bit(i, &vm86s.int_revectored); + set_revectored(i, &vm86s.int_revectored); } } mhpdbgc.int21_count++; @@ -2553,7 +2453,7 @@ int mhp_bpchk(unsigned int a1) return bpchk(a1); } -int mhp_getcsip_value(void) +int mhp_getcsip_value() { dosaddr_t val; unsigned int seg, off, limit; @@ -2572,48 +2472,6 @@ void mhp_modify_eip(int delta) else LWORD(eip) +=delta; } -typedef void cmdprintf_func(const char *fmt, ...); - -static void call_cmd(const char *cmd, int maxargs, const struct cmd_db *cmdtab, - cmdprintf_func *printf) -{ - int argc1; - char **argv1; - char *tmpcmd; - void (*cmdproc)(int, char *[]); - const struct cmd_db *cmdp; - - tmpcmd = strdup(cmd); - if (!tmpcmd) { - if (printf) (*printf)("out of memory\n"); - return; - } - argv1 = malloc(maxargs * sizeof(char *)); - if (!argv1) { - if (printf) (*printf)("out of memory\n"); - free(tmpcmd); - return; - }; - argc1 = argparse(tmpcmd, argv1, maxargs); - if (argc1 < 1) { - free(tmpcmd); - free(argv1); - return; - } - for (cmdp = cmdtab, cmdproc = NULL; cmdp->cmdproc; cmdp++) { - if (!memcmp(cmdp->cmdname, argv1[0], strlen(argv1[0])+1)) { - cmdproc = cmdp->cmdproc; - break; - } - } - if (!cmdproc) { - if (printf) (*printf)("Command %s not found\n", argv1[0]); - } - else (*cmdproc)(argc1, argv1); - free(tmpcmd); - free(argv1); -} - void mhp_cmd(const char * cmd) { call_cmd(cmd, MAXARG, cmdtab, mhp_printf); @@ -2644,7 +2502,7 @@ static void mhp_print_ldt(int argc, char * argv[]) } lines = page ? 16 : 1; - if (get_ldt(buffer, LDT_ENTRIES * LDT_ENTRY_SIZE) < 0) { + if (get_ldt(buffer) < 0) { mhp_printf("error getting ldt\n"); return; } @@ -2876,100 +2734,6 @@ static void mhp_bclog(int argc, char *argv[]) print_log_breakpoints(); } -static void mhp_reboot(int argc, char *argv[]) -{ - dos_ctrl_alt_del(); -} - -static void mhp_injchar_thr(void *arg) -{ - struct vm86_regs saved_regs = REGS; - _AX = 0x500; - _CX = (uintptr_t)arg; - do_int_call_back(0x16); - REGS = saved_regs; -} - -static void mhp_injchar(int argc, char *argv[]) -{ - int key; - if (argc < 2) { - mhp_printf("missing argument\n"); - return; - } - key = atoi(argv[1]); - mhp_printf("injecting %x\n", key); - coopth_start(ic_tid, (void*)(uintptr_t)key); -} - -static void do_hookcbrk(int on); - -static void cbrk_handler(Bit16u idx, HLT_ARG(arg)) -{ - int cnt = coopth_get_thread_count_in_process_vm86(); - fake_iret(); - mhp_printf("got cbreak, %i\n", cnt); - if (!cnt) - do_hookcbrk(0); -} - -static void mhp_setbrk_thr(void *arg) -{ - pre_msdos(); - _AX = 0x3300; - call_msdos(); - old_cbrk_on = _DX & 1; - _AX = 0x3301; - _DX = (uintptr_t)arg; - call_msdos(); - post_msdos(); -} - -static void do_hookcbrk(int on) -{ - if (on) { - old_cbrk_hdlr.segment = ISEG(0x23); - old_cbrk_hdlr.offset = IOFF(0x23); - SETIVEC(0x23, BIOS_HLT_BLK_SEG, cbrk_handler_hlt); - coopth_start(setbrk_tid, (void *)(uintptr_t)on); - } else { - SETIVEC(0x23, old_cbrk_hdlr.segment, old_cbrk_hdlr.offset); - coopth_start(setbrk_tid, (void *)(uintptr_t)old_cbrk_on); - } -} - -static void mhp_hookcbrk(int argc, char *argv[]) -{ - int on = 1; - if (argc > 1 && strcmp(argv[1], "off") == 0) - on = 0; - do_hookcbrk(on); -} - -static void c_nothr(int nthr) -{ - int cnt = coopth_get_thread_count_in_process_vm86(); - mhp_printf("no thrs %i, %i in cur process\n", nthr, cnt); - if (cnt) - return; - coopth_set_nothread_notifier(NULL); -} - -static void mhp_dosbreak (int argc, char *argv[]) -{ - int cnt = coopth_get_thread_count_in_process_vm86(); - if (cnt == 0) { - mhp_printf("no dos call to break\n"); - return; - } - mhp_printf("breaking %i coopthreads\n", cnt); - coopth_set_nothread_notifier(c_nothr); - - /* order of below 2 lines matters and should be inverse */ - coopth_start(ic_tid, (void*)(uintptr_t)3); - do_hookcbrk(1); -} - static int mhp_check_regex(char *line) { int rx, hit; @@ -3019,15 +2783,3 @@ void mhp_regex(const char *fmt, va_list args) } } -void mhpdbgc_init(void) -{ - emu_hlt_t hlt_hdlr = HLT_INITIALIZER; - hlt_hdlr.name = "mhpdbg cbreak"; - hlt_hdlr.func = cbrk_handler; - cbrk_handler_hlt = hlt_register_handler_vm86(hlt_hdlr); - setbrk_tid = coopth_create("injchar thr", mhp_setbrk_thr); - coopth_set_ctx_handlers(setbrk_tid, sig_ctx_prepare, sig_ctx_restore, NULL); - - ic_tid = coopth_create("injchar thr", mhp_injchar_thr); - coopth_set_ctx_handlers(ic_tid, sig_ctx_prepare, sig_ctx_restore, NULL); -} diff --git a/src/plugin/dj64/Makefile b/src/plugin/dj64/Makefile deleted file mode 100644 index ce7661b..0000000 --- a/src/plugin/dj64/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# -# (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". -# -# for details see file COPYING in the DOSEMU distribution -# - -top_builddir=../../.. -include ../plugins.mak - -ALL_CFLAGS += $(DL_CFLAGS) -CFILES = djdev64.c coff.c elf.c util.c stub.c -ifeq ($(USE_DL_PLUGINS),1) -all: $(BINPATH)/bin/libplugin_dj64.so -ALL_CFLAGS += -fPIC -endif - -include $(REALTOPDIR)/src/Makefile.common.post - -ifeq ($(USE_DL_PLUGINS),1) -$(BINPATH)/bin/libplugin_dj64.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(DJDEV64_LIBS) -endif diff --git a/src/plugin/dj64/Makefile.conf.in b/src/plugin/dj64/Makefile.conf.in deleted file mode 100644 index d3b7cd7..0000000 --- a/src/plugin/dj64/Makefile.conf.in +++ /dev/null @@ -1,10 +0,0 @@ -# -# (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". -# -# for details see file COPYING in the DOSEMU distribution -# -# Makefile.conf.in for DOSEMU -# -# This file is included by all Makefiles - -DJDEV64_LIBS:=@DJDEV64_LIBS@ diff --git a/src/plugin/dj64/coff.c b/src/plugin/dj64/coff.c deleted file mode 100644 index e7a37cb..0000000 --- a/src/plugin/dj64/coff.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * COFF loader. - * Copyright (C) 2023, stsp2@yandex.ru - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -#include -#include -#include -#include -#include -#include -#include -#include "util.h" -#include "coff.h" - -#define STUB_DEBUG 0 -#if STUB_DEBUG -#define stub_debug(...) printf(__VA_ARGS__) -#else -#define stub_debug(...) -#endif - -struct coff_header { - unsigned short f_magic; /* Magic number */ - unsigned short f_nscns; /* Number of Sections */ - int32_t f_timdat; /* Time & date stamp */ - int32_t f_symptr; /* File pointer to Symbol Table */ - int32_t f_nsyms; /* Number of Symbols */ - unsigned short f_opthdr; /* sizeof(Optional Header) */ - unsigned short f_flags; /* Flags */ -}; - -struct opt_header { - unsigned short magic; /* Magic Number */ - unsigned short vstamp; /* Version stamp */ - uint32_t tsize; /* Text size in bytes */ - uint32_t dsize; /* Initialised data size */ - uint32_t bsize; /* Uninitialised data size */ - uint32_t entry; /* Entry point */ - uint32_t text_start; /* Base of Text used for this file */ - uint32_t data_start; /* Base of Data used for this file */ -}; - -struct scn_header { - char s_name[8]; /* Section Name */ - int32_t s_paddr; /* Physical Address */ - int32_t s_vaddr; /* Virtual Address */ - int32_t s_size; /* Section Size in Bytes */ - int32_t s_scnptr; /* File offset to the Section data */ - int32_t s_relptr; /* File offset to the Relocation table for this Section */ - int32_t s_lnnoptr; /* File offset to the Line Number table for this Section */ - unsigned short s_nreloc; /* Number of Relocation table entries */ - unsigned short s_nlnno; /* Number of Line Number table entries */ - int32_t s_flags; /* Flags for this section */ -}; - -enum { SCT_TEXT, SCT_DATA, SCT_BSS, SCT_MAX }; - -static struct scn_header scns[SCT_MAX]; - -struct coff_h { - uint32_t length; - uint32_t entry; -}; - -static void read_section(char *buf, int ifile, long coffset, int sc) -{ - long bytes; - _dos_seek(ifile, coffset + scns[sc].s_scnptr, SEEK_SET); - bytes = _long_read(ifile, buf, scns[sc].s_vaddr, - scns[sc].s_size); - stub_debug("read returned %li\n", bytes); - if (bytes != scns[sc].s_size) { - fprintf(stderr, "err reading %i bytes, got %li\n", - scns[sc].s_size, bytes); -// _exit(EXIT_FAILURE); - } -} - -static void *read_coff_headers(int ifile) -{ - struct coff_header chdr; - struct opt_header ohdr; - struct coff_h *h; - int rc; - unsigned rd; - - rc = _dos_read(ifile, &chdr, sizeof(chdr), &rd); /* get the COFF header */ - if (rc || rd != sizeof(chdr)) { - fprintf(stderr, "bad COFF header\n"); - return NULL; - } - if (chdr.f_opthdr < sizeof(ohdr)) { - fprintf(stderr, "opt header size mismatch: %i %zi\n", - chdr.f_opthdr, sizeof(ohdr)); - return NULL; - } - rc = _dos_read(ifile, &ohdr, sizeof(ohdr), &rd); /* get the COFF opt header */ - if (rc || rd != sizeof(ohdr)) { - fprintf(stderr, "bad COFF opt header\n"); - return NULL; - } - if (chdr.f_opthdr > sizeof(ohdr)) - _dos_seek(ifile, chdr.f_opthdr - sizeof(ohdr), SEEK_CUR); - rc = _dos_read(ifile, scns, sizeof(scns[0]) * SCT_MAX, &rd); - if (rc || rd != sizeof(scns[0]) * SCT_MAX) { - fprintf(stderr, "failed to read section headers\n"); - return NULL; - } -#if STUB_DEBUG - for (int i = 0; i < SCT_MAX; i++) { - struct scn_header *h = &scns[i]; - stub_debug("Section %s pa 0x%lx va 0x%lx size 0x%lx foffs 0x%lx\n", - h->s_name, h->s_paddr, h->s_vaddr, h->s_size, h->s_scnptr); - } -#endif - h = malloc(sizeof(*h)); - assert(h); - h->entry = ohdr.entry; - h->length = scns[SCT_BSS].s_vaddr + scns[SCT_BSS].s_size; - return h; -} - -static uint32_t get_coff_va(void *handle) -{ - return 0; // ??? -} - -static uint32_t get_coff_length(void *handle) -{ - struct coff_h *h = handle; - return h->length; -} - -static uint32_t get_coff_entry(void *handle) -{ - struct coff_h *h = handle; - return h->entry; -} - -static void read_coff_sections(void *handle, char *ptr, int ifile, - uint32_t offset) -{ - struct coff_h *h = handle; - read_section(ptr, ifile, offset, SCT_TEXT); - read_section(ptr, ifile, offset, SCT_DATA); - memset(ptr + scns[SCT_BSS].s_vaddr, 0, scns[SCT_BSS].s_size + - (scns[SCT_BSS].s_size & 1)); - free(h); -} - - -struct ldops coff_ops = { - read_coff_headers, - get_coff_va, - get_coff_length, - get_coff_entry, - read_coff_sections, -}; diff --git a/src/plugin/dj64/coff.h b/src/plugin/dj64/coff.h deleted file mode 100644 index 74ed257..0000000 --- a/src/plugin/dj64/coff.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef COFF_H -#define COFF_H - -#include "stub.h" - -extern struct ldops coff_ops; - -#endif diff --git a/src/plugin/dj64/config/plugin_config.h b/src/plugin/dj64/config/plugin_config.h deleted file mode 100644 index 2e3e61a..0000000 --- a/src/plugin/dj64/config/plugin_config.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef USE_DJDEV64 -#define USE_DJDEV64 1 - -struct pm_regs; -struct djdev64_ops { - int (*open)(const char *path); - void (*close)(int handle); - unsigned (*call)(int handle); - unsigned (*ctrl)(int handle); - unsigned (*stub)(void); -}; - -void register_djdev64(const struct djdev64_ops *ops); - -#endif diff --git a/src/plugin/dj64/configure.ac b/src/plugin/dj64/configure.ac deleted file mode 100644 index 62fb427..0000000 --- a/src/plugin/dj64/configure.ac +++ /dev/null @@ -1,6 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -AC_INIT -AC_CONFIG_FILES([Makefile.conf]) -PKG_CHECK_MODULES([DJDEV64], [djdev64],, - AC_MSG_ERROR([dj64 development libs not found])) -AC_OUTPUT diff --git a/src/plugin/dj64/djdev64.c b/src/plugin/dj64/djdev64.c deleted file mode 100644 index 5caf059..0000000 --- a/src/plugin/dj64/djdev64.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2024 stsp - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include -#include "init.h" -#include "emu.h" -#include "cpu-emu.h" -#include "dosemu_debug.h" -#include "utilities.h" -#include "emudpmi.h" -#include "msdoshlp.h" -#include "coopth.h" -#include "coopth_pm.h" -#include "hlt.h" -#include "dos2linux.h" -#include "stub_ex.h" - -#if DJ64_API_VER != 4 -#error wrong dj64 version -#endif - -static unsigned ctrl_off; -#define HNDL_MAX 5 -static struct dos_helper_s call_hlp[HNDL_MAX]; -static struct dos_helper_s stub_hlp; -#define MAX_CLNUP_TIDS 5 -static int clnup_tids[HNDL_MAX][MAX_CLNUP_TIDS]; -static int num_clnup_tids[HNDL_MAX]; - -static void call_thr(void *arg); -static void stub_thr(void *arg); -static void ctrl_hlt(Bit16u offs, void *sc, void *arg); -static void do_retf(cpuctx_t *scp); - -static uint8_t *dj64_addr2ptr(uint32_t addr) -{ - return dosaddr_to_unixaddr(addr); -} - -static uint8_t *dj64_addr2ptr2(uint32_t addr, uint32_t len) -{ - e_invalidate(addr, len); - return dosaddr_to_unixaddr(addr); -} - -static uint32_t dj64_ptr2addr(const uint8_t *ptr) -{ - if (ptr >= MEM_BASE32(config.dpmi_base) && - ptr < MEM_BASE32(config.dpmi_base + dpmi_mem_size())) - return DOSADDR_REL(ptr); - dosemu_error("bad ptr2addr %p\n", ptr); - return -1; -} - -static int dj64_dos_ptr(const uint8_t *ptr) -{ - if ((ptr >= MEM_BASE32(config.dpmi_base) && - ptr < MEM_BASE32(config.dpmi_base + dpmi_mem_size())) || - (ptr >= MEM_BASE32(0) && ptr < MEM_BASE32(LOWMEM_SIZE + HMASIZE))) - return 1; - return 0; -} - -static void dj64_print(int prio, const char *format, va_list ap) -{ - switch(prio) { - case DJ64_PRINT_TERMINAL: - vfprintf(stderr, format, ap); - break; - case DJ64_PRINT_LOG: - if (debug_level('J')) { - log_printf(-1, "dj64: "); - vlog_printf(-1, format, ap); - } - break; - case DJ64_PRINT_SCREEN: - p_direct_vstr(format, ap); - break; - } -} - -static void copy_stk(cpuctx_t *scp, uint8_t *sp, uint8_t len) -{ - uint8_t *stk; - if (!len) - return; - _esp -= len; - stk = SEL_ADR(_ss, _esp); - memcpy(stk, sp, len); -} - -static void copy_gp(cpuctx_t *scp, dpmi_regs *src) -{ -#define CP_R(r) _##r = src->r - CP_R(eax); - CP_R(ebx); - CP_R(ecx); - CP_R(edx); - CP_R(esi); - CP_R(edi); - CP_R(ebp); -#undef CP_R -} - -static void bcopy_gp(dpmi_regs *dst, cpuctx_t *scp) -{ -#define CP_R(r) dst->r = _##r - CP_R(eax); - CP_R(ebx); - CP_R(ecx); - CP_R(edx); - CP_R(esi); - CP_R(edi); - CP_R(ebp); -#undef CP_R -} - -static void do_callf(cpuctx_t *scp, dpmi_paddr pma) -{ - unsigned int *ssp = SEL_ADR(_ss, _esp); - *--ssp = _cs; - *--ssp = _eip; - _esp -= 8; - - _cs = pma.selector; - _eip = pma.offset32; -} - -static int dj64_asm_call(dpmi_regs *regs, dpmi_paddr pma, uint8_t *sp, - uint8_t len) -{ - int rc; - int ret = ASM_CALL_OK; - cpuctx_t *scp = coopth_pop_user_data_cur(); - copy_stk(scp, sp, len); - copy_gp(scp, regs); -// J_printf("asm call to 0x%x:0x%x\n", pma.selector, pma.offset32); - do_callf(scp, pma); - coopth_cancel_disable_cur(); - rc = coopth_sched(); - /* re-enable cancellability only if it was not canceled already */ - if (rc == 0) { - coopth_cancel_enable_cur(); - bcopy_gp(regs, scp); - coopth_push_user_data_cur(scp); - } else { - ret = ASM_CALL_ABORT; - } - return ret; -} - -static void dj64_asm_noret(dpmi_regs *regs, dpmi_paddr pma, uint8_t *sp, - uint8_t len) -{ - struct pmaddr_s abt = doshlp_get_abort_helper(); - cpuctx_t *scp = coopth_pop_user_data_cur(); - coopth_leave_pm(scp); - copy_stk(scp, sp, len); - copy_gp(scp, regs); - _cs = abt.selector; - _eip = abt.offset; - do_callf(scp, pma); -} - -static uint8_t *dj64_inc_esp(uint32_t len) -{ - cpuctx_t *scp = coopth_pop_user_data_cur(); - _esp += len; - coopth_push_user_data_cur(scp); - return SEL_ADR(_ss, _esp); -} - -const struct dj64_api api = { - .addr2ptr = dj64_addr2ptr, - .addr2ptr2 = dj64_addr2ptr2, - .ptr2addr = dj64_ptr2addr, - .print = dj64_print, - .asm_call = dj64_asm_call, - .asm_noret = dj64_asm_noret, - .inc_esp = dj64_inc_esp, - .is_dos_ptr = dj64_dos_ptr, -}; - -static int do_open(const char *path) -{ - int ret = djdev64_open(path, &api, DJ64_API_VER); - if (ret == -1) - return ret; - assert(ret < HNDL_MAX); - if (!call_hlp[ret].tid) - doshlp_setup(&call_hlp[ret], "dj64 call", call_thr, do_retf); - if (!ctrl_off) { - emu_hlt_t hlt_hdlr = HLT_INITIALIZER; - hlt_hdlr.name = "dj64 ctrl"; - hlt_hdlr.func = ctrl_hlt; - ctrl_off = hlt_register_handler_pm(hlt_hdlr); - } - return ret; -} - -static void do_close(int handle) -{ - while (num_clnup_tids[handle]) { - int i = num_clnup_tids[handle] - 1; - int tid = clnup_tids[handle][i]; - coopth_cancel(tid); - if (coopth_get_tid() == tid) { - num_clnup_tids[handle]--; // skip own thread - continue; - } - coopth_unsafe_detach(tid, __FILE__); - } - djdev64_close(handle); -} - -static void stub_thr(void *arg) -{ - cpuctx_t *scp = arg; - cpuctx_t scp2 = *scp; - int argc = _ecx; - unsigned *argp = SEL_ADR(_ds, _edx); - char **argv = alloca((argc + 1) * sizeof(char *)); - int envc = _ebx; - unsigned *envpp = SEL_ADR(_ds, _esi); - char **envp = alloca((envc + 1) * sizeof(char *)); - int i; - for (i = 0; i < argc; i++) - argv[i] = SEL_ADR(_ds, argp[i]); - argv[i] = NULL; - for (i = 0; i < envc; i++) - envp[i] = SEL_ADR(_ds, envpp[i]); - envp[i] = NULL; - - djstub_main(argc, argv, envp, _eax, &scp2); - coopth_leave_pm(scp); - scp2.esp += 8; - assert(_esp == scp2.esp); - *scp = scp2; -} - -static unsigned call_entry(int handle) -{ - return call_hlp[handle].entry; -} - -static unsigned ctrl_entry(int handle) -{ - return ctrl_off; -} - -static unsigned stub_entry(void) -{ - if (!stub_hlp.tid) - doshlp_setup(&stub_hlp, "dj64 stub", stub_thr, do_retf); - return stub_hlp.entry; -} - -static const struct djdev64_ops ops = { - .open = do_open, - .close = do_close, - .call = call_entry, - .ctrl = ctrl_entry, - .stub = stub_entry, -}; - -static void call_thr(void *arg) -{ - cpuctx_t *scp = arg; - unsigned char *sp = SEL_ADR(_ss, _edx); // sp in edx - int handle = _eax; - if (handle >= HNDL_MAX) { - error("DJ64: bad handle %x\n", handle); - return; - } - J_printf("DJ64: djdev64_call(%i) %s\n", handle, DPMI_show_state(scp)); - coopth_push_user_data_cur(scp); - assert(num_clnup_tids[handle] < MAX_CLNUP_TIDS); - clnup_tids[handle][num_clnup_tids[handle]++] = coopth_get_tid(); - djdev64_call(handle, _ebx, _ecx, _esi, sp); - num_clnup_tids[handle]--; -} - -static void do_retf(cpuctx_t *scp) -{ - unsigned int *ssp = SEL_ADR(_ss, _esp); - _eip = *ssp++; - _cs = *ssp++; - _esp += 8; -} - -static void ctrl_hlt(Bit16u offs, void *sc, void *arg) -{ - cpuctx_t *scp = sc; - unsigned char *sp = SEL_ADR(_ss, _edx); // sp in edx - do_retf(scp); - J_printf("DJ64: djdev64_ctrl() %s\n", DPMI_show_state(scp)); - djdev64_ctrl(_eax, _ebx, _ecx, _esi, sp); -} - -CONSTRUCTOR(static void djdev64_init(void)) -{ - register_djdev64(&ops); -} diff --git a/src/plugin/dj64/elf.c b/src/plugin/dj64/elf.c deleted file mode 100644 index 2cd46d6..0000000 --- a/src/plugin/dj64/elf.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * ELF loader. - * Copyright (C) 2023, @stsp - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -#include -#include -#include -#include -#include -#include -#include -#include "util.h" -#include "stub.h" -#include "elf.h" -#include "elfp.h" - -#define STUB_DEBUG 0 -#if STUB_DEBUG -#define stub_debug(...) printf(__VA_ARGS__) -#else -#define stub_debug(...) -#endif - -struct elf_h { - uint32_t va; - uint32_t length; - uint32_t entry; - int phnum; - Elf32_Phdr phdr[0]; -}; - -static void *read_elf_headers(int ifile) -{ - Elf32_Ehdr ehdr; - struct elf_h *h; - int i, rc; - unsigned rd; - long beg = 0, end = 0; - - rc = _dos_read(ifile, &ehdr, sizeof(ehdr), &rd); /* get the ELF header */ - if (rc || rd != sizeof(ehdr)) { - fprintf(stderr, "cant read ELF header\n"); - return NULL; - } - if (memcmp(&ehdr.e_ident, ELFMAG, SELFMAG) || - ehdr.e_ehsize != sizeof(ehdr) || - ehdr.e_phentsize != sizeof(Elf32_Phdr)) { - fprintf(stderr, "bad ELF header\n"); - return NULL; - } - if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { - fprintf(stderr, "bad ELF class %i\n", ehdr.e_ident[EI_CLASS]); - return NULL; - } - if (ehdr.e_phoff > sizeof(ehdr)) - _dos_seek(ifile, ehdr.e_phoff - sizeof(ehdr), SEEK_CUR); - h = malloc(sizeof(*h) + sizeof(Elf32_Phdr) * ehdr.e_phnum); - assert(h); - rc = _dos_read(ifile, h->phdr, sizeof(Elf32_Phdr) * ehdr.e_phnum, &rd); - if (rc || rd != sizeof(Elf32_Phdr) * ehdr.e_phnum) { - fprintf(stderr, "can't read phdr\n"); - return NULL; - } - h->phnum = ehdr.e_phnum; - for (i = 0; i < ehdr.e_phnum; i++) { - Elf32_Phdr *phdr = &h->phdr[i]; - if (phdr->p_type != PT_LOAD) - continue; - if (phdr->p_align != 4096) { - fprintf(stderr, "unsupported ELF alignment %i\n", phdr->p_align); - return NULL; - } - if (phdr->p_vaddr < beg || !beg) - beg = phdr->p_vaddr; - if (phdr->p_vaddr + phdr->p_memsz > end) - end = phdr->p_vaddr + phdr->p_memsz; -#if STUB_DEBUG - stub_debug("PHDR pa 0x%lx va 0x%lx size 0x%lx foffs 0x%lx\n", - phdr->p_paddr, phdr->p_vaddr, phdr->p_filesz, phdr->p_offset); -#endif - } - h->entry = ehdr.e_entry; - h->va = beg; - h->length = end - beg; - return h; -} - -static uint32_t get_elf_length(void *handle) -{ - struct elf_h *h = handle; - return h->length; -} - -static uint32_t get_elf_entry(void *handle) -{ - struct elf_h *h = handle; - return h->entry; -} - -static uint32_t get_elf_va(void *handle) -{ - struct elf_h *h = handle; - return h->va; -} - -static void read_elf_sections(void *handle, char *ptr, int ifile, - uint32_t offset) -{ - struct elf_h *h = handle; - int i; - - for (i = 0; i < h->phnum; i++) { - Elf32_Phdr *phdr = &h->phdr[i]; - long bytes; - - if (phdr->p_type != PT_LOAD) - continue; - _dos_seek(ifile, offset + phdr->p_offset, SEEK_SET); - bytes = _long_read(ifile, ptr, phdr->p_vaddr, phdr->p_filesz); - stub_debug("read returned %li\n", bytes); - if (bytes != phdr->p_filesz) { - fprintf(stderr, "err reading %i bytes, got %li\n", - phdr->p_filesz, bytes); -// _exit(EXIT_FAILURE); - goto fr; - } - if (phdr->p_memsz > phdr->p_filesz) { - uint32_t len = phdr->p_memsz - phdr->p_filesz; - len += len & 1; // word-align - memset(ptr + phdr->p_vaddr + phdr->p_filesz, 0, len); - } - } -fr: - free(h); -} - - -struct ldops elf_ops = { - read_elf_headers, - get_elf_va, - get_elf_length, - get_elf_entry, - read_elf_sections, -}; diff --git a/src/plugin/dj64/elf.h b/src/plugin/dj64/elf.h deleted file mode 100644 index 3732ac7..0000000 --- a/src/plugin/dj64/elf.h +++ /dev/null @@ -1,750 +0,0 @@ -/* This file defines standard ELF types, structures, and macros. - Copyright (C) 1995-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _ELF_H -#define _ELF_H 1 - -/* Standard ELF types. */ - -#include - -/* Type for a 16-bit quantity. */ -typedef uint16_t Elf32_Half; -typedef uint16_t Elf64_Half; - -/* Types for signed and unsigned 32-bit quantities. */ -typedef uint32_t Elf32_Word; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf64_Word; -typedef int32_t Elf64_Sword; - -/* Types for signed and unsigned 64-bit quantities. */ -typedef uint64_t Elf32_Xword; -typedef int64_t Elf32_Sxword; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; - -/* Type of addresses. */ -typedef uint32_t Elf32_Addr; -typedef uint64_t Elf64_Addr; - -/* Type of file offsets. */ -typedef uint32_t Elf32_Off; -typedef uint64_t Elf64_Off; - -/* Type for section indices, which are 16-bit quantities. */ -typedef uint16_t Elf32_Section; -typedef uint16_t Elf64_Section; - -/* Type for version symbol information. */ -typedef Elf32_Half Elf32_Versym; -typedef Elf64_Half Elf64_Versym; - - -/* The ELF file header. This appears at the start of every ELF file. */ - -#define EI_NIDENT (16) - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf32_Half e_type; /* Object file type */ - Elf32_Half e_machine; /* Architecture */ - Elf32_Word e_version; /* Object file version */ - Elf32_Addr e_entry; /* Entry point virtual address */ - Elf32_Off e_phoff; /* Program header table file offset */ - Elf32_Off e_shoff; /* Section header table file offset */ - Elf32_Word e_flags; /* Processor-specific flags */ - Elf32_Half e_ehsize; /* ELF header size in bytes */ - Elf32_Half e_phentsize; /* Program header table entry size */ - Elf32_Half e_phnum; /* Program header table entry count */ - Elf32_Half e_shentsize; /* Section header table entry size */ - Elf32_Half e_shnum; /* Section header table entry count */ - Elf32_Half e_shstrndx; /* Section header string table index */ -} Elf32_Ehdr; - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf64_Half e_type; /* Object file type */ - Elf64_Half e_machine; /* Architecture */ - Elf64_Word e_version; /* Object file version */ - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; /* Processor-specific flags */ - Elf64_Half e_ehsize; /* ELF header size in bytes */ - Elf64_Half e_phentsize; /* Program header table entry size */ - Elf64_Half e_phnum; /* Program header table entry count */ - Elf64_Half e_shentsize; /* Section header table entry size */ - Elf64_Half e_shnum; /* Section header table entry count */ - Elf64_Half e_shstrndx; /* Section header string table index */ -} Elf64_Ehdr; - -/* Fields in the e_ident array. The EI_* macros are indices into the - array. The macros under each EI_* macro are the values the byte - may have. */ - -#define EI_MAG0 0 /* File identification byte 0 index */ -#define ELFMAG0 0x7f /* Magic number byte 0 */ - -#define EI_MAG1 1 /* File identification byte 1 index */ -#define ELFMAG1 'E' /* Magic number byte 1 */ - -#define EI_MAG2 2 /* File identification byte 2 index */ -#define ELFMAG2 'L' /* Magic number byte 2 */ - -#define EI_MAG3 3 /* File identification byte 3 index */ -#define ELFMAG3 'F' /* Magic number byte 3 */ - -/* Conglomeration of the identification bytes, for easy testing as a word. */ -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define EI_CLASS 4 /* File class byte index */ -#define ELFCLASSNONE 0 /* Invalid class */ -#define ELFCLASS32 1 /* 32-bit objects */ -#define ELFCLASS64 2 /* 64-bit objects */ -#define ELFCLASSNUM 3 - -#define EI_DATA 5 /* Data encoding byte index */ -#define ELFDATANONE 0 /* Invalid data encoding */ -#define ELFDATA2LSB 1 /* 2's complement, little endian */ -#define ELFDATA2MSB 2 /* 2's complement, big endian */ -#define ELFDATANUM 3 - -#define EI_VERSION 6 /* File version byte index */ - /* Value must be EV_CURRENT */ - -#define EI_OSABI 7 /* OS ABI identification */ -#define ELFOSABI_NONE 0 /* UNIX System V ABI */ -#define ELFOSABI_SYSV 0 /* Alias. */ -#define ELFOSABI_HPUX 1 /* HP-UX */ -#define ELFOSABI_NETBSD 2 /* NetBSD. */ -#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */ -#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */ -#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ -#define ELFOSABI_AIX 7 /* IBM AIX. */ -#define ELFOSABI_IRIX 8 /* SGI Irix. */ -#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ -#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ -#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ -#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ -#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ -#define ELFOSABI_ARM 97 /* ARM */ -#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ - -#define EI_ABIVERSION 8 /* ABI version */ - -#define EI_PAD 9 /* Byte index of padding bytes */ - -/* Legal values for e_type (object file type). */ - -#define ET_NONE 0 /* No file type */ -#define ET_REL 1 /* Relocatable file */ -#define ET_EXEC 2 /* Executable file */ -#define ET_DYN 3 /* Shared object file */ -#define ET_CORE 4 /* Core file */ -#define ET_NUM 5 /* Number of defined types */ -#define ET_LOOS 0xfe00 /* OS-specific range start */ -#define ET_HIOS 0xfeff /* OS-specific range end */ -#define ET_LOPROC 0xff00 /* Processor-specific range start */ -#define ET_HIPROC 0xffff /* Processor-specific range end */ - -/* Legal values for e_machine (architecture). */ - -#define EM_NONE 0 /* No machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SUN SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola m68k family */ -#define EM_88K 5 /* Motorola m88k family */ -#define EM_IAMCU 6 /* Intel MCU */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS R3000 big-endian */ -#define EM_S370 9 /* IBM System/370 */ -#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ - /* reserved 11-14 */ -#define EM_PARISC 15 /* HPPA */ - /* reserved 16 */ -#define EM_VPP500 17 /* Fujitsu VPP500 */ -#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ -#define EM_960 19 /* Intel 80960 */ -#define EM_PPC 20 /* PowerPC */ -#define EM_PPC64 21 /* PowerPC 64-bit */ -#define EM_S390 22 /* IBM S390 */ -#define EM_SPU 23 /* IBM SPU/SPC */ - /* reserved 24-35 */ -#define EM_V800 36 /* NEC V800 series */ -#define EM_FR20 37 /* Fujitsu FR20 */ -#define EM_RH32 38 /* TRW RH-32 */ -#define EM_RCE 39 /* Motorola RCE */ -#define EM_ARM 40 /* ARM */ -#define EM_FAKE_ALPHA 41 /* Digital Alpha */ -#define EM_SH 42 /* Hitachi SH */ -#define EM_SPARCV9 43 /* SPARC v9 64-bit */ -#define EM_TRICORE 44 /* Siemens Tricore */ -#define EM_ARC 45 /* Argonaut RISC Core */ -#define EM_H8_300 46 /* Hitachi H8/300 */ -#define EM_H8_300H 47 /* Hitachi H8/300H */ -#define EM_H8S 48 /* Hitachi H8S */ -#define EM_H8_500 49 /* Hitachi H8/500 */ -#define EM_IA_64 50 /* Intel Merced */ -#define EM_MIPS_X 51 /* Stanford MIPS-X */ -#define EM_COLDFIRE 52 /* Motorola Coldfire */ -#define EM_68HC12 53 /* Motorola M68HC12 */ -#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */ -#define EM_PCP 55 /* Siemens PCP */ -#define EM_NCPU 56 /* Sony nCPU embedded RISC */ -#define EM_NDR1 57 /* Denso NDR1 microprocessor */ -#define EM_STARCORE 58 /* Motorola Start*Core processor */ -#define EM_ME16 59 /* Toyota ME16 processor */ -#define EM_ST100 60 /* STMicroelectronic ST100 processor */ -#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam */ -#define EM_X86_64 62 /* AMD x86-64 architecture */ -#define EM_PDSP 63 /* Sony DSP Processor */ -#define EM_PDP10 64 /* Digital PDP-10 */ -#define EM_PDP11 65 /* Digital PDP-11 */ -#define EM_FX66 66 /* Siemens FX66 microcontroller */ -#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ -#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ -#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ -#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ -#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ -#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ -#define EM_SVX 73 /* Silicon Graphics SVx */ -#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ -#define EM_VAX 75 /* Digital VAX */ -#define EM_CRIS 76 /* Axis Communications 32-bit emb.proc */ -#define EM_JAVELIN 77 /* Infineon Technologies 32-bit emb.proc */ -#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ -#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ -#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc */ -#define EM_HUANY 81 /* Harvard University machine-independent object files */ -#define EM_PRISM 82 /* SiTera Prism */ -#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ -#define EM_FR30 84 /* Fujitsu FR30 */ -#define EM_D10V 85 /* Mitsubishi D10V */ -#define EM_D30V 86 /* Mitsubishi D30V */ -#define EM_V850 87 /* NEC v850 */ -#define EM_M32R 88 /* Mitsubishi M32R */ -#define EM_MN10300 89 /* Matsushita MN10300 */ -#define EM_MN10200 90 /* Matsushita MN10200 */ -#define EM_PJ 91 /* picoJava */ -#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ -#define EM_ARC_COMPACT 93 /* ARC International ARCompact */ -#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ -#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore */ -#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Proc */ -#define EM_NS32K 97 /* National Semi. 32000 */ -#define EM_TPC 98 /* Tenor Network TPC */ -#define EM_SNP1K 99 /* Trebia SNP 1000 */ -#define EM_ST200 100 /* STMicroelectronics ST200 */ -#define EM_IP2K 101 /* Ubicom IP2xxx */ -#define EM_MAX 102 /* MAX processor */ -#define EM_CR 103 /* National Semi. CompactRISC */ -#define EM_F2MC16 104 /* Fujitsu F2MC16 */ -#define EM_MSP430 105 /* Texas Instruments msp430 */ -#define EM_BLACKFIN 106 /* Analog Devices Blackfin DSP */ -#define EM_SE_C33 107 /* Seiko Epson S1C33 family */ -#define EM_SEP 108 /* Sharp embedded microprocessor */ -#define EM_ARCA 109 /* Arca RISC */ -#define EM_UNICORE 110 /* PKU-Unity & MPRC Peking Uni. mc series */ -#define EM_EXCESS 111 /* eXcess configurable cpu */ -#define EM_DXP 112 /* Icera Semi. Deep Execution Processor */ -#define EM_ALTERA_NIOS2 113 /* Altera Nios II */ -#define EM_CRX 114 /* National Semi. CompactRISC CRX */ -#define EM_XGATE 115 /* Motorola XGATE */ -#define EM_C166 116 /* Infineon C16x/XC16x */ -#define EM_M16C 117 /* Renesas M16C */ -#define EM_DSPIC30F 118 /* Microchip Technology dsPIC30F */ -#define EM_CE 119 /* Freescale Communication Engine RISC */ -#define EM_M32C 120 /* Renesas M32C */ - /* reserved 121-130 */ -#define EM_TSK3000 131 /* Altium TSK3000 */ -#define EM_RS08 132 /* Freescale RS08 */ -#define EM_SHARC 133 /* Analog Devices SHARC family */ -#define EM_ECOG2 134 /* Cyan Technology eCOG2 */ -#define EM_SCORE7 135 /* Sunplus S+core7 RISC */ -#define EM_DSP24 136 /* New Japan Radio (NJR) 24-bit DSP */ -#define EM_VIDEOCORE3 137 /* Broadcom VideoCore III */ -#define EM_LATTICEMICO32 138 /* RISC for Lattice FPGA */ -#define EM_SE_C17 139 /* Seiko Epson C17 */ -#define EM_TI_C6000 140 /* Texas Instruments TMS320C6000 DSP */ -#define EM_TI_C2000 141 /* Texas Instruments TMS320C2000 DSP */ -#define EM_TI_C5500 142 /* Texas Instruments TMS320C55x DSP */ -#define EM_TI_ARP32 143 /* Texas Instruments App. Specific RISC */ -#define EM_TI_PRU 144 /* Texas Instruments Prog. Realtime Unit */ - /* reserved 145-159 */ -#define EM_MMDSP_PLUS 160 /* STMicroelectronics 64bit VLIW DSP */ -#define EM_CYPRESS_M8C 161 /* Cypress M8C */ -#define EM_R32C 162 /* Renesas R32C */ -#define EM_TRIMEDIA 163 /* NXP Semi. TriMedia */ -#define EM_QDSP6 164 /* QUALCOMM DSP6 */ -#define EM_8051 165 /* Intel 8051 and variants */ -#define EM_STXP7X 166 /* STMicroelectronics STxP7x */ -#define EM_NDS32 167 /* Andes Tech. compact code emb. RISC */ -#define EM_ECOG1X 168 /* Cyan Technology eCOG1X */ -#define EM_MAXQ30 169 /* Dallas Semi. MAXQ30 mc */ -#define EM_XIMO16 170 /* New Japan Radio (NJR) 16-bit DSP */ -#define EM_MANIK 171 /* M2000 Reconfigurable RISC */ -#define EM_CRAYNV2 172 /* Cray NV2 vector architecture */ -#define EM_RX 173 /* Renesas RX */ -#define EM_METAG 174 /* Imagination Tech. META */ -#define EM_MCST_ELBRUS 175 /* MCST Elbrus */ -#define EM_ECOG16 176 /* Cyan Technology eCOG16 */ -#define EM_CR16 177 /* National Semi. CompactRISC CR16 */ -#define EM_ETPU 178 /* Freescale Extended Time Processing Unit */ -#define EM_SLE9X 179 /* Infineon Tech. SLE9X */ -#define EM_L10M 180 /* Intel L10M */ -#define EM_K10M 181 /* Intel K10M */ - /* reserved 182 */ -#define EM_AARCH64 183 /* ARM AARCH64 */ - /* reserved 184 */ -#define EM_AVR32 185 /* Amtel 32-bit microprocessor */ -#define EM_STM8 186 /* STMicroelectronics STM8 */ -#define EM_TILE64 187 /* Tilera TILE64 */ -#define EM_TILEPRO 188 /* Tilera TILEPro */ -#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */ -#define EM_CUDA 190 /* NVIDIA CUDA */ -#define EM_TILEGX 191 /* Tilera TILE-Gx */ -#define EM_CLOUDSHIELD 192 /* CloudShield */ -#define EM_COREA_1ST 193 /* KIPO-KAIST Core-A 1st gen. */ -#define EM_COREA_2ND 194 /* KIPO-KAIST Core-A 2nd gen. */ -#define EM_ARCV2 195 /* Synopsys ARCv2 ISA. */ -#define EM_OPEN8 196 /* Open8 RISC */ -#define EM_RL78 197 /* Renesas RL78 */ -#define EM_VIDEOCORE5 198 /* Broadcom VideoCore V */ -#define EM_78KOR 199 /* Renesas 78KOR */ -#define EM_56800EX 200 /* Freescale 56800EX DSC */ -#define EM_BA1 201 /* Beyond BA1 */ -#define EM_BA2 202 /* Beyond BA2 */ -#define EM_XCORE 203 /* XMOS xCORE */ -#define EM_MCHP_PIC 204 /* Microchip 8-bit PIC(r) */ -#define EM_INTELGT 205 /* Intel Graphics Technology */ - /* reserved 206-209 */ -#define EM_KM32 210 /* KM211 KM32 */ -#define EM_KMX32 211 /* KM211 KMX32 */ -#define EM_EMX16 212 /* KM211 KMX16 */ -#define EM_EMX8 213 /* KM211 KMX8 */ -#define EM_KVARC 214 /* KM211 KVARC */ -#define EM_CDP 215 /* Paneve CDP */ -#define EM_COGE 216 /* Cognitive Smart Memory Processor */ -#define EM_COOL 217 /* Bluechip CoolEngine */ -#define EM_NORC 218 /* Nanoradio Optimized RISC */ -#define EM_CSR_KALIMBA 219 /* CSR Kalimba */ -#define EM_Z80 220 /* Zilog Z80 */ -#define EM_VISIUM 221 /* Controls and Data Services VISIUMcore */ -#define EM_FT32 222 /* FTDI Chip FT32 */ -#define EM_MOXIE 223 /* Moxie processor */ -#define EM_AMDGPU 224 /* AMD GPU */ - /* reserved 225-242 */ -#define EM_RISCV 243 /* RISC-V */ - -#define EM_BPF 247 /* Linux BPF -- in-kernel virtual machine */ -#define EM_CSKY 252 /* C-SKY */ -#define EM_LOONGARCH 258 /* LoongArch */ - -#define EM_NUM 259 - -/* Old spellings/synonyms. */ - -#define EM_ARC_A5 EM_ARC_COMPACT - -/* If it is necessary to assign new unofficial EM_* values, please - pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the - chances of collision with official or non-GNU unofficial values. */ - -#define EM_ALPHA 0x9026 - -/* Legal values for e_version (version). */ - -#define EV_NONE 0 /* Invalid ELF version */ -#define EV_CURRENT 1 /* Current version */ -#define EV_NUM 2 - -/* Section header. */ - -typedef struct -{ - Elf32_Word sh_name; /* Section name (string tbl index) */ - Elf32_Word sh_type; /* Section type */ - Elf32_Word sh_flags; /* Section flags */ - Elf32_Addr sh_addr; /* Section virtual addr at execution */ - Elf32_Off sh_offset; /* Section file offset */ - Elf32_Word sh_size; /* Section size in bytes */ - Elf32_Word sh_link; /* Link to another section */ - Elf32_Word sh_info; /* Additional section information */ - Elf32_Word sh_addralign; /* Section alignment */ - Elf32_Word sh_entsize; /* Entry size if section holds table */ -} Elf32_Shdr; - -typedef struct -{ - Elf64_Word sh_name; /* Section name (string tbl index) */ - Elf64_Word sh_type; /* Section type */ - Elf64_Xword sh_flags; /* Section flags */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Section size in bytes */ - Elf64_Word sh_link; /* Link to another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -} Elf64_Shdr; - -/* Special section indices. */ - -#define SHN_UNDEF 0 /* Undefined section */ -#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ -#define SHN_LOPROC 0xff00 /* Start of processor-specific */ -#define SHN_BEFORE 0xff00 /* Order section before all others - (Solaris). */ -#define SHN_AFTER 0xff01 /* Order section after all others - (Solaris). */ -#define SHN_HIPROC 0xff1f /* End of processor-specific */ -#define SHN_LOOS 0xff20 /* Start of OS-specific */ -#define SHN_HIOS 0xff3f /* End of OS-specific */ -#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ -#define SHN_COMMON 0xfff2 /* Associated symbol is common */ -#define SHN_XINDEX 0xffff /* Index is in extra table. */ -#define SHN_HIRESERVE 0xffff /* End of reserved indices */ - -/* Legal values for sh_type (section type). */ - -#define SHT_NULL 0 /* Section header table entry unused */ -#define SHT_PROGBITS 1 /* Program data */ -#define SHT_SYMTAB 2 /* Symbol table */ -#define SHT_STRTAB 3 /* String table */ -#define SHT_RELA 4 /* Relocation entries with addends */ -#define SHT_HASH 5 /* Symbol hash table */ -#define SHT_DYNAMIC 6 /* Dynamic linking information */ -#define SHT_NOTE 7 /* Notes */ -#define SHT_NOBITS 8 /* Program space with no data (bss) */ -#define SHT_REL 9 /* Relocation entries, no addends */ -#define SHT_SHLIB 10 /* Reserved */ -#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ -#define SHT_INIT_ARRAY 14 /* Array of constructors */ -#define SHT_FINI_ARRAY 15 /* Array of destructors */ -#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ -#define SHT_GROUP 17 /* Section group */ -#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */ -#define SHT_RELR 19 /* RELR relative relocations */ -#define SHT_NUM 20 /* Number of defined types. */ -#define SHT_LOOS 0x60000000 /* Start OS-specific. */ -#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ -#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ -#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ -#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ -#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ -#define SHT_SUNW_move 0x6ffffffa -#define SHT_SUNW_COMDAT 0x6ffffffb -#define SHT_SUNW_syminfo 0x6ffffffc -#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ -#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ -#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ -#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ -#define SHT_HIOS 0x6fffffff /* End OS-specific type */ -#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ -#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ -#define SHT_LOUSER 0x80000000 /* Start of application-specific */ -#define SHT_HIUSER 0x8fffffff /* End of application-specific */ - -/* Legal values for sh_flags (section flags). */ - -#define SHF_WRITE (1 << 0) /* Writable */ -#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ -#define SHF_EXECINSTR (1 << 2) /* Executable */ -#define SHF_MERGE (1 << 4) /* Might be merged */ -#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ -#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ -#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ -#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling - required */ -#define SHF_GROUP (1 << 9) /* Section is member of a group. */ -#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ -#define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */ -#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ -#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ -#define SHF_GNU_RETAIN (1 << 21) /* Not to be GCed by linker. */ -#define SHF_ORDERED (1 << 30) /* Special ordering requirement - (Solaris). */ -#define SHF_EXCLUDE (1U << 31) /* Section is excluded unless - referenced or allocated (Solaris).*/ - -/* Section compression header. Used when SHF_COMPRESSED is set. */ - -typedef struct -{ - Elf32_Word ch_type; /* Compression format. */ - Elf32_Word ch_size; /* Uncompressed data size. */ - Elf32_Word ch_addralign; /* Uncompressed data alignment. */ -} Elf32_Chdr; - -typedef struct -{ - Elf64_Word ch_type; /* Compression format. */ - Elf64_Word ch_reserved; - Elf64_Xword ch_size; /* Uncompressed data size. */ - Elf64_Xword ch_addralign; /* Uncompressed data alignment. */ -} Elf64_Chdr; - -/* Legal values for ch_type (compression algorithm). */ -#define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE algorithm. */ -#define ELFCOMPRESS_ZSTD 2 /* Zstandard algorithm. */ -#define ELFCOMPRESS_LOOS 0x60000000 /* Start of OS-specific. */ -#define ELFCOMPRESS_HIOS 0x6fffffff /* End of OS-specific. */ -#define ELFCOMPRESS_LOPROC 0x70000000 /* Start of processor-specific. */ -#define ELFCOMPRESS_HIPROC 0x7fffffff /* End of processor-specific. */ - -/* Section group handling. */ -#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ - -/* Symbol table entry. */ - -typedef struct -{ - Elf32_Word st_name; /* Symbol name (string tbl index) */ - Elf32_Addr st_value; /* Symbol value */ - Elf32_Word st_size; /* Symbol size */ - unsigned char st_info; /* Symbol type and binding */ - unsigned char st_other; /* Symbol visibility */ - Elf32_Section st_shndx; /* Section index */ -} Elf32_Sym; - -typedef struct -{ - Elf64_Word st_name; /* Symbol name (string tbl index) */ - unsigned char st_info; /* Symbol type and binding */ - unsigned char st_other; /* Symbol visibility */ - Elf64_Section st_shndx; /* Section index */ - Elf64_Addr st_value; /* Symbol value */ - Elf64_Xword st_size; /* Symbol size */ -} Elf64_Sym; - -/* The syminfo section if available contains additional information about - every dynamic symbol. */ - -typedef struct -{ - Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ - Elf32_Half si_flags; /* Per symbol flags */ -} Elf32_Syminfo; - -typedef struct -{ - Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ - Elf64_Half si_flags; /* Per symbol flags */ -} Elf64_Syminfo; - -/* Possible values for si_boundto. */ -#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ -#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ -#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ - -/* Possible bitmasks for si_flags. */ -#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ -#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-through symbol for translator */ -#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ -#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy - loaded */ -/* Syminfo version values. */ -#define SYMINFO_NONE 0 -#define SYMINFO_CURRENT 1 -#define SYMINFO_NUM 2 - - -/* How to extract and insert information held in the st_info field. */ - -#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) -#define ELF32_ST_TYPE(val) ((val) & 0xf) -#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ -#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) -#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) -#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) - -/* Legal values for ST_BIND subfield of st_info (symbol binding). */ - -#define STB_LOCAL 0 /* Local symbol */ -#define STB_GLOBAL 1 /* Global symbol */ -#define STB_WEAK 2 /* Weak symbol */ -#define STB_NUM 3 /* Number of defined types. */ -#define STB_LOOS 10 /* Start of OS-specific */ -#define STB_GNU_UNIQUE 10 /* Unique symbol. */ -#define STB_HIOS 12 /* End of OS-specific */ -#define STB_LOPROC 13 /* Start of processor-specific */ -#define STB_HIPROC 15 /* End of processor-specific */ - -/* Legal values for ST_TYPE subfield of st_info (symbol type). */ - -#define STT_NOTYPE 0 /* Symbol type is unspecified */ -#define STT_OBJECT 1 /* Symbol is a data object */ -#define STT_FUNC 2 /* Symbol is a code object */ -#define STT_SECTION 3 /* Symbol associated with a section */ -#define STT_FILE 4 /* Symbol's name is file name */ -#define STT_COMMON 5 /* Symbol is a common data object */ -#define STT_TLS 6 /* Symbol is thread-local data object*/ -#define STT_NUM 7 /* Number of defined types. */ -#define STT_LOOS 10 /* Start of OS-specific */ -#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ -#define STT_HIOS 12 /* End of OS-specific */ -#define STT_LOPROC 13 /* Start of processor-specific */ -#define STT_HIPROC 15 /* End of processor-specific */ - - -/* Symbol table indices are found in the hash buckets and chain table - of a symbol hash table section. This special index value indicates - the end of a chain, meaning no further symbols are found in that bucket. */ - -#define STN_UNDEF 0 /* End of a chain. */ - - -/* How to extract and insert information held in the st_other field. */ - -#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) - -/* For ELF64 the definitions are the same. */ -#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) - -/* Symbol visibility specification encoded in the st_other field. */ -#define STV_DEFAULT 0 /* Default symbol visibility rules */ -#define STV_INTERNAL 1 /* Processor specific hidden class */ -#define STV_HIDDEN 2 /* Sym unavailable in other modules */ -#define STV_PROTECTED 3 /* Not preemptible, not exported */ - - -/* Relocation table entry without addend (in section of type SHT_REL). */ - -typedef struct -{ - Elf32_Addr r_offset; /* Address */ - Elf32_Word r_info; /* Relocation type and symbol index */ -} Elf32_Rel; - -/* I have seen two different definitions of the Elf64_Rel and - Elf64_Rela structures, so we'll leave them out until Novell (or - whoever) gets their act together. */ -/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ - -typedef struct -{ - Elf64_Addr r_offset; /* Address */ - Elf64_Xword r_info; /* Relocation type and symbol index */ -} Elf64_Rel; - -/* Relocation table entry with addend (in section of type SHT_RELA). */ - -typedef struct -{ - Elf32_Addr r_offset; /* Address */ - Elf32_Word r_info; /* Relocation type and symbol index */ - Elf32_Sword r_addend; /* Addend */ -} Elf32_Rela; - -typedef struct -{ - Elf64_Addr r_offset; /* Address */ - Elf64_Xword r_info; /* Relocation type and symbol index */ - Elf64_Sxword r_addend; /* Addend */ -} Elf64_Rela; - -/* RELR relocation table entry */ - -typedef Elf32_Word Elf32_Relr; -typedef Elf64_Xword Elf64_Relr; - -/* How to extract and insert information held in the r_info field. */ - -#define ELF32_R_SYM(val) ((val) >> 8) -#define ELF32_R_TYPE(val) ((val) & 0xff) -#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) - -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i) & 0xffffffff) -#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) - -/* Program segment header. */ - -typedef struct -{ - Elf32_Word p_type; /* Segment type */ - Elf32_Off p_offset; /* Segment file offset */ - Elf32_Addr p_vaddr; /* Segment virtual address */ - Elf32_Addr p_paddr; /* Segment physical address */ - Elf32_Word p_filesz; /* Segment size in file */ - Elf32_Word p_memsz; /* Segment size in memory */ - Elf32_Word p_flags; /* Segment flags */ - Elf32_Word p_align; /* Segment alignment */ -} Elf32_Phdr; - -typedef struct -{ - Elf64_Word p_type; /* Segment type */ - Elf64_Word p_flags; /* Segment flags */ - Elf64_Off p_offset; /* Segment file offset */ - Elf64_Addr p_vaddr; /* Segment virtual address */ - Elf64_Addr p_paddr; /* Segment physical address */ - Elf64_Xword p_filesz; /* Segment size in file */ - Elf64_Xword p_memsz; /* Segment size in memory */ - Elf64_Xword p_align; /* Segment alignment */ -} Elf64_Phdr; - -/* Special value for e_phnum. This indicates that the real number of - program headers is too large to fit into e_phnum. Instead the real - value is in the field sh_info of section 0. */ - -#define PN_XNUM 0xffff - -/* Legal values for p_type (segment type). */ - -#define PT_NULL 0 /* Program header table entry unused */ -#define PT_LOAD 1 /* Loadable program segment */ -#define PT_DYNAMIC 2 /* Dynamic linking information */ -#define PT_INTERP 3 /* Program interpreter */ -#define PT_NOTE 4 /* Auxiliary information */ -#define PT_SHLIB 5 /* Reserved */ -#define PT_PHDR 6 /* Entry for header table itself */ -#define PT_TLS 7 /* Thread-local storage segment */ -#define PT_NUM 8 /* Number of defined types */ -#define PT_LOOS 0x60000000 /* Start of OS-specific */ -#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ -#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ -#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ -#define PT_GNU_PROPERTY 0x6474e553 /* GNU property */ -#define PT_GNU_SFRAME 0x6474e554 /* SFrame segment. */ -#define PT_LOSUNW 0x6ffffffa -#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ -#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ -#define PT_HISUNW 0x6fffffff -#define PT_HIOS 0x6fffffff /* End of OS-specific */ -#define PT_LOPROC 0x70000000 /* Start of processor-specific */ -#define PT_HIPROC 0x7fffffff /* End of processor-specific */ - -/* Legal values for p_flags (segment flags). */ - -#define PF_X (1 << 0) /* Segment is executable */ -#define PF_W (1 << 1) /* Segment is writable */ -#define PF_R (1 << 2) /* Segment is readable */ -#define PF_MASKOS 0x0ff00000 /* OS-specific */ -#define PF_MASKPROC 0xf0000000 /* Processor-specific */ - -/* rest of the file is removed by @stsp */ - -#endif /* elf.h */ diff --git a/src/plugin/dj64/elfp.h b/src/plugin/dj64/elfp.h deleted file mode 100644 index 68029f2..0000000 --- a/src/plugin/dj64/elfp.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ELFP_H -#define ELFP_H - -#include "stub.h" - -extern struct ldops elf_ops; - -#endif diff --git a/src/plugin/dj64/stub.c b/src/plugin/dj64/stub.c deleted file mode 100644 index aa8c9ec..0000000 --- a/src/plugin/dj64/stub.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * go32-compatible COFF, PE32 and ELF loader stub. - * Copyright (C) 2022, stsp - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "plugin_config.h" -#include "dosemu_debug.h" -#include "stubinfo.h" -#include "coff.h" -#include "elfp.h" -#include "util.h" -#include "stub_ex.h" -#include "stub.h" - -#define STUB_DEBUG 0 -#if STUB_DEBUG -#define stub_debug(...) J_printf(__VA_ARGS__) -#else -#define stub_debug(...) -#endif - -typedef struct -{ - uint32_t offset32; - unsigned short selector; -} DPMI_FP; - -typedef struct -{ - uint16_t rm; - int pm; -} dpmi_dos_block; - -static char *client_memory; -static DPMI_FP clnt_entry; - -static const char *_basename(const char *name) -{ - const char *p; - p = strrchr(name, '\\'); - if (!p) - p = name; - else - p++; - return p; -} - -static char *_fname(char *name) -{ - char *p, *p1; - p = strrchr(name, '\\'); - if (!p) - p = name; - else - p++; - p1 = strrchr(p, '.'); - if (p1) - p1[0] = '\0'; - return p; -} - -#define exit(x) return x -int djstub_main(int argc, char *argv[], char *envp[], unsigned psp_sel, - cpuctx_t *scp) -{ - int ifile; - off_t coffset = 0; - uint32_t coffsize = 0; - uint32_t noffset = 0; - uint32_t nsize = 0; - uint32_t noffset2 = 0; - uint32_t nsize2 = 0; - char ovl_name[16] = {}; - int rc, i; -#define BUF_SIZE 0x40 - char buf[BUF_SIZE]; - int done = 0; - uint32_t va; - uint32_t va_size; - uint32_t mem_lin; - uint32_t mem_base; - unsigned short clnt_ds; - unsigned short stubinfo_fs; - __dpmi_meminfo info; - dpmi_dos_block db; - void *handle; - _GO32_StubInfo stubinfo; - _GO32_StubInfo *stubinfo_p; - struct ldops *ops = NULL; - char *argv0 = strdup(argv[0]); - - rc = _dos_open(argv[0], O_RDONLY, &ifile); - if (rc) { - fprintf(stderr, "cannot open %s\n", argv[0]); - exit(EXIT_FAILURE); - } - while (!done) { - unsigned rd; -#if STUB_DEBUG - int cnt = 0; -#endif - - stub_debug("Expecting header at 0x%lx\n", coffset); - rc = _dos_read(ifile, buf, BUF_SIZE, &rd); - if (rc) { - error("stub: read() failure\n"); - exit(EXIT_FAILURE); - } - if (rd != BUF_SIZE) { - error("stub: read(%i)=%i, wrong exe file\n", BUF_SIZE, rd); - exit(EXIT_FAILURE); - } - if (buf[0] == 'M' && buf[1] == 'Z' && buf[8] == 4 /* lfanew */) { - uint32_t offs; -#if STUB_DEBUG - cnt++; -#endif - stub_debug("Found exe header %i at 0x%lx\n", cnt, coffset); - memcpy(&offs, &buf[0x3c], sizeof(offs)); - coffset = offs; - memcpy(&coffsize, &buf[0x1c], sizeof(coffsize)); - if (coffsize) - noffset = coffset + coffsize; - memcpy(&nsize, &buf[0x20], sizeof(nsize)); - if (nsize) - noffset2 = noffset + nsize; - memcpy(&nsize2, &buf[0x24], sizeof(nsize2)); - strncpy(ovl_name, &buf[0x30], 12); - ovl_name[12] = '\0'; - } else if (buf[0] == 0x4c && buf[1] == 0x01) { /* it's a COFF */ - done = 1; - ops = &coff_ops; - } else if (buf[0] == 0x7f && buf[1] == 0x45 && - buf[2] == 0x4c && buf[3] == 0x46) { /* it's an ELF */ - done = 1; - ops = &elf_ops; - } else { - fprintf(stderr, "not an exe %s at %lx\n", argv[0], coffset); - exit(EXIT_FAILURE); - } - _dos_seek(ifile, coffset, SEEK_SET); - } - - assert(ops); - handle = ops->read_headers(ifile); - if (!handle) - exit(EXIT_FAILURE); - va = ops->get_va(handle); - va_size = ops->get_length(handle); - clnt_entry.offset32 = ops->get_entry(handle); - stub_debug("va 0x%x va_size 0x%x entry 0x%x\n", - va, va_size, clnt_entry.offset32); - - strncpy(stubinfo.magic, "dj64 (C) stsp", sizeof(stubinfo.magic)); - stubinfo.size = sizeof(stubinfo); - i = 0; - while(*envp) { - i += strlen(*envp) + 1; - envp++; - } - if (i) { - i += strlen(argv0) + 1; - i += 2; - } - stub_debug("env size %i\n", i); - stubinfo.env_size = i; - stubinfo.minstack = 0x80000; - stubinfo.minkeep = 0x4000; - strncpy(stubinfo.argv0, _basename(argv0), sizeof(stubinfo.argv0)); - stubinfo.argv0[sizeof(stubinfo.argv0) - 1] = '\0'; - strncpy(stubinfo.basename, _fname(argv0), sizeof(stubinfo.basename)); -// stubinfo.basename[sizeof(stubinfo.basename) - 1] = '\0'; - strncpy(stubinfo.dpmi_server, "CWSDPMI.EXE", sizeof(stubinfo.dpmi_server)); -#define max(a, b) ((a) > (b) ? (a) : (b)) - stubinfo.initial_size = max(va_size, 0x10000); - stubinfo.psp_selector = psp_sel; - /* DJGPP relies on ds_selector, cs_selector and ds_segment all mapping - * the same real-mode memory block. */ - _dos_link_umb(1); - db.rm = __dpmi_allocate_dos_memory(stubinfo.minkeep >> 4, &db.pm); - _dos_link_umb(0); - stub_debug("rm seg 0x%x\n", db.rm); - stubinfo.ds_selector = db.pm; - stubinfo.ds_segment = db.rm; - /* create alias */ - stubinfo.cs_selector = __dpmi_create_alias_descriptor(db.pm); - /* set descriptor access rights */ - __dpmi_set_descriptor_access_rights(stubinfo.cs_selector, 0x00fb); - - clnt_entry.selector = __dpmi_allocate_ldt_descriptors(1); - clnt_ds = __dpmi_allocate_ldt_descriptors(1); - info.size = PAGE_ALIGN(stubinfo.initial_size); - /* allocate mem */ - __dpmi_allocate_memory(&info); - stubinfo.memory_handle = info.handle; - mem_lin = info.address; - mem_base = mem_lin - va; - stubinfo.mem_base = mem_base; - stub_debug("mem_lin 0x%x mem_base 0x%x\n", mem_lin, mem_base); - /* set base */ - __dpmi_set_segment_base_address(clnt_entry.selector, mem_base); - /* set descriptor access rights */ - __dpmi_set_descriptor_access_rights(clnt_entry.selector, 0xc0fb); - /* set limit */ - __dpmi_set_segment_limit(clnt_entry.selector, 0xffffffff); - /* set base */ - __dpmi_set_segment_base_address(clnt_ds, mem_base); - /* set descriptor access rights */ - __dpmi_set_descriptor_access_rights(clnt_ds, 0xc0f3); - /* set limit */ - __dpmi_set_segment_limit(clnt_ds, 0xffffffff); - - client_memory = SEL_ADR(clnt_ds, 0); - stubinfo_fs = __dpmi_allocate_ldt_descriptors(1); - info.size = PAGE_ALIGN(sizeof(_GO32_StubInfo)); - __dpmi_allocate_memory(&info); - __dpmi_set_segment_base_address(stubinfo_fs, info.address); - __dpmi_set_segment_limit(stubinfo_fs, sizeof(_GO32_StubInfo) - 1); - stubinfo_p = SEL_ADR(stubinfo_fs, 0); - - ops->read_sections(handle, client_memory, ifile, coffset); - - stubinfo.self_fd = ifile; - stubinfo.self_offs = coffset; - stubinfo.self_size = coffsize; - stubinfo.payload_offs = noffset; - stubinfo.payload_size = nsize; - stubinfo.payload2_offs = noffset2; - stubinfo.payload2_size = nsize2; - if (ovl_name[0]) { - snprintf(stubinfo.payload2_name, sizeof(stubinfo.payload2_name), - "%s.dbg", ovl_name); - dbug_printf("loading %s\n", ovl_name); - } - _dos_seek(ifile, noffset, SEEK_SET); - if (nsize > 0) - stub_debug("Found payload of size %i at 0x%x\n", nsize, noffset); - stubinfo.stubinfo_ver = 2; - - memcpy(stubinfo_p, &stubinfo, sizeof(stubinfo)); - stub_debug("Jump to entry...\n"); - _fs = stubinfo_fs; - _es = _ds; - _ds = clnt_ds; - _cs = clnt_entry.selector; - _eip = clnt_entry.offset32; - return 0; -} diff --git a/src/plugin/dj64/stub.h b/src/plugin/dj64/stub.h deleted file mode 100644 index 41e971d..0000000 --- a/src/plugin/dj64/stub.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef STUB_H -#define STUB_H - -struct ldops { - void *(*read_headers)(int ifile); - uint32_t (*get_va)(void *handle); - uint32_t (*get_length)(void *handle); - uint32_t (*get_entry)(void *handle); - void (*read_sections)(void *handle, char *ptr, int ifile, - uint32_t offset); -}; - -#endif diff --git a/src/plugin/dj64/stub_ex.h b/src/plugin/dj64/stub_ex.h deleted file mode 100644 index 224ffc5..0000000 --- a/src/plugin/dj64/stub_ex.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef STUB_EX_H -#define STUB_EX_H - -int djstub_main(int argc, char *argv[], char *envp[], unsigned psp_sel, - cpuctx_t *scp); - -#endif diff --git a/src/plugin/dj64/stubinfo.h b/src/plugin/dj64/stubinfo.h deleted file mode 100644 index 5687c11..0000000 --- a/src/plugin/dj64/stubinfo.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef __dj_include_stub_h__ -#define __dj_include_stub_h__ - -#define STUBINFO 0 -#define STUBINFO_MAGIC 0 -#define STUBINFO_SIZE 0x10 -#define STUBINFO_MINSTACK 0x14 -#define STUBINFO_MEMORY_HANDLE 0x18 -#define STUBINFO_INITIAL_SIZE 0x1c -#define STUBINFO_MINKEEP 0x20 -#define STUBINFO_DS_SELECTOR 0x22 -#define STUBINFO_DS_SEGMENT 0x24 -#define STUBINFO_PSP_SELECTOR 0x26 -#define STUBINFO_CS_SELECTOR 0x28 -#define STUBINFO_ENV_SIZE 0x2a -#define STUBINFO_BASENAME 0x2c -#define STUBINFO_ARGV0 0x34 -#define STUBINFO_DPMI_SERVER 0x44 -#define STUBINFO_STUBINFO_VER 0x54 -#define STUBINFO_SELF_FD 0x58 -#define STUBINFO_SELF_OFFS 0x5C -#define STUBINFO_SELF_SIZE 0x60 -#define STUBINFO_PAYLOAD_OFFS 0x64 -#define STUBINFO_PAYLOAD_SIZE 0x68 -#define STUBINFO_PAYLOAD2_OFFS 0x6C -#define STUBINFO_PAYLOAD2_SIZE 0x70 -#define STUBINFO_PAYLOAD2_NAME 0x74 -#define STUBINFO_MEM_BASE 0x88 -#define STUBINFO_END 0x8C -#ifndef __ASSEMBLER__ -#include -typedef struct { - char magic[16]; - uint32_t size; - uint32_t minstack; - uint32_t memory_handle; - uint32_t initial_size; - unsigned short minkeep; - unsigned short ds_selector; - unsigned short ds_segment; - unsigned short psp_selector; - unsigned short cs_selector; - unsigned short env_size; - char basename[8]; - char argv0[16]; - char dpmi_server[16]; - /* standard djgpp stubinfo ends here */ - uint32_t stubinfo_ver; - int32_t self_fd; - uint32_t self_offs; - int32_t self_size; - uint32_t payload_offs; - int32_t payload_size; - uint32_t payload2_offs; - int32_t payload2_size; - char payload2_name[20]; - uint32_t mem_base; -} _GO32_StubInfo; -#endif - -static_assert(sizeof(_GO32_StubInfo) == STUBINFO_END, "size mismatch"); - -#endif /* __dj_include_stub_h__ */ diff --git a/src/plugin/dj64/util.c b/src/plugin/dj64/util.c deleted file mode 100644 index 982fe8e..0000000 --- a/src/plugin/dj64/util.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2023, stsp2@yandex.ru - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -#include -#include -#include -#include -#include -#include "util.h" - -long _long_read(int file, char *buf, unsigned long offset, unsigned long size) -{ - char tmp[PAGE_SIZE]; - unsigned long done = 0; - -#define min(a, b) ((a) < (b) ? (a) : (b)) - while (size) { - unsigned todo = min(size, sizeof(tmp)); - unsigned rd; - int err = _dos_read(file, tmp, todo, &rd); - if (!err) { - /* word-align memcpy */ - memcpy(buf + offset + done, tmp, rd + (rd & 1)); - done += rd; - size -= rd; - } - if (rd < todo) - break; - } - return done; -} diff --git a/src/plugin/dj64/util.h b/src/plugin/dj64/util.h deleted file mode 100644 index 8161526..0000000 --- a/src/plugin/dj64/util.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef UTIL_H -#define UTIL_H - -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif -#ifndef PAGE_MASK -#define PAGE_MASK (~(PAGE_SIZE-1)) -#endif - -long _long_read(int file, char *buf, unsigned long offset, - unsigned long size); - -#endif diff --git a/src/plugin/doscmd/Makefile b/src/plugin/doscmd/Makefile index 6d2c508..3dd2c93 100644 --- a/src/plugin/doscmd/Makefile +++ b/src/plugin/doscmd/Makefile @@ -16,7 +16,7 @@ COM = $(D)/generic.com STUBSYMLINK = $(D)/eject.com $(D)/exitemu.com $(D)/speed.com $(D)/emudrv.com \ $(D)/lredir.com $(D)/emumouse.com $(D)/xmode.com $(D)/emuconf.com \ $(D)/unix.com $(D)/system.com $(D)/emusound.com \ - $(D)/emudpmi.com $(D)/emufs.com $(D)/fossil.com $(D)/comredir.com + $(D)/emudpmi.com $(D)/emufs.com all: lib $(COM) $(STUBSYMLINK) $(COM): | $(top_builddir)/commands @@ -24,15 +24,15 @@ $(COM): | $(top_builddir)/commands include $(REALTOPDIR)/src/Makefile.common.post $(STUBSYMLINK): $(D1)/generic.com - $(LN_S) -f $( -#if BPRM_MIN_VER != 10 +#if BPRM_VER != 6 #error wrong bprm version #endif -/* currently supported version */ -#define BPRM_SUPP_VER 10 #include "boot.h" -int fdpp_boot(far_t *plt, int plt_len, const void *krnl, int len, - uint16_t seg, uint16_t off, int khigh, - uint16_t heap_seg, int heap, int hhigh, unsigned char *boot_sec, - uint16_t bpseg) +int fdpp_boot(far_t plt, const void *krnl, int len, uint16_t seg, int khigh, + uint16_t heap_seg, int heap, int hhigh, unsigned char *boot_sec) { int i; struct _bprm bprm = {}; - struct _bprm_xtra *xtra = MK_FP32(bpseg, 0); + uint16_t ofs = 0x0000; + dosaddr_t loadaddress = SEGOFF2LINEAR(seg, ofs); uint16_t env_seg = FDPP_BS_SEG + (FDPP_BS_OFF >> 4) + 0x20; // stack+bs char *env = SEG2UNIX(env_seg); int env_len = 0; int warn_legacy_conf = 0; - int use_comcom = 0; bprm.BprmLen = sizeof(bprm); - bprm.BprmVersion = BPRM_SUPP_VER; bprm.HeapSize = heap; bprm.HeapSeg = heap_seg; - bprm.XtraSeg = bpseg; -#if BPRM_VER >= 9 - bprm.PredMask |= (!config.dumb_video << 0); -#endif if (khigh) bprm.Flags |= FDPP_FL_KERNEL_HIGH; if (hhigh) bprm.Flags |= FDPP_FL_HEAP_HIGH; - if (hhigh == 2) - bprm.Flags |= FDPP_FL_HEAP_HMA; bprm.InitEnvSeg = env_seg; bprm.DriveMask = config.drives_mask; @@ -68,10 +57,8 @@ int fdpp_boot(far_t *plt, int plt_len, const void *krnl, int len, env_len += sprintf(env + env_len, "USERDRV=%c", (config.drive_c_num & 0x7f) + 'C'); env_len++; - xtra->BootDrvNum = (config.drive_c_num & 0x7f) + 2; } else { LO(bx) = 0x80; - xtra->BootDrvNum = 2; } FOR_EACH_HDISK(i, { if (disk_root_contains(&hdisktab[i], CONF4_IDX)) { @@ -90,14 +77,8 @@ int fdpp_boot(far_t *plt, int plt_len, const void *krnl, int len, struct sys_dsc *sf1 = fatfs_get_sfiles(f1); bprm.ShellDrive = drv_num + hdisktab[i].log_offs; - if (sf1[CMD_IDX].flags & FLG_COMCOM32) { - dbug_printf("booting comcom32\n"); - use_comcom++; - } - if (sf1[CMD_IDX].flags & FLG_COMCOM64) { - dbug_printf("booting comcom64\n"); - use_comcom++; - } + if (sf1[CMD_IDX].flags & FLG_COMCOM32) + dbug_printf("booting with comcom32\n"); env_len += sprintf(env + env_len, "SHELLDRV=%c", drv + hdisktab[i].log_offs); env_len++; @@ -136,23 +117,14 @@ int fdpp_boot(far_t *plt, int plt_len, const void *krnl, int len, } }); - env_len += sprintf(env + env_len, "#0 :SWITCHES=/F/T%s", - config.dos_trace ? "/Y" : "" - ); + env_len += sprintf(env + env_len, "#0 :SWITCHES=/F%s", + config.dos_trace ? "/Y" : ""); env_len++; if (config.country) { env_len += sprintf(env + env_len, "#1 :COUNTRY=%i,%i", config.country, atoi(config.internal_cset + 2)); env_len++; } - if (use_comcom) - env_len += sprintf(env + env_len, "#2 =command.com /e:%s /k " - "%%FDPP_AUTOEXEC%%", - config.dos_cmd ? "512" : "384 /p"); - else - env_len += sprintf(env + env_len, "#2 =command.com /e:2048 /k " - "%%FDPP_AUTOEXEC%%"); - env_len++; if (fddir_default) { struct disk *dsk = hdisk_find_by_path(fddir_default); @@ -178,24 +150,23 @@ int fdpp_boot(far_t *plt, int plt_len, const void *krnl, int len, env[env_len++] = '\0'; // third terminator (can be \1 for cmdline) env[env_len++] = '\0'; // third terminator is a word, not byte - memcpy(boot_sec + 0x03, "FDPP 1.6", 8); - memcpy(boot_sec + FDPP_PLT_OFFSET, plt, sizeof(plt) * plt_len); + memcpy(boot_sec + 0x03, "FDPP 1.4", 8); + memcpy(boot_sec + FDPP_PLT_OFFSET, &plt, sizeof(plt)); *(uint16_t *)(boot_sec + FDPP_BPRM_VER_OFFSET) = BPRM_VER; memcpy(boot_sec + FDPP_BPRM_OFFSET, &bprm, sizeof(bprm)); - SREG(ds) = seg; - SREG(es) = seg; + SREG(ds) = loadaddress >> 4; + SREG(es) = loadaddress >> 4; SREG(ss) = FDPP_BS_SEG; LWORD(esp) = FDPP_BS_OFF; /* temp stack */ LWORD(ebp) = FDPP_BS_OFF; SREG(cs) = seg; - LWORD(eip) = off; + LWORD(eip) = ofs; int_try_disable_revect(); /* try disable int hooks as well */ if (config.int_hooks == -1) config.int_hooks = config.force_revect; - add_syscom_user(&xtra->BootDrvNum); if (warn_legacy_conf) { error("@Compatibility warning: CONFIG.SYS found on drive C: "); @@ -207,8 +178,3 @@ int fdpp_boot(far_t *plt, int plt_len, const void *krnl, int len, } return 0; } - -int fdpp_boot_xtra_space(void) -{ - return sizeof(struct _bprm_xtra); -} diff --git a/src/plugin/fdpp/boot.h b/src/plugin/fdpp/boot.h index dec249f..387942a 100644 --- a/src/plugin/fdpp/boot.h +++ b/src/plugin/fdpp/boot.h @@ -1,10 +1,7 @@ #ifndef BOOT_H #define BOOT_H -int fdpp_boot(far_t *plt, int plt_len, const void *krnl, int len, - uint16_t seg, uint16_t off, int khigh, - uint16_t heap_seg, int heap, int hhigh, unsigned char *boot_sec, - uint16_t bpseg); -int fdpp_boot_xtra_space(void); +int fdpp_boot(far_t plt, const void *krnl, int len, uint16_t seg, int khigh, + uint16_t heap_seg, int heap, int hhigh, unsigned char *boot_sec); #endif diff --git a/src/plugin/fdpp/configure.ac b/src/plugin/fdpp/configure.ac index 0a69837..f8e8602 100644 --- a/src/plugin/fdpp/configure.ac +++ b/src/plugin/fdpp/configure.ac @@ -1,69 +1,37 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT -AC_CONFIG_HEADERS([_fdppconf.h]) +AC_CONFIG_HEADER(_fdppconf.h) AC_CONFIG_FILES([Makefile.conf]) PKG_PROG_PKG_CONFIG -AC_ARG_WITH([fdpp-lib-dir], AS_HELP_STRING([--with-fdpp-lib-dir=DIR], +AC_ARG_WITH([fdpp-build-path], AS_HELP_STRING([--with-fdpp-build-path=DIR], [use alternate fdpp dir]), [ - fdpp_lib_dir="$withval" - AC_CHECK_FILE([$fdpp_lib_dir/libfdpp.so],, - AC_MSG_ERROR([$fdpp_lib_dir incorrect])) - AC_ARG_WITH([fdpp-include-dir], - AS_HELP_STRING([--with-fdpp-include-dir=DIR], - [set fdpp include dir]), - [fdpp_inc_dir="$withval" - AC_CHECK_FILE([$fdpp_inc_dir/fdpp/thunks.h],, - AC_MSG_ERROR([$fdpp_inc_dir incorrect]))], - AC_MSG_ERROR([use --with-fdpp-include-dir])) - AC_ARG_WITH([fdpp-kernel-dir], - AS_HELP_STRING([--with-fdpp-kernel-dir=DIR], - [set fdpp kernel dir]), - fdpp_kern_dir="$withval", - fdpp_kern_dir="$fdpp_lib_dir") - AC_ARG_WITH([fdpp-pkgconf-dir], - AS_HELP_STRING([--with-fdpp-pkgconf-dir=DIR], - [set fdpp pkgconf dir]), - [export PKG_CONFIG_PATH="$withval"], - [export PKG_CONFIG_PATH="$fdpp_lib_dir"]) - - AC_DEFINE_UNQUOTED(FDPP_KERNEL_DIR, "$fdpp_kern_dir") - FDPP_RPATH="$fdpp_lib_dir" - FDPP_INCLUDES=-I"$fdpp_inc_dir" - FDPP_LFLAGS=-L"$fdpp_lib_dir" + fdpp_lib_dir=$withval + AC_ARG_WITH([fdpp-include-path], + AS_HELP_STRING([--with-fdpp-include-path=DIR], + [set fdpp include dir]), fdpp_inc_dir="$withval", + AC_MSG_ERROR([use --with-fdpp-include-path])) + export PKG_CONFIG_PATH="$fdpp_lib_dir" + export PKG_CONFIG="$PKG_CONFIG \ + --define-variable=includedir="$fdpp_inc_dir" \ + --define-variable=fdpplibdir=$fdpp_lib_dir" + AC_DEFINE_UNQUOTED(FDPP_KERNEL_DIR, "$fdpp_lib_dir") ], [ if test "x$prefix" = xNONE; then if test "x$PKG_CONFIG_PATH" = x then - export PKG_CONFIG_PATH="$ac_default_prefix/lib/pkgconfig" + export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig" else - export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$ac_default_prefix/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig" fi - AC_ARG_WITH([fdpp-rpath], AS_HELP_STRING([--with-fdpp-rpath=DIR], - [add alternate fdpp rpath]), - [FDPP_RPATH="$fdpp_rpath"], - [FDPP_RPATH="/usr/lib/fdpp" - FDPP_RPATH2="/usr/lib64/fdpp"] - ) - else - FDPP_RPATH="$prefix/lib/fdpp" - FDPP_RPATH2="$prefix/lib64/fdpp" fi - FDPP_RPATH3="$ac_default_prefix/lib/fdpp" - FDPP_RPATH4="$ac_default_prefix/lib64/fdpp" ] ) - -AC_SUBST(FDPP_RPATH) -AC_SUBST(FDPP_RPATH2) -AC_SUBST(FDPP_RPATH3) -AC_SUBST(FDPP_RPATH4) -AC_SUBST(FDPP_INCLUDES) -AC_SUBST(FDPP_LFLAGS) - -PKG_CHECK_MODULES([FDPP], [fdpp >= 1.7],, +PKG_CHECK_MODULES([FDPP], [fdpp >= 1.6],, AC_MSG_ERROR([fdpp installation not found or too old])) +AC_SUBST(FDPP_CFLAGS) +AC_SUBST(FDPP_LIBS) PKG_CHECK_MODULES([VALGRIND], [valgrind], AC_DEFINE(HAVE_VALGRIND), AC_MSG_NOTICE([valgrind support disabled])) AH_TEMPLATE([HAVE_VALGRIND], diff --git a/src/plugin/fdpp/fdpp.c b/src/plugin/fdpp/fdpp.c index 420567a..8f1f29b 100644 --- a/src/plugin/fdpp/fdpp.c +++ b/src/plugin/fdpp/fdpp.c @@ -22,7 +22,7 @@ #include #include #include -#if FDPP_API_VER != 35 +#if FDPP_API_VER != 30 #error wrong fdpp version #endif #include "emu.h" @@ -65,7 +65,7 @@ static void fdpp_call_noret(struct vm86_regs *regs, uint16_t seg, uint16_t off, uint8_t *sp, uint8_t len) { REGS = *regs; - coopth_leave_vm86(); + coopth_leave(); copy_stk(sp, len); jmp_to(0xffff, 0); fake_call_to(seg, off); @@ -111,7 +111,7 @@ static void fdpp_print(int prio, const char *format, va_list ap) { switch(prio) { case FDPP_PRINT_TERMINAL: - vfprintf(stderr, format, ap); + vprintf(format, ap); break; case FDPP_PRINT_LOG: if (debug_level('f')) { @@ -119,6 +119,9 @@ static void fdpp_print(int prio, const char *format, va_list ap) vlog_printf(-1, format, ap); } break; + case FDPP_PRINT_SCREEN: + p_dos_vstr(format, ap); + break; } } @@ -129,22 +132,28 @@ static uint8_t *fdpp_so2lin(uint16_t seg, uint16_t off) static int fdpp_ping(void) { - int rc = 0; if (signal_pending()) - rc = fdpp_coopth_yield(); - return rc; + coopth_yield(); +#if 0 + if (GETusTIME(0) - watchdog > 1000000) { + watchdog = GETusTIME(0); // just once + error("fdpp hang, rebooting\n"); + coopth_leave(); + dos_ctrl_alt_del(); + return -1; + } +#endif + return 0; } -static int fdpp_relax(void) +static void fdpp_relax(void) { - int rc; int ii = isset_IF(); set_IF(); - rc = fdpp_coopth_wait(); + coopth_wait(); if (!ii) clear_IF(); - return rc; } static void fdpp_debug(const char *msg) @@ -177,7 +186,7 @@ static void fdpp_fmemset(fdpp_far_t d, int ch, size_t n) memset_dos(dst, ch, n); } -static const struct fdpp_api api = { +static struct fdpp_api api = { .so2lin = fdpp_so2lin, .exit = fdpp_exit, .abort = fdpp_abort, diff --git a/src/plugin/fdpp/hooks.c b/src/plugin/fdpp/hooks.c index d2f0e9f..a43a56c 100644 --- a/src/plugin/fdpp/hooks.c +++ b/src/plugin/fdpp/hooks.c @@ -22,16 +22,12 @@ #ifdef HAVE_LIBBSD #include #endif -#include -#include #include #include "emu.h" #include "cpu.h" #include "int.h" #include "lowmem.h" -#include "xms.h" #include "fatfs.h" -#include "hlt.h" #include "coopth.h" #include "doshelpers.h" #include "utilities.h" @@ -65,14 +61,6 @@ static void fdpp_thr(void *arg) } } -static void fdpp_ctrl(Bit16u idx, HLT_ARG(arg)) -{ - int err; - fake_retf(); - err = FdppCtrl(idx, ®S); - assert(!err); -} - static void fdpp_cleanup(void) { while (num_clnup_tids) { @@ -87,7 +75,7 @@ static void fdpp_cleanup(void) static int fdpp_pre_boot(unsigned char *boot_sec) { int err; - void *hndl = NULL; + void *hndl; const void *krnl; int krnl_len; struct fdpp_bss_list *bss; @@ -95,73 +83,52 @@ static int fdpp_pre_boot(unsigned char *boot_sec) #ifdef USE_MHPDBG char *map; #endif -#define PLT_LEN 2 - static far_t plt[PLT_LEN]; + static far_t plt; static int initialized; uint16_t seg; - uint32_t off; - uint16_t new_seg; - uint16_t bpseg; uint16_t heap_seg; uint16_t daddr; - int heap_sz; int khigh = 0; int hhigh = 0; if (!initialized) { - emu_hlt_t hlt_hdlr = HLT_INITIALIZER; - plt[0].segment = BIOS_HLT_BLK_SEG; + plt.segment = BIOS_HLT_BLK_SEG; fdpp_tid = coopth_create_vm86("fdpp thr", fdpp_thr, fake_retf, - &plt[0].offset); - hlt_hdlr.name = "fdpp control"; - hlt_hdlr.func = fdpp_ctrl; - plt[1].segment = BIOS_HLT_BLK_SEG; - plt[1].offset = hlt_register_handler_vm86(hlt_hdlr); + &plt.offset); initialized++; } fddir = getenv("FDPP_KERNEL_DIR"); - if (fddir) - hndl = FdppKernelLoad(fddir, &krnl_len, &bss, &off); #ifdef FDPP_KERNEL_DIR - if (!hndl) { + if (!fddir) fddir = FDPP_KERNEL_DIR; - hndl = FdppKernelLoad(fddir, &krnl_len, &bss, &off); - } #endif - if (!hndl) { + if (!fddir) fddir = FdppKernelDir(); - assert(fddir); - hndl = FdppKernelLoad(fddir, &krnl_len, &bss, &off); - } + assert(fddir); + hndl = FdppKernelLoad(fddir, &krnl_len, &bss); if (!hndl) return -1; - assert(off < 65536); - assert(!kptr); - if (config.dos_up) { - int tot_sz; - int to_hma = (config.dos_up == 2 && xms_helper_init_ext()); - heap_sz = to_hma ? 0 : FDPP_LMHEAP_ADD; - tot_sz = P2ALIGN(krnl_len + heap_sz, 16); - kptr = lowmem_alloc_aligned(16, tot_sz + fdpp_boot_xtra_space()); - daddr = DOSEMU_LMHEAP_OFFS_OF(kptr); - assert(!(daddr & 15)); - heap_seg = 0x90; // for low heap - seg = DOSEMU_LMHEAP_SEG + (daddr >> 4); - bpseg = seg + (tot_sz >> 4); - khigh++; - hhigh = to_hma + 1; - } else { - heap_sz = 1024 * 6; - kptr = lowmem_alloc_aligned(16, heap_sz + fdpp_boot_xtra_space()); - daddr = DOSEMU_LMHEAP_OFFS_OF(kptr); - assert(!(daddr & 15)); - heap_seg = DOSEMU_LMHEAP_SEG + (daddr >> 4); - bpseg = heap_seg + (heap_sz >> 4); - seg = 0x90; - hhigh++; - } - krnl = FdppKernelReloc(hndl, seg, &new_seg, FdppLoaderHook); +#if 1 +#define HEAP_SZ 1024 + kptr = lowmem_alloc_aligned(16, krnl_len + HEAP_SZ); + daddr = DOSEMU_LMHEAP_OFFS_OF(kptr); + assert(!(daddr & 15)); + heap_seg = 0x90; // for low heap + seg = DOSEMU_LMHEAP_SEG + (daddr >> 4); + khigh++; + hhigh++; +#else + /* alternative layout for testing */ +#define HEAP_SZ (1024*3) + kptr = lowmem_alloc_aligned(16, HEAP_SZ); + daddr = DOSEMU_LMHEAP_OFFS_OF(kptr); + assert(!(daddr & 15)); + heap_seg = DOSEMU_LMHEAP_SEG + (daddr >> 4); + seg = 0x60; + hhigh++; +#endif + krnl = FdppKernelReloc(hndl, seg); if (!krnl) return -1; /* copy kernel, clear bss and boot it */ @@ -169,13 +136,12 @@ static int fdpp_pre_boot(unsigned char *boot_sec) if (bss) { int i; for (i = 0; i < bss->num; i++) - MEMSET_DOS(SEGOFF2LINEAR(new_seg, bss->ent[i].off), 0, + MEMSET_DOS(SEGOFF2LINEAR(seg, 0) + bss->ent[i].off, 0, bss->ent[i].len); free(bss); } - FdppKernelFree(hndl); - err = fdpp_boot(plt, PLT_LEN, krnl, krnl_len, new_seg, off, khigh, - heap_seg, heap_sz, hhigh, boot_sec, bpseg); + err = fdpp_boot(plt, krnl, krnl_len, seg, khigh, heap_seg, HEAP_SZ, hhigh, + boot_sec); if (err) return err; register_cleanup_handler(fdpp_cleanup); @@ -206,36 +172,13 @@ int do_fdpp_call(uint16_t seg, uint16_t off) assert(num_clnup_tids < MAX_CLNUP_TIDS); clnup_tids[num_clnup_tids++] = coopth_get_tid(); - coopth_cancel_disable_cur(); + coopth_cancel_disable(); rc = do_call_back(seg, off); - /* re-enable cancellability only if it was not canceled already */ + /* re-enable cancelability only if it was not canceled already */ if (rc == 0) - coopth_cancel_enable_cur(); + coopth_cancel_enable(); else ret = ASM_CALL_ABORT; num_clnup_tids--; return ret; } - -static int do_coopth_wrp(int (*cbk)(void)) -{ - int rc; - assert(num_clnup_tids < MAX_CLNUP_TIDS); - clnup_tids[num_clnup_tids++] = coopth_get_tid(); - coopth_cancel_disable_cur(); - rc = cbk(); - if (rc != -1) - coopth_cancel_enable_cur(); - num_clnup_tids--; - return rc; -} - -int fdpp_coopth_wait(void) -{ - return do_coopth_wrp(coopth_wait); -} - -int fdpp_coopth_yield(void) -{ - return do_coopth_wrp(coopth_yield); -} diff --git a/src/plugin/fdpp/hooks.h b/src/plugin/fdpp/hooks.h index 3fe1aaf..dc698a9 100644 --- a/src/plugin/fdpp/hooks.h +++ b/src/plugin/fdpp/hooks.h @@ -3,7 +3,5 @@ void fdpp_fatfs_hook(struct sys_dsc *sfiles, fatfs_t *fat); int do_fdpp_call(uint16_t seg, uint16_t off); -int fdpp_coopth_wait(void); -int fdpp_coopth_yield(void); #endif diff --git a/src/plugin/fluidsynth/Makefile b/src/plugin/fluidsynth/Makefile index 3551a58..6de101e 100644 --- a/src/plugin/fluidsynth/Makefile +++ b/src/plugin/fluidsynth/Makefile @@ -9,15 +9,15 @@ include ../plugins.mak ALL_CFLAGS+=$(DL_CFLAGS) $(FLUSCFLAGS) -I$(srcdir)/fluid_rip CFILES = mid_o_flus.c fluid_rip/fluid_seqbind.c -LDFLAGS += -Bsymbolic -ifeq ($(USE_DL_PLUGINS),1) +ALL_LDFLAGS += -Bsymbolic +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_fluidsynth.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_fluidsynth.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(FLUSLIB) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(FLUSLIB) endif diff --git a/src/plugin/fluidsynth/configure.ac b/src/plugin/fluidsynth/configure.ac index 6c0dfbd..da3fc62 100644 --- a/src/plugin/fluidsynth/configure.ac +++ b/src/plugin/fluidsynth/configure.ac @@ -3,4 +3,11 @@ AC_INIT AC_CONFIG_FILES([Makefile.conf]) PKG_CHECK_MODULES([FLUS], [fluidsynth],, AC_MSG_ERROR([fluidsynth development libs not found])) +dnl need to see if new_fluid_midi_parser() is exported - it is private +dnl in some versions of fluidsynth +#AC_CHECK_LIB([fluidsynth], new_fluid_midi_parser,, +# AC_MSG_ERROR([fluidsynth is found but new_fluid_midi_parser() \ +#is not exported])) +AC_SUBST(FLUS_CFLAGS) +AC_SUBST(FLUS_LIBS) AC_OUTPUT diff --git a/src/plugin/fluidsynth/mid_o_flus.c b/src/plugin/fluidsynth/mid_o_flus.c index 733da33..34d0f9f 100644 --- a/src/plugin/fluidsynth/mid_o_flus.c +++ b/src/plugin/fluidsynth/mid_o_flus.c @@ -31,12 +31,8 @@ #include #include #include -#include -#ifdef __APPLE__ /* to redefine sem_init() and related functions */ -#include "utilities.h" -#else #include -#endif +#include #include "seqbind.h" #include "emu.h" #include "init.h" @@ -48,6 +44,7 @@ #define midoflus_name "flus" #define midoflus_longname "MIDI Output: FluidSynth device" static const int flus_format = PCM_FORMAT_S16_LE; +static const float flus_gain = 1; static const float flus_srate = 44100.0; #define FLUS_CHANNELS 2 #define FLUS_MAX_BUF 512 @@ -72,55 +69,44 @@ static int midoflus_init(void *arg) char *sfont = NULL; const char *def_sfonts[] = { "/usr/share/soundfonts/default.sf2", // fedora - "/usr/share/sounds/sf2/default-GM.sf2", // ubuntu "/usr/share/soundfonts/FluidR3_GM.sf2", // fedora "/usr/share/sounds/sf2/FluidR3_GM.sf2.flac", // ubuntu "/usr/share/sounds/sf2/FluidR3_GM.sf2", // debian NULL }; + int use_defsf = 0; settings = new_fluid_settings(); fluid_settings_setint(settings, "synth.lock-memory", 0); - fluid_settings_setnum(settings, "synth.gain", config.fluid_volume / 4.0); + fluid_settings_setnum(settings, "synth.gain", flus_gain); fluid_settings_setnum(settings, "synth.sample-rate", flus_srate); - if (config.fluid_sfont && config.fluid_sfont[0]) { - if (access(config.fluid_sfont, R_OK) == 0) { - sfont = strdup(config.fluid_sfont); - ret = FLUID_OK; - } else { - error("soundfont %s missing\n", config.fluid_sfont); + ret = fluid_settings_dupstr(settings, "synth.default-soundfont", &sfont); + if (ret == 0 || access(sfont, R_OK) != 0) { + int i = 0; + if (ret == 0) + warn("Your fluidsynth is too old\n"); + else + warn("fluidsynth sound font unavailable at %s\n", sfont); + free(sfont); + while (def_sfonts[i]) { + if (access(def_sfonts[i], R_OK) == 0) { + sfont = strdup(def_sfonts[i]); + use_defsf = 1; + break; + } + i++; + } + if (!use_defsf) { + error("Your fluidsynth is too old and soundfonts not found\n"); goto err1; } - } else { - ret = fluid_settings_dupstr(settings, "synth.default-soundfont", - &sfont); - if (ret == FLUID_FAILED) { - error("Your fluidsynth is too old\n"); - } else if (access(sfont, R_OK) != 0) { - error("fluidsynth sound font unavailable at %s\n", sfont); - free(sfont); - sfont = NULL; - } - if (!sfont) { - int i = 0; - - while (def_sfonts[i]) { - if (access(def_sfonts[i], R_OK) == 0) { - sfont = strdup(def_sfonts[i]); - break; - } - i++; - } - if (!sfont) { - error("soundfonts not found\n"); - goto err1; - } - } } synth = new_fluid_synth(settings); ret = fluid_synth_sfload(synth, sfont, TRUE); if (ret == FLUID_FAILED) { - error("fluidsynth: cannot load soundfont %s\n", sfont); + warn("fluidsynth: cannot load soundfont %s\n", sfont); + if (use_defsf) + error("Your fluidsynth is too old\n"); free(sfont); goto err2; } diff --git a/src/plugin/gpm/Makefile b/src/plugin/gpm/Makefile index 847ea65..3c9161e 100644 --- a/src/plugin/gpm/Makefile +++ b/src/plugin/gpm/Makefile @@ -9,14 +9,14 @@ include ../plugins.mak ALL_CFLAGS+=$(DL_CFLAGS) CFILES=mouse_gpm.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_gpm.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_gpm.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(GPMLIB) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(GPMLIB) endif diff --git a/src/plugin/gpm/configure.ac b/src/plugin/gpm/configure.ac index a49cafc..a18629b 100644 --- a/src/plugin/gpm/configure.ac +++ b/src/plugin/gpm/configure.ac @@ -3,4 +3,5 @@ AC_INIT AC_CONFIG_FILES([Makefile.conf]) AC_CHECK_LIB(gpm, Gpm_Open,, AC_MSG_ERROR([gpm development libs not found])) +AC_SUBST(LIBS) AC_OUTPUT diff --git a/src/plugin/gpm/mouse_gpm.c b/src/plugin/gpm/mouse_gpm.c index 3bac4b2..e5cdbb6 100644 --- a/src/plugin/gpm/mouse_gpm.c +++ b/src/plugin/gpm/mouse_gpm.c @@ -9,15 +9,15 @@ #include #include -#include -#include "ioselect.h" + +#include "emu.h" #include "video.h" #include "mouse.h" #include "utilities.h" #include "init.h" #include "vc.h" -static void gpm_getevent(int fd, void *arg) +static void gpm_getevent(void *arg) { static unsigned char buttons; Gpm_Event ev; @@ -30,7 +30,6 @@ static void gpm_getevent(int fd, void *arg) if (select(gpm_fd + 1, &mfds, NULL, NULL, &tv) <= 0) return; Gpm_GetEvent((void*)&ev); -// ioselect_complete(gpm_fd); type = GPM_BARE_EVENTS(ev.type); m_printf("MOUSE: Get GPM Event, %d\n", type); switch (type) { @@ -91,7 +90,7 @@ static int gpm_init(void) return FALSE; } - add_to_io_select_threaded(fd, gpm_getevent, NULL); + add_to_io_select(fd, gpm_getevent, NULL); m_printf("GPM MOUSE: Using GPM Mouse\n"); return TRUE; } diff --git a/src/plugin/ieee1284/Makefile b/src/plugin/ieee1284/Makefile index a940840..04c766c 100644 --- a/src/plugin/ieee1284/Makefile +++ b/src/plugin/ieee1284/Makefile @@ -9,14 +9,14 @@ include ../plugins.mak ALL_CFLAGS+=$(DL_CFLAGS) CFILES = opl2lpt.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_lpt.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_lpt.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(LPTLIB) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(LPTLIB) endif diff --git a/src/plugin/ieee1284/configure.ac b/src/plugin/ieee1284/configure.ac index 142bde4..430f548 100644 --- a/src/plugin/ieee1284/configure.ac +++ b/src/plugin/ieee1284/configure.ac @@ -5,4 +5,5 @@ AC_CHECK_LIB(ieee1284, ieee1284_open,, AC_MSG_ERROR([ieee1284 development lib not found])) AC_CHECK_HEADER(ieee1284.h,, AC_MSG_ERROR([ieee1284 development header not found])) +AC_SUBST(LIBS) AC_OUTPUT diff --git a/src/plugin/ieee1284/opl2lpt.c b/src/plugin/ieee1284/opl2lpt.c index 2bfc835..63920a8 100644 --- a/src/plugin/ieee1284/opl2lpt.c +++ b/src/plugin/ieee1284/opl2lpt.c @@ -30,7 +30,6 @@ #include #include #include -#include "init.h" #include "emu.h" #include "sound/oplplug.h" @@ -76,7 +75,7 @@ static bool opl2lpt_init(void) struct parport_list parports = {}; const char *parportName = config.opl2lpt_device; - if (!parportName || !parportName[0]) + if (!parportName) return false; // Look for available parallel ports if (ieee1284_find_ports(&parports, 0) != E1284_OK) { diff --git a/src/plugin/json/Makefile b/src/plugin/json/Makefile index c288475..edfe786 100644 --- a/src/plugin/json/Makefile +++ b/src/plugin/json/Makefile @@ -10,14 +10,14 @@ include ../plugins.mak ALL_CPPFLAGS += $(JSONCINC) CFILES = locale.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_json.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_json.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $(OBJS) $(JSONCLIB) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $(OBJS) $(JSONCLIB) endif diff --git a/src/plugin/json/configure.ac b/src/plugin/json/configure.ac index 4ad6a7a..a7d17cb 100644 --- a/src/plugin/json/configure.ac +++ b/src/plugin/json/configure.ac @@ -3,4 +3,6 @@ AC_INIT AC_CONFIG_FILES([Makefile.conf]) PKG_CHECK_MODULES([JSONC], [json-c >= 0.13],, AC_MSG_ERROR([json-c development headers not found or too old])) +AC_SUBST(JSONC_CFLAGS) +AC_SUBST(JSONC_LIBS) AC_OUTPUT diff --git a/src/plugin/json/locale.c b/src/plugin/json/locale.c index 8a76e0a..6404446 100644 --- a/src/plugin/json/locale.c +++ b/src/plugin/json/locale.c @@ -138,7 +138,7 @@ static void charset_init(void) else error("Can't find codepage for \"%s\".\n" "Please add the mapping to locales.conf and send patch.\n", - lang); + l2); cntry = json_get_country_for_lang(obj2, l2); if (cntry != -1) set_country_code(cntry); @@ -146,7 +146,6 @@ static void charset_init(void) done: free(l2); free(path); - json_object_put(jobj); } CONSTRUCTOR(static void init(void)) diff --git a/src/plugin/ladspa/Makefile b/src/plugin/ladspa/Makefile index f1dbd07..5759ed8 100644 --- a/src/plugin/ladspa/Makefile +++ b/src/plugin/ladspa/Makefile @@ -14,14 +14,14 @@ CFILES = load.c ladspa.c OBJS=$(CFILES:.c=.o) DEPENDS=$(CFILES:.c=.d) -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_ladspa.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_ladspa.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(LADSPA_LDFLAGS) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(LADSPA_LDFLAGS) endif diff --git a/src/plugin/libao/Makefile b/src/plugin/libao/Makefile index 3c6cb70..4c08278 100644 --- a/src/plugin/libao/Makefile +++ b/src/plugin/libao/Makefile @@ -9,14 +9,14 @@ include ../plugins.mak ALL_CFLAGS+=$(DL_CFLAGS) $(LIBAOCFL) CFILES=snd_o_ao.c snd_o_ao_file.c ao_init.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_libao.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_libao.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBAOLIB) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(LIBAOLIB) endif diff --git a/src/plugin/libao/configure.ac b/src/plugin/libao/configure.ac index 2b9922d..f733c8e 100644 --- a/src/plugin/libao/configure.ac +++ b/src/plugin/libao/configure.ac @@ -1,5 +1,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT AC_CONFIG_FILES([Makefile.conf]) -PKG_CHECK_MODULES([AO], [ao],, AC_MSG_ERROR([libao development libs not found])) +XIPH_PATH_AO(, AC_MSG_ERROR([libao development libs not found])) +AC_SUBST(AO_LIBS) +AC_SUBST(AO_CFLAGS) AC_OUTPUT diff --git a/src/plugin/libao/m4/ao.m4 b/src/plugin/libao/m4/ao.m4 new file mode 100644 index 0000000..207ccc7 --- /dev/null +++ b/src/plugin/libao/m4/ao.m4 @@ -0,0 +1,108 @@ +# ao.m4 +# Configure paths for libao +# Jack Moffitt 10-21-2000 +# Shamelessly stolen from Owen Taylor and Manish Singh + +dnl XIPH_PATH_AO([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Test for libao, and define AO_CFLAGS and AO_LIBS +dnl +AC_DEFUN([XIPH_PATH_AO], +[dnl +dnl Get the cflags and libraries +dnl +AC_ARG_WITH(ao,[ --with-ao=PFX Prefix where libao is installed (optional)], ao_prefix="$withval", ao_prefix="") +AC_ARG_WITH(ao-libraries,[ --with-ao-libraries=DIR Directory where libao library is installed (optional)], ao_libraries="$withval", ao_libraries="") +AC_ARG_WITH(ao-includes,[ --with-ao-includes=DIR Directory where libao header files are installed (optional)], ao_includes="$withval", ao_includes="") +AC_ARG_ENABLE(aotest, [ --disable-aotest Do not try to compile and run a test ao program],, enable_aotest=yes) + + + if test "x$ao_libraries" != "x" ; then + AO_LIBS="-L$ao_libraries" + elif test "x$ao_prefix" != "x"; then + AO_LIBS="-L$ao_prefix/lib" + fi + + if test "x$ao_includes" != "x" ; then + AO_CFLAGS="-I$ao_includes" + elif test "x$ao_prefix" != "x"; then + AO_CFLAGS="-I$ao_prefix/include" + fi + + # see where dl* and friends live + AC_CHECK_FUNCS(dlopen, [AO_DL_LIBS=""], [ + AC_CHECK_LIB(dl, dlopen, [AO_DL_LIBS="-ldl"], [ + AC_MSG_WARN([could not find dlopen() needed by libao sound drivers + your system may not be supported.]) + ]) + ]) + + AO_LIBS="$AO_LIBS -lao $AO_DL_LIBS" + + AC_MSG_CHECKING(for ao) + no_ao="" + + + if test "x$enable_aotest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $AO_CFLAGS" + LIBS="$LIBS $AO_LIBS" +dnl +dnl Now check if the installed ao is sufficiently new. +dnl + rm -f conf.aotest + AC_TRY_RUN([ +#include +#include +#include +#include + +int main () +{ + system("touch conf.aotest"); + return 0; +} + +],, no_ao=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + + if test "x$no_ao" = "x" ; then + AC_MSG_RESULT(yes) + ifelse([$1], , :, [$1]) + else + AC_MSG_RESULT(no) + if test -f conf.aotest ; then + : + else + echo "*** Could not run ao test program, checking why..." + CFLAGS="$CFLAGS $AO_CFLAGS" + LIBS="$LIBS $AO_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding ao or finding the wrong" + echo "*** version of ao. If it is not finding ao, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means ao was incorrectly installed" + echo "*** or that you have moved ao since it was installed." ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + AO_CFLAGS="" + AO_LIBS="" + ifelse([$2], , :, [$2]) + fi + AC_SUBST(AO_CFLAGS) + AC_SUBST(AO_LIBS) + rm -f conf.aotest +]) diff --git a/src/plugin/libao/snd_o_ao.c b/src/plugin/libao/snd_o_ao.c index 35c3267..de86f14 100644 --- a/src/plugin/libao/snd_o_ao.c +++ b/src/plugin/libao/snd_o_ao.c @@ -40,11 +40,7 @@ #include #include #include -#ifdef __APPLE__ /* to redefine sem_init() and related functions */ -#include "utilities.h" -#else #include -#endif #define aosnd_name "ao" #define aosnd_longname "Sound Output: libao" diff --git a/src/plugin/midimisc/Makefile b/src/plugin/midimisc/Makefile index 2b8a3d3..9410f7d 100644 --- a/src/plugin/midimisc/Makefile +++ b/src/plugin/midimisc/Makefile @@ -7,9 +7,17 @@ top_builddir=../../.. include ../plugins_simp.mak -CFILES = mid_o_pipe.c mid_o_tmdty.c mid_i_pipe.c fluid_midi.c mid_o_file.c -ifeq ($(USE_OSS),1) -CFILES += mid_o_oss.c -endif +CFILES=mid_o_pipe.c mid_o_tmdty.c mid_o_oss.c mid_i_pipe.c fluid_midi.c \ + mid_o_file.c + +SFILES= +ALL=$(CFILES) $(SFILES) + +OBJS=$(CFILES:.c=.o) +DEPENDS=$(CFILES:.c=.d) include $(REALTOPDIR)/src/Makefile.common.post + +all: lib + +install: all diff --git a/src/plugin/midimisc/fluid_midi.c b/src/plugin/midimisc/fluid_midi.c index 2a3cde8..7b16903 100644 --- a/src/plugin/midimisc/fluid_midi.c +++ b/src/plugin/midimisc/fluid_midi.c @@ -39,7 +39,7 @@ static int fluid_midi_event_length(unsigned char event); * @return New MIDI event structure or NULL when out of memory. */ fluid_midi_event_t * -new_fluid_midi_event (void) +new_fluid_midi_event () { fluid_midi_event_t* evt; evt = FLUID_NEW(fluid_midi_event_t); @@ -303,7 +303,7 @@ fluid_midi_event_set_sysex(fluid_midi_event_t *evt, void *data, int size, int dy * new_fluid_midi_parser */ fluid_midi_parser_t * -new_fluid_midi_parser (void) +new_fluid_midi_parser () { fluid_midi_parser_t *parser; parser = FLUID_NEW(fluid_midi_parser_t); diff --git a/src/plugin/midimisc/mid_i_pipe.c b/src/plugin/midimisc/mid_i_pipe.c index 35bf111..d14836e 100644 --- a/src/plugin/midimisc/mid_i_pipe.c +++ b/src/plugin/midimisc/mid_i_pipe.c @@ -20,8 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "ioselect.h" -#include "dosemu_debug.h" +#include "emu.h" #include "dosemu_config.h" #include "init.h" #include "sound/midi.h" @@ -36,7 +35,7 @@ static int pipe_fd = -1; #define midipipe_name "MIDI Input: named pipe" -static void midipipe_io(int fd, void *arg) +static void midipipe_io(void *arg) { unsigned char buf[1024]; int n, selret; @@ -47,7 +46,7 @@ static void midipipe_io(int fd, void *arg) tv.tv_sec = 0; tv.tv_usec = 0; while ((selret = select(pipe_fd + 1, &rfds, NULL, NULL, &tv)) > 0) { - n = read(pipe_fd, buf, sizeof(buf)); + n = RPT_SYSCALL(read(pipe_fd, buf, sizeof(buf))); if (n > 0) { midi_put_data(buf, n); } else { @@ -58,13 +57,12 @@ static void midipipe_io(int fd, void *arg) tv.tv_sec = 0; tv.tv_usec = 0; } - ioselect_complete(fd); } static int midipipe_init(void *arg) { - const char *name = dosemu_midi_in_path; - pipe_fd = open(name, O_RDONLY | O_NONBLOCK); + const char *name = DOSEMU_MIDI_IN_PATH; + pipe_fd = RPT_SYSCALL(open(name, O_RDONLY | O_NONBLOCK)); if (pipe_fd == -1) { S_printf("%s: unable to open %s for reading: %s\n", midipipe_name, name, strerror(errno)); diff --git a/src/plugin/midimisc/mid_o_pipe.c b/src/plugin/midimisc/mid_o_pipe.c index 866210e..0f54ff2 100644 --- a/src/plugin/midimisc/mid_o_pipe.c +++ b/src/plugin/midimisc/mid_o_pipe.c @@ -38,9 +38,9 @@ static int pipe_fd = -1; static int midopipe_init(void *arg) { - const char *name = dosemu_midi_path; + const char *name = DOSEMU_MIDI_PATH; - if (mkfifo(name, 0640) == -1) { + if (mkfifo(name, 0666) == -1) { S_printf("Unable to mkfifo() '%s'\n", strerror(errno)); return 0; } @@ -71,7 +71,7 @@ static void midopipe_write(unsigned char val) { /* Try again to open FIFO on each write in case some readers showed up. */ if (pipe_fd == -1) { - pipe_fd = RPT_SYSCALL(open(dosemu_midi_path, O_WRONLY | O_CREAT | O_NONBLOCK, 0640)); + pipe_fd = RPT_SYSCALL(open(DOSEMU_MIDI_PATH, O_WRONLY | O_CREAT | O_NONBLOCK, 0666)); if (pipe_fd == -1) { return; } diff --git a/src/plugin/midimisc/mid_o_tmdty.c b/src/plugin/midimisc/mid_o_tmdty.c index f9d148a..7a29618 100644 --- a/src/plugin/midimisc/mid_o_tmdty.c +++ b/src/plugin/midimisc/mid_o_tmdty.c @@ -25,7 +25,6 @@ #include "init.h" #include "utilities.h" #include "sig.h" -#include "ioselect.h" #include "sound/sound.h" #include "sound/midi.h" #include @@ -64,7 +63,7 @@ static int pcm_stream, pcm_running; static void midotmdty_reset(void); -static void midotmdty_io(int fd, void *arg) +static void midotmdty_io(void *arg) { sndbuf_t buf[16384][SNDBUF_CHANS]; int n, selret, fmt; @@ -90,7 +89,6 @@ static void midotmdty_io(int fd, void *arg) tv.tv_sec = 0; tv.tv_usec = 0; } - ioselect_complete(fd); } static int midotmdty_preinit(void) @@ -180,7 +178,7 @@ static int midotmdty_preinit(void) ctrl_sock_in = tmdty_pipe_in[0]; ctrl_sock_out = tmdty_pipe_out[1]; /* no handler, default handler does waitpid() */ - sigchld_register_handler(tmdty_pid, NULL, NULL); + sigchld_register_handler(tmdty_pid, NULL); return TRUE; diff --git a/src/plugin/modemu/atcmd.c b/src/plugin/modemu/atcmd.c index 8f8c9ab..f3e55bb 100644 --- a/src/plugin/modemu/atcmd.c +++ b/src/plugin/modemu/atcmd.c @@ -332,7 +332,7 @@ atcmdPQ(void) } /* %Rn */ -/* n: 0(cooked?? mode) or 1(raw mode: 8bit through, no IAC handling) */ +/* n: 0(cooked?? mode) or 1(raw mode: 8bit thru, no IAC handling) */ /* overrides %B and %L settings */ int atcmdPR(const char *s) @@ -346,7 +346,7 @@ atcmdPR(const char *s) } /* %Tn */ -/* n: 0(don't support telnet term-type option) or */ +/* n: 0(dont support telnet term-type option) or */ /* 1(send $TERM for term-type option request) */ int atcmdPT(const char *s) @@ -381,7 +381,7 @@ atcmdPT(const char *s) int atcmdPTSet(const char *s) { - char buf[PT_MAX + 1]; + char buf[PT_MAX]; sscanf(s+4, "%" LIT(PT_MAX) "[^\"]", buf); /*strncpy(atcmd.pt.str, s+3, PT_MAX);*/ atcmd.pt.len = strlen(buf); @@ -394,7 +394,7 @@ atcmdPTSet(const char *s) /* %Vn */ /* n: 0-255 */ /* bit0: output misc info to make up for less descriptive ATX0 indication */ -/* bit1: output telnet option negotiation */ +/* bit1: output telnet option negotioation */ int atcmdPV(const char *s) { diff --git a/src/plugin/modemu/modemu.c b/src/plugin/modemu/modemu.c index a6b4cb9..6a412fc 100644 --- a/src/plugin/modemu/modemu.c +++ b/src/plugin/modemu/modemu.c @@ -2,7 +2,6 @@ #include "emu.h" #include "serial.h" #include "utilities.h" -#include "ioselect.h" #else #define _XOPEN_SOURCE #endif @@ -274,7 +273,7 @@ onlineMode(void) perror("select()"); return 0; } - /* fall through */ + /* fall thru */ case 0: return 2; } @@ -288,12 +287,10 @@ onlineMode(void) if (FD_ISSET(sock.fd, &rfds)) { sockBufRead(); sockReadLoop(); - ioselect_complete(sock.fd); } if (FD_ISSET(tty.rfd, &rfds)) { ttyBufRead(); ttyReadLoop(); - ioselect_complete(tty.rfd); } } return 0; @@ -670,7 +667,7 @@ int run_modemu(void) #ifdef DOSEMU static int initialized; -void modemu_async_callback(int fd, void *arg) +void modemu_async_callback(void *arg) { run_modemu(); } diff --git a/src/plugin/modemu/sock.c b/src/plugin/modemu/sock.c index d3e1c15..e13072a 100644 --- a/src/plugin/modemu/sock.c +++ b/src/plugin/modemu/sock.c @@ -1,5 +1,5 @@ #ifdef DOSEMU -#include "ioselect.h" +#include "emu.h" #endif #ifdef TERMNET #include diff --git a/src/plugin/modemu/sock.h b/src/plugin/modemu/sock.h index bc09a7b..26e2dbf 100644 --- a/src/plugin/modemu/sock.h +++ b/src/plugin/modemu/sock.h @@ -15,5 +15,5 @@ sockDial(void); int sockConnectStart(void); #ifdef DOSEMU -void modemu_async_callback(int fd, void *arg); +void modemu_async_callback(void *arg); #endif diff --git a/src/plugin/modemu/telopt.c b/src/plugin/modemu/telopt.c index 89771c1..f5b9569 100644 --- a/src/plugin/modemu/telopt.c +++ b/src/plugin/modemu/telopt.c @@ -260,7 +260,7 @@ telOptHandle(int cmd, int opt) if (tostp->pending) { tostp->pending = 0; if (tostp->req == mustNegate) - return 1; /* requirement didn't meet */ + return 1; /* requirment didn't meet */ if (tostp->state == !reqState) { /* this may not happen */ tostp->state = reqState; putOptCmd(posiResCmd, opt); /* positive response */ diff --git a/src/plugin/munt/Makefile b/src/plugin/munt/Makefile index dd59e55..5f64669 100644 --- a/src/plugin/munt/Makefile +++ b/src/plugin/munt/Makefile @@ -9,14 +9,14 @@ include ../plugins.mak ALL_CFLAGS+=$(DL_CFLAGS) CFILES=munt.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_munt.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_munt.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(MUNTLIB) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(MUNTLIB) endif diff --git a/src/plugin/munt/configure.ac b/src/plugin/munt/configure.ac index 80f8c18..07dc04c 100644 --- a/src/plugin/munt/configure.ac +++ b/src/plugin/munt/configure.ac @@ -6,4 +6,5 @@ AC_CHECK_LIB(mt32emu, mt32emu_create_context,, AC_CHECK_HEADER([mt32emu/c_interface/c_interface.h],, AC_MSG_ERROR([munt development headers not found])) +AC_SUBST(LIBS) AC_OUTPUT diff --git a/src/plugin/munt/munt.c b/src/plugin/munt/munt.c index e00b57b..25e3b20 100644 --- a/src/plugin/munt/munt.c +++ b/src/plugin/munt/munt.c @@ -22,14 +22,10 @@ */ #include +#include #include #include #include -#ifdef __APPLE__ /* to redefine sem_init() and related functions */ -#include "utilities.h" -#else -#include -#endif #include "emu.h" #include "init.h" #include "timers.h" @@ -64,8 +60,7 @@ static int midomunt_init(void *arg) strcat(p, "/MT32_CONTROL.ROM"); ret = mt32emu_add_rom_file(ctx, p); if (ret != MT32EMU_RC_ADDED_CONTROL_ROM) { - error("MUNT: Can't find %s\n" - "\tYou may want to download mt32 roms.\n", p); + error("MUNT: Can't find %s\n", p); goto err; } strcpy(p, config.munt_roms_dir); @@ -76,8 +71,6 @@ static int midomunt_init(void *arg) goto err; } - mt32emu_set_output_gain(ctx, config.fluid_volume / 2); - sem_init(&syn_sem, 0, 0); pthread_create(&syn_thr, NULL, synth_thread, NULL); #if defined(HAVE_PTHREAD_SETNAME_NP) && defined(__GLIBC__) diff --git a/src/plugin/periph/Makefile b/src/plugin/periph/Makefile index 2acbeb1..6364be5 100644 --- a/src/plugin/periph/Makefile +++ b/src/plugin/periph/Makefile @@ -6,19 +6,32 @@ IDEST=/var/lib CFILES=hdinfo.c mkhdimage.c putrom.c mkfatimage16.c \ dexeconfig.c scsicheck.c dosctrl.c vbioscheck.c -SFILES = bootsect.S bootnorm.S +XSFILES=bootsect.s bootnorm.s SRC=$(CFILES) OBJ1=hdinfo OBJ2=putrom dexeconfig scsicheck dosctrl vbioscheck -OBJ=$(BINPATH)/bin/mkfatimage16 $(BINPATH)/bin/mkhdimage +OBJ=$(OBJ1) $(BINPATH)/bin/mkfatimage16 $(BINPATH)/bin/mkhdimage ALL_CPPFLAGS += -I. all: $(OBJ) -include $(REALTOPDIR)/src/Makefile.common.post +boot%.elf: boot%.o + $(AS_LD) $(AS_LDFLAGS) -static --section-start .text=0x0000 \ + -e _start16 -Map boot$*.map -o $@ $< + chmod -x $@ -$(BINPATH)/bin/mkfatimage16: mkfatimage16.o $(SFILES:.S=.o) | $(BINPATH)/bin +boot%.bin: boot%.elf + $(OBJCOPY) -j .text -O binary $< $@ + +boot%.xxd: boot%.bin + echo "const char boot$*_code[] = \"\\" >$@ + hexdump -v -e '"\\" "x" 1/1 "%02X"' $< >>$@ + echo "\";" >>$@ + +mkfatimage16.o: bootsect.xxd bootnorm.xxd + +$(BINPATH)/bin/mkfatimage16: mkfatimage16.o | $(BINPATH)/bin $(LD) $(ALL_LDFLAGS) $^ -o $@ $(BINPATH)/bin/mkhdimage: mkhdimage.o | $(BINPATH)/bin @@ -37,8 +50,10 @@ install: clean:: rm -f $(OBJ) $(OBJ2) *.o mkfatimage16 mkhdimage - rm -f *.map + rm -f *.out *.xxd *.map realclean:: clean +include $(REALTOPDIR)/src/Makefile.common.post + NO_LIB = 1 diff --git a/src/plugin/periph/bootnorm.S b/src/plugin/periph/bootnorm.s similarity index 56% rename from src/plugin/periph/bootnorm.S rename to src/plugin/periph/bootnorm.s index 27d4052..2c77a92 100644 --- a/src/plugin/periph/bootnorm.S +++ b/src/plugin/periph/bootnorm.s @@ -2,11 +2,12 @@ # normal DOS boot sector # +.intel_syntax noprefix .text .code16 -.global _start -_start: +.globl _start16 +_start16: #----------------------------------------------------------------------- # ENTRY (copied from freedos bootsector) @@ -18,39 +19,38 @@ _start: real_start: cli cld - xorw %ax,%ax - movw %ax,%ds - movw $0x7c00,%bp - movw %ax,%ss # initialize stack - leaw -0x20(%bp),%sp + xor ax, ax + mov ds, ax + mov bp, 0x7c00 + mov ss, ax # initialize stack + lea sp, [bp-0x20] sti - movw $0x1FE0,%ax - movw %ax,%es - movw %bp,%si - movw %bp,%di - movw $0x0100,%cx - rep - movsw + mov ax, 0x1FE0 + mov es, ax + mov si, bp + mov di, bp + mov cx, 0x0100 + rep movsw - jmp $0x1FE0,$0x7c00+ cont-real_start + jmp 0x1FE0:0x7c00+ cont-real_start -cont: movw %ax,%ds - movw %ax,%ss - xorw %ax,%ax - movw %ax,%es +cont: mov ds, ax + mov ss, ax + xor ax,ax + mov es,ax # call print # db "FreeDOS MBR...",0 # search for active partition - leaw 0x1be(%bp),%di # start of partition table + lea di, [bp+0x1be] # start of partition table test_next_for_active: - testb $0x80,(%di) + test byte ptr [di],0x80 jne active_partition_found - addw $0x10,%di # next table - cmpw $0x7c00+0x1fe,%di # scanned beyond end of table ?? + add di,0x10 # next table + cmp di, 0x7c00+0x1fe# scanned beyond end of table ?? jb test_next_for_active #***************************************************************** @@ -87,14 +87,14 @@ active_partition_found: jc trouble_reading_drive - cmpw $0xaa55,%es:0x7c00+0x1fe + cmp word ptr [es:0x7c00+0x1fe],0xaa55 jne invalid_partition_code # call print # db '.jump DOS..',0 - movw %di,%si # ds:si -> booted partition entry - jmp $0x0,$0x7c00 # and jump to boot sector code + mov si, di # ds:si -> booted partition entry + jmp 0x0:0x7c00 # and jump to boot sector code #***************************** @@ -106,34 +106,34 @@ active_partition_found: read_boot_sector: # /* check for LBA support */ - movw $0x55aa,%bx - movb $0x41,%ah - int $0x13 + mov bx,0x55aa + mov ah,0x41 + int 0x13 jc StandardBios # if (regs.b.x != 0xaa55 || (regs.flags & 0x01)) - cmpw $0xaa55,%bx # goto StandardBios; + cmp bx,0xaa55 # goto StandardBios# jne StandardBios # /* if DAP cannot be used, don't use LBA */ # /* if ((regs.c.x & 1) == 0) */ - # /* goto StandardBios; */ - testb $1,%cl + # /* goto StandardBios# */ + test cl,1 jz StandardBios - jmp LBABios + jmp short LBABios #struct _bios_LBA_address_packet /* Used to access a hard disk via LBA */ #{ -# unsigned char packet_size; /* size of this packet...set to 16 */ -# unsigned char reserved_1; /* set to 0...unused */ -# unsigned char number_of_blocks; /* 0 < number_of_blocks < 128 */ -# unsigned char reserved_2; /* set to 0...unused */ -# UBYTE far *buffer_address; /* addr of transfer buffer */ -# unsigned long block_address; /* LBA address */ -# unsigned long block_address_high; /* high bytes of LBA addr...unused */ -#}; +# unsigned char packet_size# /* size of this packet...set to 16 */ +# unsigned char reserved_1# /* set to 0...unused */ +# unsigned char number_of_blocks# /* 0 < number_of_blocks < 128 */ +# unsigned char reserved_2# /* set to 0...unused */ +# UBYTE far *buffer_address# /* addr of transfer buffer */ +# unsigned long block_address# /* LBA address */ +# unsigned long block_address_high# /* high bytes of LBA addr...unused */ +#}# _bios_LBA_address_packet: .byte 0x10 @@ -151,15 +151,15 @@ _bios_LBA_high: LBABios: # copy start address of partition to DAP - movw 8(%di),%ax - movw %ax,0x7c00+ _bios_LBA_low-real_start - movw 8+2(%di),%ax - movw %ax,0x7c00+ _bios_LBA_high-real_start + mov ax,[di+8] + mov [0x7c00+ (_bios_LBA_low-real_start)],ax + mov ax,[di+8+2] + mov [0x7c00+ (_bios_LBA_high-real_start)],ax - movw $0x4200,%ax # regs.a.x = LBA_READ; - mov $0x7c00+ _bios_LBA_address_packet-real_start,%si + mov ax,0x4200 # regs.a.x = LBA_READ# + mov si,0x7c00+ (_bios_LBA_address_packet-real_start)# regs.si = FP_OFF(&dap)# - int $0x13 + int 0x13 ret #***************************************************************** @@ -170,15 +170,15 @@ StandardBios: # .byte 'standard BIOS',0 - movw $0x0204,%ax # regs.a.x = 0x0201; - movw $0x7c00,%bx # regs.b.x = FP_OFF(buffer); - movw 2(%di),%cx # regs.c.x = + mov ax,0x0204 # regs.a.x = 0x0201# + mov bx,0x7c00 # regs.b.x = FP_OFF(buffer)# + mov cx,[di+2] # regs.c.x = # ((chs.Cylinder & 0xff) << 8) + ((chs.Cylinder & 0x300) >> 2) + - # chs.Sector; - # that was easy ;-) - movb 1(%di),%dh # regs.d.b.h = chs.Head; - # regs.es = FP_SEG(buffer); - int $0x13 + # chs.Sector# + # that was easy #-) + mov dh,[di+1] # regs.d.b.h = chs.Head# + # regs.es = FP_SEG(buffer)# + int 0x13 ret @@ -187,13 +187,13 @@ StandardBios: # prints text after call to this function. print_1char: - xorw %bx,%bx # video page 0 - movb $0x0E,%ah # else print it - int $0x10 # via TTY mode -print: popw %si # this is the first character + xor bx, bx # video page 0 + mov ah, 0x0E # else print it + int 0x10 # via TTY mode +print: pop si # this is the first character print1: lodsb # get token - pushw %si # stack up potential return address - cmpb $0,%al # end of string? + push si # stack up potential return address + cmp al, 0 # end of string? jne print_1char # until done ret # and jump to it diff --git a/src/plugin/periph/bootnorm_offsets.h b/src/plugin/periph/bootnorm_offsets.h deleted file mode 100644 index 40a8c17..0000000 --- a/src/plugin/periph/bootnorm_offsets.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/src/plugin/periph/bootsect.S b/src/plugin/periph/bootsect.s similarity index 98% rename from src/plugin/periph/bootsect.S rename to src/plugin/periph/bootsect.s index ac50914..31bdb39 100644 --- a/src/plugin/periph/bootsect.S +++ b/src/plugin/periph/bootsect.s @@ -8,8 +8,8 @@ .code16 .text -.globl _start -_start: +.globl _start16 +_start16: head: diff --git a/src/plugin/periph/bootsect_offsets.h b/src/plugin/periph/bootsect_offsets.h deleted file mode 100644 index 40a8c17..0000000 --- a/src/plugin/periph/bootsect_offsets.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/src/plugin/periph/dexeconfig.c b/src/plugin/periph/dexeconfig.c index d78136d..78435ac 100644 --- a/src/plugin/periph/dexeconfig.c +++ b/src/plugin/periph/dexeconfig.c @@ -86,7 +86,7 @@ static void viewconf(void) exit(1); } close(fd); - printf("\ncontents of embedded .dosrc:\n\n"); + printf("\ncontents of imbedded .dosrc:\n\n"); fwrite(buf, size, 1, stdout); } @@ -230,9 +230,10 @@ static void getconf(void) int main(int argc, char **argv) { - int c; + char c; char *flags=0; + optind = 0; while ((c = getopt(argc, argv, "vi:x:Mp:")) !=EOF) { switch (c) { case 'i': diff --git a/src/plugin/periph/mkfatimage16.c b/src/plugin/periph/mkfatimage16.c index 1fed3e6..f1ff304 100644 --- a/src/plugin/periph/mkfatimage16.c +++ b/src/plugin/periph/mkfatimage16.c @@ -32,12 +32,11 @@ #include "disks.h" //#include "doshelpers.h" +#include "bootnorm.xxd" +#include "bootsect.xxd" + #define MIN(a,b) (((a)<(b))?(a):(b)) -extern char _binary_bootnorm_o_bin_end[] asm("_binary_bootnorm_o_bin_end"); -extern char _binary_bootnorm_o_bin_start[] asm("_binary_bootnorm_o_bin_start"); -extern char _binary_bootsect_o_bin_end[] asm("_binary_bootsect_o_bin_end"); -extern char _binary_bootsect_o_bin_start[] asm("_binary_bootsect_o_bin_start"); /* These can be changed -- at least in theory. In practise, it doesn't * seem to work very well (I don't know why). @@ -396,8 +395,7 @@ int main(int argc, char *argv[]) } /* Write our master boot record */ clear_buffer(); - memcpy(buffer, _binary_bootnorm_o_bin_start, - MIN(sizeof(buffer), _binary_bootnorm_o_bin_end-_binary_bootnorm_o_bin_start)); + memcpy(buffer, bootnorm_code, MIN(sizeof(buffer), sizeof(bootnorm_code))); #if 0 buffer[0] = 0xeb; /* Jump to dosemu exit code. */ buffer[1] = 0x3c; /* (jmp 62; nop) */ @@ -443,8 +441,7 @@ int main(int argc, char *argv[]) } if (!bootsect_file) { clear_buffer(); - memcpy(buffer, _binary_bootsect_o_bin_start, - MIN(sizeof(buffer), _binary_bootsect_o_bin_end-_binary_bootsect_o_bin_start)); + memcpy(buffer, bootsect_code, MIN(sizeof(buffer), sizeof(bootsect_code))); } bpb = (struct on_disk_bpb *) &buffer[0x0b]; diff --git a/src/plugin/plugins.mak b/src/plugin/plugins.mak index 693325d..0cb0bba 100644 --- a/src/plugin/plugins.mak +++ b/src/plugin/plugins.mak @@ -1,6 +1,4 @@ include ../plugins_simp.mak ifeq ($(findstring $(MAKECMDGOALS), clean realclean configure),) -ifneq ($(wildcard Makefile.conf.in),) -include Makefile.conf -endif +-include Makefile.conf endif diff --git a/src/plugin/sdl/Makefile b/src/plugin/sdl/Makefile index 9caa9cc..84e59bf 100644 --- a/src/plugin/sdl/Makefile +++ b/src/plugin/sdl/Makefile @@ -8,11 +8,11 @@ top_builddir=../../.. include ../plugins.mak ALL_CFLAGS+=$(DL_CFLAGS) $(SDL_CFLAGS) -CFILES=sdl.c keyb_SDL.c snd_o_SDL.c clip_SDL.c +CFILES=sdl.c keyb_SDL.c snd_o_SDL.c OBJS=$(CFILES:.c=.o) DEPENDS=$(CFILES:.c=.d) -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_sdl.so ALL_CFLAGS += -fPIC endif @@ -21,9 +21,9 @@ include $(REALTOPDIR)/src/Makefile.common.post ALL_CPPFLAGS += $(SDL_CFLAGS) -I$(srcdir)/../X -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_sdl.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(SDL_LIBS) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(SDL_LIBS) endif install: all diff --git a/src/plugin/sdl/acinclude.m4 b/src/plugin/sdl/acinclude.m4 new file mode 100644 index 0000000..b6df43f --- /dev/null +++ b/src/plugin/sdl/acinclude.m4 @@ -0,0 +1,181 @@ +# Configure paths for SDL +# Sam Lantinga 9/21/99 +# stolen from Manish Singh +# stolen back from Frank Belew +# stolen from Manish Singh +# Shamelessly stolen from Owen Taylor + +dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS +dnl +AC_DEFUN([AM_PATH_SDL], +[dnl +dnl Get the cflags and libraries from the sdl-config script +dnl +AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], + sdl_prefix="$withval", sdl_prefix="") +AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], + sdl_exec_prefix="$withval", sdl_exec_prefix="") +AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], + , enable_sdltest=yes) + + if test x$sdl_exec_prefix != x ; then + sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_args="$sdl_args --prefix=$sdl_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_prefix/bin/sdl-config + fi + fi + + if test "x$prefix" != xNONE; then + PATH="$prefix/bin:$prefix/usr/bin:$PATH" + fi + AC_PATH_PROG(SDL_CONFIG, sdl-config, no, [$PATH]) + min_sdl_version=ifelse([$1], ,0.11.0,$1) + AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) + no_sdl="" + if test "$SDL_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` + SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` + + sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_CXXFLAGS="$CXXFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" +dnl +dnl Now check if the installed SDL is sufficiently new. (Also sanity +dnl checks the results of sdl-config to some extent +dnl + rm -f conf.sdltest + AC_TRY_RUN([ +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); + printf("*** to point to the correct copy of sdl-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + CXXFLAGS="$ac_save_CXXFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$SDL_CONFIG" = "no" ; then + echo "*** The sdl-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL_CONFIG environment variable to the" + echo "*** full path to sdl-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + AC_TRY_LINK([ +#include +#include "SDL.h" + +int main(int argc, char *argv[]) +{ return 0; } +#undef main +#define main K_and_R_C_main +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + CXXFLAGS="$ac_save_CXXFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) + rm -f conf.sdltest +]) diff --git a/src/plugin/sdl/clip_SDL.c b/src/plugin/sdl/clip_SDL.c deleted file mode 100644 index 6396786..0000000 --- a/src/plugin/sdl/clip_SDL.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: SDL clipboard support - * - * Author: @andrewbird @stsp - */ - -#include -#include -#include -#ifdef HAVE_LIBBSD -#include -#endif -#include -#include -#include -#include "dosemu_debug.h" -#include "types.h" -#include "init.h" -#include "clipboard.h" -#include "clip_SDL.h" - -static int cl_type; -#define _clipboard_grabbed_data clip_str - -static int clipboard_clear(void) -{ - cnn_clear(); - // SDL3 TODO: SDL_ClearClipboardData() - if (SDL_SetClipboardText("")) { - v_printf("SDL_clipboard: Clear failed, error '%s'\n", SDL_GetError()); - return FALSE; - } - return TRUE; -} - -static int clipboard_write(int type, const char *p, int size) -{ - int ret; - - if (!cnn_write(type, p, size)) - return FALSE; - ret = SDL_SetClipboardText(clip_str); - return ret == 0 ? TRUE : FALSE; -} - -static int clipboard_getsize(int type) -{ - cnn_clear(); - - if (SDL_HasClipboardText() == FALSE) - return 0; - - _clipboard_grabbed_data = SDL_GetClipboardText(); - if (!_clipboard_grabbed_data) { - v_printf("SDL_clipboard: GetSize failed (grabbed data is NULL\n"); - return 0; - } - - return cnn_getsize(type); -} - -static int clipboard_getdata(int type, char *p, int size) -{ - return cnn_getdata(type, p, size); -} - -static struct clipboard_system cnative_SDL = -{ - clipboard_clear, - clipboard_write, - clipboard_getsize, - clipboard_getdata, - "sdl native clipboard", -}; - -static struct clipboard_system cnonnative_SDL = -{ - cnn_clear, - cnn_write, - cnn_getsize, - cnn_getdata, - "sdl nonnative clipboard", -}; - -static struct clipboard_system *cl_ops[] = { - &cnonnative_SDL, - &cnative_SDL, -}; - -static int cwrp_clear(void) -{ - return cl_ops[cl_type]->clear(); -} - -static int cwrp_write(int type, const char *p, int size) -{ - return cl_ops[cl_type]->write(type, p, size); -} - -static int cwrp_getsize(int type) -{ - return cl_ops[cl_type]->getsize(type); -} - -static int cwrp_getdata(int type, char *p, int size) -{ - return cl_ops[cl_type]->getdata(type, p, size); -} - -static struct clipboard_system cwrapped_SDL = -{ - cwrp_clear, - cwrp_write, - cwrp_getsize, - cwrp_getdata, - "sdl clipboard", -}; - -void sdlclip_setnative(int on) -{ - assert(on <= 1); - cl_type = on; -} - -int sdlclip_copy(SDL_Window *window) -{ - int ret; - if (!clip_str) - return FALSE; - // SDL3 TODO: SDL_ClearWindowNotification() - ret = SDL_SetClipboardText(clip_str); - return ret == 0 ? TRUE : FALSE; -} - -int sdlclip_paste(SDL_Window *window) -{ - cnn_clear(); - - if (SDL_HasClipboardText() == FALSE) - return FALSE; - - _clipboard_grabbed_data = SDL_GetClipboardText(); - if (!_clipboard_grabbed_data) { - v_printf("SDL_clipboard: SDL_GetClipboardText() failed\n"); - return FALSE; - } - return TRUE; -} - -int sdlclip_clear(SDL_Window *window) -{ - // SDL3 TODO: SDL_ClearWindowNotification() - cnn_clear(); - return TRUE; -} - -CONSTRUCTOR(void sdlclip_initialize(void)) -{ - register_clipboard_system(&cwrapped_SDL); -} diff --git a/src/plugin/sdl/clip_SDL.h b/src/plugin/sdl/clip_SDL.h deleted file mode 100644 index d8620f6..0000000 --- a/src/plugin/sdl/clip_SDL.h +++ /dev/null @@ -1,4 +0,0 @@ -void sdlclip_setnative(int on); -int sdlclip_copy(SDL_Window *window); -int sdlclip_paste(SDL_Window *window); -int sdlclip_clear(SDL_Window *window); diff --git a/src/plugin/sdl/configure.ac b/src/plugin/sdl/configure.ac index 9c46c24..25c92af 100644 --- a/src/plugin/sdl/configure.ac +++ b/src/plugin/sdl/configure.ac @@ -2,15 +2,10 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT dnl Check for SDL -SDL_MIN_VERSION=2.0.6 -PKG_CHECK_MODULES(SDL, [sdl2 >= $SDL_MIN_VERSION],, [ - AC_MSG_ERROR([*** SDL version $SDL_MIN_VERSION not found!]) -]) -m4_define(SDL_VERSION, [2$1[]26$1[]0]) -m4_define(SDL_VER, [SDL_VERSION(.)]) -PKG_CHECK_MODULES(sdl2_[]SDL_VERSION(_), [sdl2 >= SDL_VER],, [ - AC_MSG_WARN([sdl2 version SDL_VER not found]) -]) +SDL_VERSION=2.0.6 +AM_PATH_SDL2($SDL_VERSION,, + AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]) +) dnl Check for SDL2_ttf PKG_CHECK_MODULES(SDL2_TTF, [SDL2_ttf], [ @@ -28,6 +23,14 @@ PKG_CHECK_MODULES(FONTCONFIG, [fontconfig], [ AC_MSG_WARN([Fontconfig development package not installed]) ]) +dnl Check for SDL2_image +PKG_CHECK_MODULES(SDL2_IMAGE, [SDL2_image], [ + SDL_LIBS+=" $SDL2_IMAGE_LIBS" + SDL_CFLAGS+=" $SDL2_IMAGE_CFLAGS -DHAVE_SDL2_IMAGE" +], [ + AC_MSG_WARN([SDL2_image development package not installed]) +]) + AC_CONFIG_FILES([Makefile.conf]) AC_OUTPUT diff --git a/src/plugin/sdl/keyb_SDL.c b/src/plugin/sdl/keyb_SDL.c index 5af31c6..9b3654f 100644 --- a/src/plugin/sdl/keyb_SDL.c +++ b/src/plugin/sdl/keyb_SDL.c @@ -30,16 +30,10 @@ #include "keyb_SDL.h" #include "sdl2-keymap.h" -static int kbd_inited; - static void SDL_sync_shiftstate(Boolean make, SDL_Keycode kc, SDL_Keymod e_state) { - t_modifiers shiftstate; + t_modifiers shiftstate = get_shiftstate(); - if (!kbd_inited) - return; - - shiftstate = get_shiftstate(); switch (kc) { case SDLK_LSHIFT: case SDLK_RSHIFT: @@ -100,9 +94,6 @@ void SDL_process_key_text(SDL_KeyboardEvent keyevent, SDL_Scancode scan = keysym.scancode; t_keynum keynum = sdl2_scancode_to_keynum(scan); - if (!kbd_inited) - return; - if (keynum == NUM_VOID) { error("SDL: unknown scancode %x\n", scan); return; @@ -125,9 +116,6 @@ void SDL_process_key_text(SDL_KeyboardEvent keyevent, void SDL_process_key_press(SDL_KeyboardEvent keyevent) { - if (!kbd_inited) - return; - SDL_Keysym keysym = keyevent.keysym; SDL_Scancode scan = keysym.scancode; t_keynum keynum = sdl2_scancode_to_keynum(scan); @@ -145,9 +133,6 @@ void SDL_process_key_press(SDL_KeyboardEvent keyevent) void SDL_process_key_release(SDL_KeyboardEvent keyevent) { - if (!kbd_inited) - return; - SDL_Keysym keysym = keyevent.keysym; SDL_Scancode scan = keysym.scancode; t_keynum keynum = sdl2_scancode_to_keynum(scan); @@ -169,7 +154,6 @@ static int sdl_kbd_probe(void) static int sdl_kbd_init(void) { - kbd_inited = 1; return 1; } diff --git a/src/plugin/sdl/keyb_SDL.h b/src/plugin/sdl/keyb_SDL.h index fd0f51e..3165dc4 100644 --- a/src/plugin/sdl/keyb_SDL.h +++ b/src/plugin/sdl/keyb_SDL.h @@ -1,17 +1,7 @@ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * for details see file COPYING in the DOSEMU distribution */ void SDL_process_key_press(SDL_KeyboardEvent keyevent); diff --git a/src/plugin/sdl/m4/sdl2.m4 b/src/plugin/sdl/m4/sdl2.m4 new file mode 100644 index 0000000..8ff2c5d --- /dev/null +++ b/src/plugin/sdl/m4/sdl2.m4 @@ -0,0 +1,202 @@ +# Configure paths for SDL +# Sam Lantinga 9/21/99 +# stolen from Manish Singh +# stolen back from Frank Belew +# stolen from Manish Singh +# Shamelessly stolen from Owen Taylor + +# serial 1 + +dnl AM_PATH_SDL2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS +dnl +AC_DEFUN([AM_PATH_SDL2], +[dnl +dnl Get the cflags and libraries from the sdl2-config script +dnl +AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], + sdl_prefix="$withval", sdl_prefix="") +AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], + sdl_exec_prefix="$withval", sdl_exec_prefix="") +AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], + , enable_sdltest=yes) + + min_sdl_version=ifelse([$1], ,2.0.0,$1) + + if test "x$sdl_prefix$sdl_exec_prefix" = x ; then + PKG_CHECK_MODULES([SDL], [sdl2 >= $min_sdl_version], + [sdl_pc=yes], + [sdl_pc=no]) + else + sdl_pc=no + if test x$sdl_exec_prefix != x ; then + sdl_config_args="$sdl_config_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL2_CONFIG+set} != xset ; then + SDL2_CONFIG=$sdl_exec_prefix/bin/sdl2-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_config_args="$sdl_config_args --prefix=$sdl_prefix" + if test x${SDL2_CONFIG+set} != xset ; then + SDL2_CONFIG=$sdl_prefix/bin/sdl2-config + fi + fi + fi + + if test "x$sdl_pc" = xyes ; then + no_sdl="" + SDL2_CONFIG="pkg-config sdl2" + else + as_save_PATH="$PATH" + if test "x$prefix" != xNONE && test "$cross_compiling" != yes; then + PATH="$prefix/bin:$prefix/usr/bin:$PATH" + fi + AC_PATH_PROG(SDL2_CONFIG, sdl2-config, no, [$PATH]) + PATH="$as_save_PATH" + AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) + no_sdl="" + + if test "$SDL2_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL2_CONFIG $sdl_config_args --cflags` + SDL_LIBS=`$SDL2_CONFIG $sdl_config_args --libs` + + sdl_major_version=`$SDL2_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdl_minor_version=`$SDL2_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdl_micro_version=`$SDL2_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_CXXFLAGS="$CXXFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" +dnl +dnl Now check if the installed SDL is sufficiently new. (Also sanity +dnl checks the results of sdl2-config to some extent +dnl + rm -f conf.sdltest + AC_TRY_RUN([ +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl2-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl2-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl2-config was wrong, set the environment variable SDL2_CONFIG\n"); + printf("*** to point to the correct copy of sdl2-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_sdl=yes, no_sdl=yes) + CFLAGS="$ac_save_CFLAGS" + CXXFLAGS="$ac_save_CXXFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + fi + if test "x$no_sdl" = x ; then + ifelse([$2], , :, [$2]) + else + if test "$SDL2_CONFIG" = "no" ; then + echo "*** The sdl2-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL2_CONFIG environment variable to the" + echo "*** full path to sdl2-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + AC_TRY_LINK([ +#include +#include "SDL.h" + +int main(int argc, char *argv[]) +{ return 0; } +#undef main +#define main K_and_R_C_main +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl2-config script: $SDL2_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + CXXFLAGS="$ac_save_CXXFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) + rm -f conf.sdltest +]) diff --git a/src/plugin/sdl/sdl.c b/src/plugin/sdl/sdl.c index df14868..fd698e3 100644 --- a/src/plugin/sdl/sdl.c +++ b/src/plugin/sdl/sdl.c @@ -32,6 +32,9 @@ #include #include #include +#ifdef HAVE_SDL2_IMAGE +#include +#endif #if defined(HAVE_SDL2_TTF) && defined(HAVE_FONTCONFIG) #include #include @@ -48,7 +51,6 @@ #include "vgatext.h" #include "render.h" #include "keyb_SDL.h" -#include "clip_SDL.h" #include "keyboard/keyb_clients.h" #include "dos2linux.h" #include "utilities.h" @@ -136,7 +138,6 @@ struct rect_desc { static int font_width, font_height; static int win_width, win_height; static int real_win_width, real_win_height; -static int desired_win_width, desired_win_height; static int m_x_res, m_y_res; static int use_bitmap_font; static int use_ttf_font; @@ -154,25 +155,18 @@ static pthread_cond_t rend_cnd = PTHREAD_COND_INITIALIZER; static int force_grab = 0; static int grab_active = 0; static int kbd_grab_active = 0; -static int sdlclip_mode; static int m_cursor_visible; static int initialized; static int pre_initialized = 0; static int wait_kup; static int copypaste; static int current_mode_class; -static int border_on; #define MODE_CLASS() ((current_mode_class == GRAPH || use_bitmap_font ) ? \ GRAPH : TEXT) static SDL_Keycode mgrab_key = SDLK_HOME; -#if SDL_VERSION_ATLEAST(2,26,0) #define CONFIG_SDL_SELECTION 1 -#else -#define CONFIG_SDL_SELECTION 0 -#endif -#if defined(HAVE_SDL2_TTF) && defined(HAVE_FONTCONFIG) static void SDL_draw_string(void *opaque, int x, int y, const char *text, int len, Bit8u attr); static void SDL_draw_line(void *opaque, int x, int y, float ul, int len, @@ -193,7 +187,6 @@ static struct text_system Text_SDL = NULL, "sdl", }; -#endif /* separate done call-back for video-unrelated things (eg audio) */ static void SDL_done(void) @@ -229,25 +222,11 @@ static int SDL_priv_init(void) SDL_pre_init(); /* RENDER_DRIVER hint appears to be the hint for video init, * not CreateRenderer */ - if (!config.sdl_hwrend) { + if (!config.sdl_hwrend) SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software"); - /* unaccelerated fb doesn't work with Wayland */ -#if 0 - SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION, "0"); -#endif - } -#ifdef FE_NOMASK_ENV - /* workaround for non-fatal bug in Mesa on WSL2, see - https://github.com/dosemu2/dosemu2/issues/1987 - https://gitlab.freedesktop.org/mesa/mesa/-/issues/8818 */ - fedisableexcept(FE_DIVBYZERO); -#endif enter_priv_on(); ret = SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_EVENTS); leave_priv_setting(); -#ifdef FE_NOMASK_ENV - fesetenv(&dosemu_fenv); -#endif if (ret < 0) { error("SDL init: %s\n", SDL_GetError()); return -1; @@ -370,27 +349,21 @@ static int SDL_init(void) SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); #endif + rc = 0; + if (config.sdl_fonts && config.sdl_fonts[0] && !config.vga_fonts) + rc = SDL_text_init(); + use_ttf_font = rc; + use_bitmap_font = 1; + /* hints are set before renderer is created */ - if (config.X_bilin_filt) { - v_printf("SDL: enabling scaling filter \"best\"\n"); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); - } else if (config.X_lin_filt) { - v_printf("SDL: enabling scaling filter \"linear\"\n"); + if (config.X_lin_filt || config.X_bilin_filt) { + v_printf("SDL: enabling scaling filter\n"); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - } else { - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); } #if SDL_VERSION_ATLEAST(2,0,10) SDL_SetHint(SDL_HINT_RENDER_BATCHING, "1"); #endif - if (!config.X_noresize) - flags |= SDL_WINDOW_RESIZABLE; - if (!config.sdl_wcontrols) { - flags |= SDL_WINDOW_BORDERLESS; - border_on = 0; - } else { - border_on = 1; - } + flags |= SDL_WINDOW_RESIZABLE; #if 0 /* some SDL bug prevents resizing if the window was created with this * flag. And leaving full-screen mode doesn't help. @@ -451,12 +424,6 @@ static int SDL_init(void) if (config.X_mgrab_key && config.X_mgrab_key[0]) mgrab_key = SDL_GetKeyFromName(config.X_mgrab_key); - rc = 0; - if (config.sdl_fonts && config.sdl_fonts[0] && !config.vga_fonts) - rc = SDL_text_init(); - use_ttf_font = rc; - use_bitmap_font = 1; - #if THREADED_REND pthread_create(&rend_thr, NULL, render_thread, NULL); #if defined(HAVE_PTHREAD_SETNAME_NP) && defined(__GLIBC__) @@ -464,12 +431,6 @@ static int SDL_init(void) #endif #endif - if (config.sdl_clip_native) { - sdlclip_mode = 1; - sdlclip_setnative(sdlclip_mode); - SDL_change_config(CHG_TITLE, NULL); - } - c_printf("VID: SDL plugin initialization completed\n"); return 0; @@ -504,7 +465,6 @@ void SDL_close(void) for (i = 0; i < num_fdescs; i++) SDL_RWclose(sdl_fdesc[i].rw); TTF_Quit(); - FcFini(); } rng_destroy(&ttf_char_rng); #endif @@ -840,36 +800,19 @@ static void *render_thread(void *arg) int SDL_set_videomode(struct vid_mode_params vmp) { - SDL_DisplayMode mode; - int x_res, y_res, w_x_res, w_y_res; - v_printf ("SDL: set_videomode: 0x%x (%s), size %d x %d (%d x %d pixel)\n", video_mode, vmp.mode_class ? "GRAPH" : "TEXT", vmp.text_width, vmp.text_height, vmp.x_res, vmp.y_res); - if (win_width == vmp.x_res && win_height == vmp.y_res && - current_mode_class == vmp.mode_class) { + if (win_width == vmp.x_res && win_height == vmp.y_res) { v_printf("SDL: same mode, not changing\n"); return 1; } - if (vmp.mode_class == TEXT && !use_bitmap_font) { - x_res = 0; - y_res = 0; - w_x_res = vmp.text_width * font_width; - w_y_res = vmp.text_height * font_height; - } else { - x_res = vmp.x_res; - y_res = vmp.y_res; - w_x_res = vmp.w_x_res; - w_y_res = vmp.w_y_res; - } - SDL_GetDesktopDisplayMode(0, &mode); - if (mode.w >= w_x_res * 2.5 && mode.h >= w_y_res * 2.5) { - /* upscale a bit */ - w_x_res *= 2; - w_y_res *= 2; - } - SDL_change_mode(x_res, y_res, w_x_res, w_y_res); + if (vmp.mode_class == TEXT && !use_bitmap_font) + SDL_change_mode(0, 0, vmp.text_width * font_width, + vmp.text_height * font_height); + else + SDL_change_mode(vmp.x_res, vmp.y_res, vmp.w_x_res, vmp.w_y_res); current_mode_class = vmp.mode_class; return 1; @@ -934,10 +877,6 @@ static void SDL_change_mode(int x_res, int y_res, int w_x_res, int w_y_res) is_text = 1; } - /* remember desired params before adjusting to real window */ - desired_win_width = w_x_res; - desired_win_height = w_y_res; - flags = SDL_GetWindowFlags(window); if (!(flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN_DESKTOP))) { int nw_x_res, nw_y_res; @@ -956,7 +895,7 @@ static void SDL_change_mode(int x_res, int y_res, int w_x_res, int w_y_res) } /* set window size again to avoid crash, huh? */ SDL_SetWindowSize(window, w_x_res, w_y_res); - } else if (!config.X_fixed_aspect || is_text) { + } else { SDL_GetWindowSize(window, &w_x_res, &w_y_res); } if (config.X_fixed_aspect) { @@ -966,7 +905,9 @@ static void SDL_change_mode(int x_res, int y_res, int w_x_res, int w_y_res) SDL_RenderSetLogicalSize(renderer, 0, 0); } if (!initialized) { - sigset_t oset; +#ifdef HAVE_SDL2_IMAGE + SDL_Surface *icon; +#endif initialized = 1; if (config.X_fullscreen) { SDL_DisplayMode dm; @@ -977,17 +918,17 @@ static void SDL_change_mode(int x_res, int y_res, int w_x_res, int w_y_res) w_x_res = dm.w; w_y_res = dm.h; } - /* wayland may create threads here! */ - if (sig_threads_wa) - signal_block_async_nosig(&oset); - SDL_ShowWindow(window); - if (sig_threads_wa) - sigprocmask(SIG_SETMASK, &oset, NULL); - SDL_SetWindowResizable(window, !config.X_noresize); - if (config.X_fullscreen) { - SDL_RaiseWindow(window); - render_gain_focus(); +#ifdef HAVE_SDL2_IMAGE + icon = IMG_Load(DOSEMULIB_DEFAULT "/icons/dosemu.xpm"); + if (icon) { + SDL_SetWindowIcon(window, icon); + SDL_FreeSurface(icon); } +#endif + SDL_ShowWindow(window); + SDL_RaiseWindow(window); + if (config.X_fullscreen) + render_gain_focus(); } SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); SDL_RenderClear(renderer); @@ -1077,31 +1018,6 @@ static void window_grab(int on, int kbd) SDL_change_config(CHG_TITLE, NULL); } -static void window_size_changed(int w, int h) -{ - v_printf("SDL: window size changed to %dx%d\n", w, h); - real_win_width = w; - real_win_height = h; -#if defined(HAVE_SDL2_TTF) && defined(HAVE_FONTCONFIG) - if (MODE_CLASS() == TEXT) { - pthread_mutex_lock(&rend_mtx); - setup_ttf_winsize(w, h); - pthread_mutex_unlock(&rend_mtx); - } -#endif - - /* very strange things happen: if renderer size was explicitly - * set, SDL reports mouse coords relative to that. Otherwise - * it reports mouse coords relative to the window. */ - SDL_RenderGetLogicalSize(renderer, &m_x_res, &m_y_res); - if (!m_x_res || !m_y_res) { - m_x_res = w; - m_y_res = h; - } - update_mouse_coords(); - SDL_redraw(); -} - static void toggle_grab(int kbd) { window_grab(grab_active ^ 1, kbd); @@ -1109,8 +1025,6 @@ static void toggle_grab(int kbd) static void toggle_fullscreen_mode(void) { - if (!initialized) - return; config.X_fullscreen = !config.X_fullscreen; if (config.X_fullscreen) { v_printf("SDL: entering fullscreen mode\n"); @@ -1125,7 +1039,6 @@ static void toggle_fullscreen_mode(void) v_printf("SDL: entering windowed mode!\n"); pthread_mutex_lock(&rend_mtx); SDL_SetWindowFullscreen(window, 0); - SDL_SetWindowSize(window, desired_win_width, desired_win_height); pthread_mutex_unlock(&rend_mtx); if (force_grab && grab_active) { window_grab(0, 0); @@ -1145,8 +1058,6 @@ static int SDL_change_config(unsigned item, void *buf) v_printf("SDL: SDL_change_config: item = %d, buffer = %p\n", item, buf); - update_screen(); // process any pending updates - switch (item) { case CHG_TITLE: @@ -1177,7 +1088,7 @@ static int SDL_change_config(unsigned item, void *buf) case CHG_WINSIZE: case CHG_BACKGROUND_PAUSE: case GET_TITLE_APPNAME: - change_config(item, buf, grab_active, kbd_grab_active, sdlclip_mode); + change_config(item, buf, grab_active, kbd_grab_active); break; case CHG_FONT: { @@ -1265,10 +1176,10 @@ static char *get_selection_string(t_unicode sel_text[], const char *charset) return s; } -static int ctrl_pressed(void) +static int shift_pressed(void) { const Uint8 *state = SDL_GetKeyboardState(NULL); - return (state[SDL_SCANCODE_LCTRL] || state[SDL_SCANCODE_RCTRL]); + return (state[SDL_SCANCODE_LSHIFT] || state[SDL_SCANCODE_RSHIFT]); } static int window_has_focus(void) @@ -1278,32 +1189,16 @@ static int window_has_focus(void) } #endif /* CONFIG_SDL_SELECTION */ -static int alt_pressed(void) -{ - const Uint8 *state = SDL_GetKeyboardState(NULL); - return (state[SDL_SCANCODE_LALT] || state[SDL_SCANCODE_RALT]); -} - -static int shift_pressed(void) -{ - const Uint8 *state = SDL_GetKeyboardState(NULL); - return (state[SDL_SCANCODE_LSHIFT] || state[SDL_SCANCODE_RSHIFT]); -} - static void SDL_handle_events(void) { SDL_Event event; - sigset_t oset; assert(pthread_equal(pthread_self(), dosemu_pthread_self)); + if (render_is_updating()) + return; /* events may resize renderer, so lock */ pthread_mutex_lock(&rend_mtx); - /* SDL may spawn threads during event handling! */ - if (sig_threads_wa) - signal_block_async_nosig(&oset); SDL_PumpEvents(); - if (sig_threads_wa) - sigprocmask(SIG_SETMASK, &oset, NULL); pthread_mutex_unlock(&rend_mtx); /* SDL_PeepEvents() is thread-safe, SDL_PollEvent() - not */ while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, @@ -1324,14 +1219,33 @@ static void SDL_handle_events(void) if (config.X_background_pause && !dosemu_user_froze) freeze_dosemu(); break; -#if 0 - /* same as SIZE_CHANGED, but is often not sent */ + + case SDL_WINDOWEVENT_SIZE_CHANGED: + v_printf("SDL: window size changed to %dx%d\n", event.window.data1, event.window.data2); + break; + case SDL_WINDOWEVENT_RESIZED: v_printf("SDL: window resized %dx%d\n", event.window.data1, event.window.data2); - break; + real_win_width = event.window.data1; + real_win_height = event.window.data2; +#if defined(HAVE_SDL2_TTF) && defined(HAVE_FONTCONFIG) + if (MODE_CLASS() == TEXT) { + pthread_mutex_lock(&rend_mtx); + setup_ttf_winsize(event.window.data1, event.window.data2); + pthread_mutex_unlock(&rend_mtx); + } #endif - case SDL_WINDOWEVENT_SIZE_CHANGED: - window_size_changed(event.window.data1, event.window.data2); + + /* very strange things happen: if renderer size was explicitly + * set, SDL reports mouse coords relative to that. Otherwise + * it reports mouse coords relative to the window. */ + SDL_RenderGetLogicalSize(renderer, &m_x_res, &m_y_res); + if (!m_x_res || !m_y_res) { + m_x_res = event.window.data1; + m_y_res = event.window.data2; + } + update_mouse_coords(); + SDL_redraw(); break; case SDL_WINDOWEVENT_EXPOSED: @@ -1384,15 +1298,6 @@ static void SDL_handle_events(void) * the infinite switching loop. */ wait_kup = 1; break; - } else if (keysym.sym == SDLK_b && !config.X_fullscreen) { - border_on ^= 1; - SDL_SetWindowBordered(window, border_on); - break; - } else if (keysym.sym == SDLK_c) { - sdlclip_mode ^= 1; - sdlclip_setnative(sdlclip_mode); - SDL_change_config(CHG_TITLE, NULL); - break; } } if (vga.mode_class == TEXT && @@ -1445,48 +1350,23 @@ static void SDL_handle_events(void) #if CONFIG_SDL_SELECTION if (window_has_focus() && !shift_pressed()) { clear_selection_data(); - } else if (vga.mode_class == TEXT && !grab_active && !alt_pressed()) { - switch (event.button.button) { - case SDL_BUTTON_LEFT: + } else if (vga.mode_class == TEXT && !grab_active) { + if (event.button.button == SDL_BUTTON_LEFT) start_selection(x_to_col(event.button.x, m_x_res), - y_to_row(event.button.y, m_y_res), - ctrl_pressed()); - break; - case SDL_BUTTON_RIGHT: + y_to_row(event.button.y, m_y_res)); + else if (event.button.button == SDL_BUTTON_RIGHT) start_extend_selection(x_to_col(event.button.x, m_x_res), y_to_row(event.button.y, m_y_res)); - break; - case SDL_BUTTON_MIDDLE: { - char *paste = SDL_GetPrimarySelectionText(); + else if (event.button.button == SDL_BUTTON_MIDDLE) { + char *paste = SDL_GetClipboardText(); if (paste) { - if (paste[0]) { - set_shiftstate(0); - paste_text(paste, strlen(paste), "utf8"); - } - SDL_free(paste); + set_shiftstate(0); + paste_text(paste, strlen(paste), "utf8"); } - break; - } } break; } #endif /* CONFIG_SDL_SELECTION */ - - if (!sdlclip_mode && shift_pressed() && alt_pressed()) { - switch (event.button.button) { - case SDL_BUTTON_LEFT: - sdlclip_copy(window); - break; - case SDL_BUTTON_RIGHT: - sdlclip_clear(window); - break; - case SDL_BUTTON_MIDDLE: - sdlclip_paste(window); - break; - } - break; - } - mouse_move_buttons(!!(buttons & SDL_BUTTON(1)), !!(buttons & SDL_BUTTON(2)), !!(buttons & SDL_BUTTON(3)), @@ -1501,7 +1381,7 @@ static void SDL_handle_events(void) t_unicode *sel = end_selection(); if (sel) { char *send_text = get_selection_string(sel, "utf8"); - SDL_SetPrimarySelectionText(send_text); + SDL_SetClipboardText(send_text); free(send_text); } } @@ -1703,6 +1583,8 @@ static void SDL_draw_text_cursor(void *opaque, int x, int y, Bit8u attr, rect.h = font_height; d.rect.x = font_width * x; d.rect.y = font_height * y; + d.rect.w = font_width; + d.rect.h = font_height; } else { int cstart, cend; @@ -1719,9 +1601,9 @@ static void SDL_draw_text_cursor(void *opaque, int x, int y, Bit8u attr, rect.h = cend - cstart + 1; d.rect.x = font_width * x; d.rect.y = font_height * y + cstart; + d.rect.w = font_width; + d.rect.h = cend - cstart + 1; } - d.rect.w = rect.w; - d.rect.h = rect.h; pthread_mutex_lock(&rend_mtx); d.tex = CreateTextureTarget(rect.w, rect.h, 0); diff --git a/src/plugin/sdl/sdl.h b/src/plugin/sdl/sdl.h index ce5b217..d231446 100644 --- a/src/plugin/sdl/sdl.h +++ b/src/plugin/sdl/sdl.h @@ -1,17 +1,7 @@ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team". * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * for details see file COPYING in the DOSEMU distribution */ void SDL_pre_init(void); diff --git a/src/plugin/sdl1/Makefile b/src/plugin/sdl1/Makefile index d7aef02..b3e873e 100644 --- a/src/plugin/sdl1/Makefile +++ b/src/plugin/sdl1/Makefile @@ -18,16 +18,16 @@ OBJS=$(CFILES:.c=.o) OOBJS= DEPENDS=$(CFILES:.c=.d) -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_sdl1.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_sdl1.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(SDL_LIBS) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(SDL_LIBS) endif install: all diff --git a/src/plugin/sdl1/configure.ac b/src/plugin/sdl1/configure.ac index f41352a..716cb5e 100644 --- a/src/plugin/sdl1/configure.ac +++ b/src/plugin/sdl1/configure.ac @@ -2,9 +2,9 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT dnl Check for SDL SDL_VERSION=1.2.0 -PKG_CHECK_MODULES(SDL, [sdl >= $SDL_VERSION],, [ +AM_PATH_SDL($SDL_VERSION,, AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]) -]) +) AC_CONFIG_FILES([Makefile.conf]) diff --git a/src/plugin/sdl1/m4/sdl.m4 b/src/plugin/sdl1/m4/sdl.m4 new file mode 100644 index 0000000..639eb85 --- /dev/null +++ b/src/plugin/sdl1/m4/sdl.m4 @@ -0,0 +1,185 @@ +# Configure paths for SDL +# Sam Lantinga 9/21/99 +# stolen from Manish Singh +# stolen back from Frank Belew +# stolen from Manish Singh +# Shamelessly stolen from Owen Taylor + +# serial 1 + +dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS +dnl +AC_DEFUN([AM_PATH_SDL], +[dnl +dnl Get the cflags and libraries from the sdl-config script +dnl +AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], + sdl_prefix="$withval", sdl_prefix="") +AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], + sdl_exec_prefix="$withval", sdl_exec_prefix="") +AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], + , enable_sdltest=yes) + + if test x$sdl_exec_prefix != x ; then + sdl_config_args="$sdl_config_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_config_args="$sdl_config_args --prefix=$sdl_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_prefix/bin/sdl-config + fi + fi + + as_save_PATH="$PATH" + if test "x$prefix" != xNONE; then + PATH="$prefix/bin:$prefix/usr/bin:$PATH" + fi + AC_PATH_PROG(SDL_CONFIG, sdl-config, no, [$PATH]) + PATH="$as_save_PATH" + min_sdl_version=ifelse([$1], ,0.11.0,$1) + AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) + no_sdl="" + if test "$SDL_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL_CONFIG $sdl_config_args --cflags` + SDL_LIBS=`$SDL_CONFIG $sdl_config_args --libs` + + sdl_major_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdl_minor_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_CXXFLAGS="$CXXFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" +dnl +dnl Now check if the installed SDL is sufficiently new. (Also sanity +dnl checks the results of sdl-config to some extent +dnl + rm -f conf.sdltest + AC_TRY_RUN([ +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); + printf("*** to point to the correct copy of sdl-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + CXXFLAGS="$ac_save_CXXFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$SDL_CONFIG" = "no" ; then + echo "*** The sdl-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL_CONFIG environment variable to the" + echo "*** full path to sdl-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + AC_TRY_LINK([ +#include +#include "SDL.h" + +int main(int argc, char *argv[]) +{ return 0; } +#undef main +#define main K_and_R_C_main +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + CXXFLAGS="$ac_save_CXXFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) + rm -f conf.sdltest +]) diff --git a/src/plugin/sdl1/sdl.c b/src/plugin/sdl1/sdl.c index ca7a7f5..ea5c954 100644 --- a/src/plugin/sdl1/sdl.c +++ b/src/plugin/sdl1/sdl.c @@ -351,7 +351,7 @@ static void unlock_surface(void) static void SDL_reset_redraw_text_screen(void) { if(!is_mapped) return; -// reset_redraw_text_screen(); + reset_redraw_text_screen(); } static void SDL_redraw_text_screen(void) @@ -784,7 +784,7 @@ static void SDL_handle_events(void) if (x11.display && vga.mode_class == TEXT && !grab_active) { if (event.button.button == SDL_BUTTON_LEFT) start_selection(x_to_col(event.button.x, w_x_res), - y_to_row(event.button.y, w_y_res), 0); + y_to_row(event.button.y, w_y_res)); else if (event.button.button == SDL_BUTTON_RIGHT) start_extend_selection(x_to_col(event.button.x, w_x_res), y_to_row(event.button.y, w_y_res)); diff --git a/src/plugin/slirp/Makefile b/src/plugin/slirp/Makefile index 806c915..74cbc21 100644 --- a/src/plugin/slirp/Makefile +++ b/src/plugin/slirp/Makefile @@ -9,14 +9,14 @@ include ../plugins.mak ALL_CFLAGS += $(DL_CFLAGS) -I$(srcdir)/libvdeslirp CFILES = slirp.c libvdeslirp/libvdeslirp.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_slirp.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_slirp.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(SLIRP_LIBS) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(SLIRP_LIBS) endif diff --git a/src/plugin/slirp/configure.ac b/src/plugin/slirp/configure.ac index 44909b2..af4820b 100644 --- a/src/plugin/slirp/configure.ac +++ b/src/plugin/slirp/configure.ac @@ -3,4 +3,5 @@ AC_INIT AC_CONFIG_FILES([Makefile.conf]) PKG_CHECK_MODULES([SLIRP], [slirp >= 4.1.0],, AC_MSG_ERROR([slirp development library not installed])) +AC_SUBST(LIBS) AC_OUTPUT diff --git a/src/plugin/slirp/slirp.c b/src/plugin/slirp/slirp.c index 458ec4e..37f7c89 100644 --- a/src/plugin/slirp/slirp.c +++ b/src/plugin/slirp/slirp.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "libvdeslirp.h" #include "emu.h" #include "init.h" @@ -55,7 +56,7 @@ static int OpenNetworkLinkSlirp(const char *name, void (*cbk)(int, int)) sscanf(cmd, "%i %i", &pmin, &pmax); /* this is not a strict check, but default value is 1 0 */ if (pmin > pmax) - warn("userspace pings are disabled.\n" + error("userspace pings are disabled.\n" "\tTo enable them, do as root:\n" "\techo 0 65535 > /proc/sys/net/ipv4/ping_group_range\n"); pd_printf("PKT: ping_group_range is %s", cmd); diff --git a/src/plugin/svgalib/Makefile b/src/plugin/svgalib/Makefile index 37805d9..f72fe00 100644 --- a/src/plugin/svgalib/Makefile +++ b/src/plugin/svgalib/Makefile @@ -9,14 +9,14 @@ include ../plugins.mak ALL_CFLAGS+=$(DL_CFLAGS) CFILES=svgalib.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_svgalib.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_svgalib.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(SVGALIBLIB) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(SVGALIBLIB) endif diff --git a/src/plugin/svgalib/configure.ac b/src/plugin/svgalib/configure.ac index fc05b78..6dbea5b 100644 --- a/src/plugin/svgalib/configure.ac +++ b/src/plugin/svgalib/configure.ac @@ -21,4 +21,5 @@ if test "$use_svgalib" = "no"; then AC_MSG_ERROR([Your svgalib is too old.]) fi +AC_SUBST(LIBS) AC_OUTPUT diff --git a/src/plugin/term/Makefile b/src/plugin/term/Makefile index f61dac2..769b79d 100644 --- a/src/plugin/term/Makefile +++ b/src/plugin/term/Makefile @@ -9,16 +9,16 @@ include ../plugins.mak ALL_CFLAGS+=$(DL_CFLAGS) -DENABLE_SLFUTURE_CONST ALL_CPPFLAGS+=$(SLANGINC) -CFILES=term_core.c terminal.c keyb_slang.c mouse_xterm.c clip_term.c +CFILES=term_core.c terminal.c keyb_slang.c mouse_xterm.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_term.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_term.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $(OBJS) $(SLANGLIB) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $(OBJS) $(SLANGLIB) endif diff --git a/src/plugin/term/Makefile.conf.in b/src/plugin/term/Makefile.conf.in index b0381f4..b5b8a81 100644 --- a/src/plugin/term/Makefile.conf.in +++ b/src/plugin/term/Makefile.conf.in @@ -8,4 +8,4 @@ # This file is included by all Makefiles SLANGINC:=@SLANG_CFLAGS@ -SLANGLIB:=@SLANG_LIBS@ @LIBS@ +SLANGLIB:=@SLANG_LIBS@ diff --git a/src/plugin/term/clip_term.c b/src/plugin/term/clip_term.c deleted file mode 100644 index 3b1aed3..0000000 --- a/src/plugin/term/clip_term.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Purpose: terminal clipboard support (OSC-52) - * - * Note: only copy support for now (no paste) - * - * Author: @stsp - */ - -#include -#include -#include -#include "init.h" -#include "types.h" -#include "emu.h" -#include "clipboard.h" - -static int cterm_clear(void) -{ - cnn_clear(); - if (!config.clip_term) - return TRUE; - fprintf(stdout, "\033]52;c;-\a"); - fflush(stdout); - return TRUE; -} - -static int base64_encoded_size(int size) -{ - return (size + 2) / 3 * 4 + 1; -} - -static int cterm_write(int type, const char *p, int size) -{ - int cnt; - base64_encodestate state; - char *buf; - - if (!cnn_write(type, p, size)) - return FALSE; - if (!config.clip_term) - return TRUE; - size = strlen(clip_str) + 1; - buf = alloca(base64_encoded_size(size)); - fprintf(stdout, "\033]52;c;"); - base64_init_encodestate(&state); - cnt = base64_encode_block(clip_str, size, buf, &state); - if (cnt > 0) - fwrite(buf, 1, cnt, stdout); - cnt = base64_encode_blockend(buf, &state); - if (cnt > 0) - fwrite(buf, 1, cnt, stdout); - fprintf(stdout, "\a"); - fflush(stdout); - return TRUE; -} - -static int cterm_getsize(int type) -{ - return cnn_getsize(type); -} - -static int cterm_getdata(int type, char *p, int size) -{ - return cnn_getdata(type, p, size); -} - -static struct clipboard_system clip_term = -{ - cterm_clear, - cterm_write, - cterm_getsize, - cterm_getdata, - "terminal clipboard", -}; - -CONSTRUCTOR(static void clipterm_initialize(void)) -{ - register_clipboard_system(&clip_term); -} diff --git a/src/plugin/term/configure.ac b/src/plugin/term/configure.ac index dcfd140..46c6149 100644 --- a/src/plugin/term/configure.ac +++ b/src/plugin/term/configure.ac @@ -3,8 +3,6 @@ AC_INIT AC_CONFIG_FILES([Makefile.conf]) PKG_CHECK_MODULES([SLANG], [slang],, AC_MSG_ERROR([slang development headers not found])) -AC_CHECK_LIB(b64, base64_encode_block,, - AC_MSG_ERROR([b64 libs not found])) -AC_CHECK_HEADER([b64/cencode.h],, - AC_MSG_ERROR([b64 development headers not found])) +AC_SUBST(SLANG_CFLAGS) +AC_SUBST(SLANG_LIBS) AC_OUTPUT diff --git a/src/plugin/term/keyb_slang.c b/src/plugin/term/keyb_slang.c index 56ce00b..a38da6f 100644 --- a/src/plugin/term/keyb_slang.c +++ b/src/plugin/term/keyb_slang.c @@ -25,7 +25,6 @@ #include "video.h" #include "env_term.h" #include "translate/translate.h" -#include "ioselect.h" #ifndef SLANG_VERSION # define SLANG_VERSION 1 @@ -754,13 +753,10 @@ static int init_slang_keymaps(void) } /* - * Now add one more for the esc character so that sending it 3times - * sends it. - * Note that 2 escs are not enough because some terminals prefix - * Alt-fX sequences with 2 escs, see - * https://github.com/dosemu2/dosemu2/issues/1735 + * Now add one more for the esc character so that sending it twice sends + * it. */ - SLkm_define_key("^[^[^[", (VOID *) DKY_ESC, m); + SLkm_define_key("^[^[", (VOID *) DKY_ESC, m); if (slang_get_error()) return -1; @@ -803,20 +799,9 @@ static int read_some_keys(void) offs = keyb_state.kbp - keyb_state.kbbuf; cc = read(keyb_state.kbd_fd, &keyb_state.kbp[keyb_state.kbcount], KBBUF_SIZE - keyb_state.kbcount - offs); - ioselect_complete(keyb_state.kbd_fd); k_printf("KBD: cc found %d characters (Xlate)\n", cc); - if (cc > 0) { - if (debug_level('k') >= 9) { - int i; - k_printf("KBD: "); - for (i = 0; i < cc; i++) - k_printf("%x ", - keyb_state.kbp[ - keyb_state.kbcount + i]); - k_printf("\n"); - } + if (cc > 0) keyb_state.kbcount += cc; - } return cc; } @@ -1261,7 +1246,8 @@ static int get_modifiers(void) static void do_slang_pending(void) { - if (keyb_state.KeyNot_Ready && *keyb_state.kbp == 27) { + if (keyb_state.KeyNot_Ready && (keyb_state.Keystr_Len == 1) && + (*keyb_state.kbp == 27) && keyb_state.kbcount == 1) { #if 0 #define THE_TIMEOUT 750000L #else @@ -1269,27 +1255,11 @@ static void do_slang_pending(void) #endif hitimer_t t_dif = GETusTIME(0) - keyb_state.t_start; if (t_dif >= THE_TIMEOUT) { - t_unicode symbol = DKY_VOID; - size_t result; - switch (keyb_state.kbcount) { - case 1: - k_printf("KBD: slang got single ESC\n"); - slang_send_scancode(keyb_state.Shift_Flags, DKY_ESC); - keyb_state.KeyNot_Ready = 0; - break; - case 2: - result = charset_to_unicode(&keyb_state.translate_state, - &symbol, keyb_state.kbp + 1, keyb_state.kbcount - 1); - if (result > 0) - slang_send_scancode(keyb_state.Shift_Flags | ALT_MASK, symbol); - keyb_state.KeyNot_Ready = 0; - break; - default: - error("term: timeout after %i chars\n", keyb_state.kbcount); - break; - } - keyb_state.kbp += keyb_state.kbcount; - keyb_state.kbcount = 0; + k_printf("KBD: slang got single ESC\n"); + keyb_state.kbcount--; /* update count */ + keyb_state.kbp++; + slang_send_scancode(keyb_state.Shift_Flags, DKY_ESC); + keyb_state.KeyNot_Ready = 0; } } /* do_slang_getkeys() throttles pasting. So we call it here in @@ -1451,7 +1421,7 @@ static void _do_slang_getkeys(void) } } -static void do_slang_getkeys(int fd, void *arg) +static void do_slang_getkeys(void *arg) { _do_slang_getkeys(); } @@ -1498,7 +1468,7 @@ static void exit_pc_scancode_mode(void) * * DANG_END_FUNCTION */ -static void do_pc_scancode_getkeys(int fd, void *arg) +static void do_pc_scancode_getkeys(void *arg) { if (read_some_keys() <= 0) { return; @@ -1592,8 +1562,6 @@ static int slang_keyb_init(void) } sigalrm_register_handler(do_slang_pending); - /* Enable cursor keys (DECCKM) */ - printf("\033[?1h\r"); k_printf("KBD: slang_keyb_init() ok\n"); return TRUE; } @@ -1612,7 +1580,6 @@ static void slang_keyb_close(void) } term_close(); cleanup_charset_state(&keyb_state.translate_state); - printf("\033[?1l\r"); if (exitstr) printf("%s", exitstr); } diff --git a/src/plugin/term/mouse_xterm.c b/src/plugin/term/mouse_xterm.c index 45416e2..13e9465 100644 --- a/src/plugin/term/mouse_xterm.c +++ b/src/plugin/term/mouse_xterm.c @@ -19,7 +19,7 @@ static int use_sgr; -/* old XTERM MOUSE support by M.Laak */ +/* old XTERM MOUSE suport by M.Laak */ static int xtermmouse_get_event_old(Bit8u *kbp, int kbcount) { int btn; diff --git a/src/plugin/term/terminal.c b/src/plugin/term/terminal.c index 13237cb..18266f8 100644 --- a/src/plugin/term/terminal.c +++ b/src/plugin/term/terminal.c @@ -62,7 +62,6 @@ #include #include -#include "init.h" #include "bios.h" #include "emu.h" #include "memory.h" @@ -196,13 +195,9 @@ static void get_screen_size (void) { if (ws.ws_row > MAX_LINES || ws.ws_col > MAX_COLUMNS) { - error("Screen size is too large: %dx%d, max is %dx%d, ", + error("Screen size is too large: %dx%d, max is %dx%d\n", ws.ws_col, ws.ws_row, MAX_COLUMNS, MAX_LINES); - if (ws.ws_row > MAX_LINES) - ws.ws_row = MAX_LINES; - if (ws.ws_col > MAX_COLUMNS) - ws.ws_col = MAX_COLUMNS; - error("@Using %dx%d\n", ws.ws_col, ws.ws_row); + leavedos(0x63); } SLtt_Screen_Rows = ws.ws_row; SLtt_Screen_Cols = ws.ws_col; @@ -340,7 +335,7 @@ static void set_char_set (void) v_printf("mapping: %x -> %04x -> %.*s (len=%zu,acs=%x)\n", i, uni, (int)result, buff, result, result == 1 && buff[1] ? buff[1] : 0); - /* If we have any non control characters in 0x80 - 0x9f + /* If we have any non control charcters in 0x80 - 0x9f * set up the slang code up so we can send them. */ if (result > 1 || (buff[0] >= 0x80 && buff[0] <= 0x9f diff --git a/src/plugin/vde/Makefile b/src/plugin/vde/Makefile index 1aecba5..19920f8 100644 --- a/src/plugin/vde/Makefile +++ b/src/plugin/vde/Makefile @@ -9,14 +9,14 @@ include ../plugins.mak ALL_CFLAGS+=$(DL_CFLAGS) CFILES=vde.c -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS all: $(BINPATH)/bin/libplugin_vde.so ALL_CFLAGS += -fPIC endif include $(REALTOPDIR)/src/Makefile.common.post -ifeq ($(USE_DL_PLUGINS),1) +ifdef USE_DL_PLUGINS $(BINPATH)/bin/libplugin_vde.so: $(OBJS) | $(BINPATH)/bin - $(CC) $(LDFLAGS) -shared -o $@ $^ $(VDELIB) + $(CC) $(ALL_LDFLAGS) -shared -o $@ $^ $(VDELIB) endif diff --git a/src/plugin/vde/configure.ac b/src/plugin/vde/configure.ac index 55fe51e..c386bb3 100644 --- a/src/plugin/vde/configure.ac +++ b/src/plugin/vde/configure.ac @@ -3,4 +3,5 @@ AC_INIT AC_CONFIG_FILES([Makefile.conf]) AC_CHECK_LIB(vdeplug, vde_close,, AC_MSG_ERROR([vde development libs not found])) +AC_SUBST(LIBS) AC_OUTPUT diff --git a/src/plugin/vde/vde.c b/src/plugin/vde/vde.c index 5a3fe96..5803d71 100644 --- a/src/plugin/vde/vde.c +++ b/src/plugin/vde/vde.c @@ -39,7 +39,7 @@ static VDECONN *vde; static struct popen2 vdesw, slirp; static pthread_t open_thr; -static void vde_exit(void *arg) +static void vde_exit(void) { error("vde failed, exiting\n"); leavedos(35); @@ -153,6 +153,8 @@ out: goto fail0; } + sigchld_register_handler(vdesw.child_pid, vde_exit); + sigchld_register_handler(slirp.child_pid, vde_exit); pd_printf("PKT: started VDE at %s\n", nam); return nam; @@ -173,8 +175,6 @@ static void pkt_register_cb(void *arg) { struct cbk_data *cbkd = arg; vde = cbkd->vde; - sigchld_register_handler(vdesw.child_pid, vde_exit, NULL); - sigchld_register_handler(slirp.child_pid, vde_exit, NULL); cbkd->cbk(vde_datafd(cbkd->vde), 6); free(cbkd); } @@ -212,17 +212,12 @@ static void *open_thread(void *arg) static int OpenNetworkLinkVde(const char *name, void (*cbk)(int, int)) { - int ret; struct thr_data *thrd = malloc(sizeof(*thrd)); thrd->name = name; thrd->cbk = cbk; /* need to open in a separate thread as waiting for startup * may be long if the vde is unpatched */ - ret = pthread_create(&open_thr, NULL, open_thread, thrd); -#if defined(HAVE_PTHREAD_SETNAME_NP) && defined(__GLIBC__) - pthread_setname_np(open_thr, "dosemu: vde"); -#endif - return ret; + return pthread_create(&open_thr, NULL, open_thread, thrd); } static void CloseNetworkLinkVde(int pkt_fd) @@ -293,7 +288,6 @@ static struct pkt_ops vde_ops = { .get_MTU = GetDeviceMTUVde, .pkt_read = pkt_read_vde, .pkt_write = pkt_write_vde, - .flags = PFLG_ASYNC, }; CONSTRUCTOR(static void vde_init(void)) diff --git a/test/common_framework.py b/test/common_framework.py index 3f32e58..31daa11 100644 --- a/test/common_framework.py +++ b/test/common_framework.py @@ -5,7 +5,7 @@ import re import traceback import unittest -from datetime import datetime, timezone +from datetime import datetime from hashlib import sha1 from os import environ, rename from os.path import exists, join @@ -16,7 +16,6 @@ from subprocess import (Popen, call, check_call, check_output, DEVNULL, STDOUT, TimeoutExpired, CalledProcessError) from sys import exit, stdout, stderr, version_info from tarfile import open as topen -from time import sleep from unittest.util import strclass BINSDIR = "test-binaries" @@ -33,25 +32,6 @@ VFAT_FIMAGE = "/img/dosemu.img" VFAT_HELPER = "/bin/dosemu_fat_mount.sh" VFAT_MNTPNT = "/mnt/dosemu" -TAP_HELPER = "/bin/dosemu_tap_interface.sh" - -# Get any test binaries we need -TEST_BINARY_HOST = "http://www.spheresystems.co.uk/test-binaries" -TEST_BINARIES = ( - 'DR-DOS-7.01.tar', - 'FR-DOS-1.20.tar', - 'FR-DOS-1.30.tar', - 'MS-DOS-6.22.tar', - 'MS-DOS-7.00.tar', - 'MS-DOS-7.10.tar', - 'VARIOUS.tar', - 'TEST_CRYNWR.tar', - 'TEST_DOSLFN.tar', - 'TEST_EMM286.tar', - 'TEST_JAPHETH.tar', - 'TEST_MTCP.tar', -) - def mkstring(length): return ''.join(random.choice(string.hexdigits) for x in range(length)) @@ -75,7 +55,6 @@ def setup_vfat_mounted_image(self): except (CalledProcessError, TimeoutExpired): self.skipTest("mount helper ineffective") - def teardown_vfat_mounted_image(self): if not exists(VFAT_HELPER): self.skipTest("mount helper not installed") @@ -83,41 +62,8 @@ def teardown_vfat_mounted_image(self): check_call(["sudo", VFAT_HELPER, "umount"], stderr=STDOUT) -def setup_tap_interface(self): - if not exists(TAP_HELPER): - self.skipTest("tap interface helper not installed") - - check_call(["sudo", TAP_HELPER, "setup"], stderr=STDOUT) - - -def teardown_tap_interface(self): - if not exists(TAP_HELPER): - self.skipTest("tap interface helper not installed") - - check_call(["sudo", TAP_HELPER, "teardown"], stderr=STDOUT) - - -def get_test_binaries(): - tbindir = Path('.').resolve() / BINSDIR - - if tbindir.is_symlink(): - tbindir = tbindir.resolve() - if not tbindir.exists(): - tbindir.mkdir() - - for tfile in TEST_BINARIES: - if not Path(tbindir / tfile).exists(): - check_call([ - "wget", - "--no-verbose", - TEST_BINARY_HOST + '/' + tfile, - ], stderr=STDOUT, cwd=tbindir) - - class BaseTestCase(object): - attrs = [] - @classmethod def setUpClass(cls): cls.topdir = Path('.').resolve() @@ -154,26 +100,21 @@ class BaseTestCase(object): if cls.tarfile is None: cls.tarfile = cls.prettyname + ".tar" - if cls.tarfile != "": - if cls.tarfile not in TEST_BINARIES: - exit("\nUpdate tuple TEST_BINARIES for '%s'\n" % cls.prettyname) - if not exists(join(BINSDIR, cls.tarfile)): - exit("\nMissing test binary file, please run test/test_dos.py --get-test-binaries\n") + if cls.tarfile != "" and not exists(join(BINSDIR, cls.tarfile)): + raise unittest.SkipTest( + "TestCase %s binary not available" % cls.prettyname) @classmethod def tearDownClass(cls): pass def setUp(self): - # Process and skip actions - for key, value in self.actions.items(): - if re.match(key, self._testMethodName): - d = { - SKIP: "", - KNOWNFAIL: "known failure", - UNSUPPORTED: "unsupported", - } - self.skipTest(d.get(value, "unknown key")) + if self.actions.get(self._testMethodName) == SKIP: + self.skipTest("") + elif self.actions.get(self._testMethodName) == KNOWNFAIL: + self.skipTest("known failure") + elif self.actions.get(self._testMethodName) == UNSUPPORTED: + self.skipTest("unsupported") for p in self.imagedir.iterdir(): if p.is_dir(): @@ -189,7 +130,7 @@ class BaseTestCase(object): self.unTarOrSkip(self.tarfile, self.files) # Empty dosemu.conf for default values - self.mkfile("dosemu.conf", """\n""", self.imagedir) + self.mkfile("dosemu.conf", """$_force_fs_redirect = (off)\n""", self.imagedir) # Create startup files self.setUpDosAutoexec() @@ -223,8 +164,26 @@ class BaseTestCase(object): # helpers - def utcnow(self): - return datetime.now(timezone.utc) + def mkcom_with_gas(self, fname, content, dname=None): + if dname is None: + p = self.workdir + else: + p = Path(dname).resolve() + basename = str(p / fname) + + with open(basename + ".S", "w") as f: + f.write(content) + check_call(["as", "-o", basename + ".o", basename + ".S"]) + check_call(["gcc", + "-static", + "-Wl,--section-start=.text=0x100,-e,_start16", "-nostdlib", + "-o", basename + ".com.elf", + basename + ".o"]) + check_call(["objcopy", + "-j", ".text", "-O", "binary", + basename + ".com.elf", + basename + ".com"]) + check_call(["rm", basename + ".o", basename + ".com.elf"]) def mkcom_with_ia16(self, fname, content, dname=None): if dname is None: @@ -235,7 +194,7 @@ class BaseTestCase(object): with open(basename + ".c", "w") as f: f.write(content) - check_call(["ia16-elf-gcc", "-mcmodel=tiny", + check_call(["ia16-elf-gcc", "-mcmodel=small", "-o", basename + ".com", basename + ".c", "-li86"]) def mkexe_with_djgpp(self, fname, content, dname=None): @@ -250,18 +209,6 @@ class BaseTestCase(object): check_call(["i586-pc-msdosdjgpp-gcc", "-o", basename + ".exe", basename + ".c"]) - def mkcom_with_nasm(self, fname, content, dname=None): - if dname is None: - p = self.workdir - else: - p = Path(dname).resolve() - basename = p / fname - - sfile = basename.with_suffix('.asm') - sfile.write_text(content) - ofile = basename.with_suffix('.com') - check_call(["nasm", "-f", "bin", "-o", str(ofile), str(sfile)]) - def mkfile(self, fname, content, dname=None, mode="w", newline=None): if dname is None: p = self.workdir / fname @@ -367,44 +314,6 @@ class BaseTestCase(object): return name - def mkimage_vbr(self, fat, lfn=False, cwd=None): - if fat == "12": - bcount = 306 * 4 * 17 # type 1 - elif fat == "16": - bcount = 615 * 4 * 17 # type 2 - elif fat == "16b": - bcount = 900 * 15 * 17 # type 9 - elif fat == "32": - bcount = 1048576 # 1 GiB - else: - raise ValueError - name = "fat%s.img" % fat - - # mkfs.fat [OPTIONS] DEVICE [BLOCK-COUNT] - check_call( - ["mkfs", - "-t", ("fat", "vfat")[lfn], - "-C", - "-F", fat[0:2], - str(self.imagedir / name), - str(bcount)], - stdout=DEVNULL, stderr=DEVNULL) - - if cwd is None: - cwd = self.workdir - - # mcopy -i ../fat32.img -s -v * ::/ - srcs = [str(f) for f in cwd.glob('*')] - if srcs: # copy files - args = ["mcopy", - "-i", str(self.imagedir / name), - "-s"] - args += srcs - args += ["::/",] - check_call(args, cwd=cwd, stdout=DEVNULL, stderr=DEVNULL) - - return name - def patch(self, fname, changes, cwd=None): if cwd is None: cwd = self.workdir @@ -423,7 +332,7 @@ class BaseTestCase(object): f.write(c[2]) def runDosemu(self, cmd, opts=None, outfile=None, config=None, timeout=5, - eofisok=False, interactions=[]): + interactions=[]): # Note: if debugging is turned on then times increase 10x dbin = "bin/dosemu" args = ["-f", str(self.imagedir / "dosemu.conf"), @@ -453,10 +362,7 @@ class BaseTestCase(object): child.send(resp[1]) if outfile is None: ret += child.before.decode('ASCII', 'replace') - trms = ['rem end',] - if eofisok: - trms += [pexpect.EOF,] - child.expect(trms, timeout=timeout) + child.expect(['rem end'], timeout=timeout) if outfile is None: ret += child.before.decode('ASCII', 'replace') else: @@ -464,10 +370,6 @@ class BaseTestCase(object): ret = f.read() except pexpect.TIMEOUT: ret = 'Timeout' - tlog = self.logfiles['log'][0].read_text() - if '(gdb) Attaching to program' in tlog: - sleep(60) - self.shouldStop = True except pexpect.EOF: ret = 'EndOfFile' @@ -491,18 +393,14 @@ class BaseTestCase(object): if config is not None: self.mkfile("dosemu.conf", config, dname=self.imagedir, mode="a") - self.logfiles['xpt'][1] = "output.log" try: - ret = check_output(args, cwd=cwd, timeout=timeout, stderr=STDOUT).decode('ASCII') - self.logfiles['xpt'][0].write_text(ret) - except CalledProcessError as e: - ret = e.output.decode('ASCII') - ret += '\nNonZeroReturn:%d\n' % e.returncode - self.logfiles['xpt'][0].write_text(ret) + ret = check_output(args, cwd=cwd, timeout=timeout, stderr=STDOUT) + with open(self.logfiles['xpt'][0], "w") as f: + f.write(ret.decode('ASCII')) except TimeoutExpired as e: - ret = e.output.decode('ASCII') - ret += '\nTimeout:%d seconds\n' % timeout - self.logfiles['xpt'][0].write_text(ret) + ret = 'Timeout' + with open(self.logfiles['xpt'][0], "w") as f: + f.write(e.output.decode('ASCII')) return ret @@ -516,7 +414,7 @@ class MyTestResult(unittest.TextTestResult): def startTest(self, test): super(MyTestResult, self).startTest(test) - self.starttime = test.utcnow() + self.starttime = datetime.utcnow() name = test.id().replace('__main__', test.pname) test.logfiles = { @@ -526,15 +424,14 @@ class MyTestResult(unittest.TextTestResult): test.firstsub = True test.msg = None - def _is_relevant_tb_level(self, tb): - return '__unittest' in tb.tb_frame.f_globals - - def _count_relevant_tb_levels(self, tb): - length = 0 - while tb and not self._is_relevant_tb_level(tb): - length += 1 - tb = tb.tb_next - return length + def addFailure(self, test, err): + if self.showAll: + self.stream.writeln("FAIL") + elif self.dots: + self.stream.write('F') + self.stream.flush() + self.failures.append((test, self.gather_info_for_failure(err, test))) + self._mirrorOutput = True def gather_info_for_failure(self, err, test): """Gather traceback, stdout, stderr, dosemu and expect logs""" @@ -592,22 +489,11 @@ class MyTestResult(unittest.TextTestResult): return ''.join(msgLines) - def addFailure(self, test, err): - if self.showAll: - self.stream.writeln("FAIL") - elif self.dots: - self.stream.write('F') - self.stream.flush() - self.failures.append((test, self.gather_info_for_failure(err, test))) - self._mirrorOutput = True - if getattr(test, 'shouldStop', None) is not None: - self.shouldStop = test.shouldStop - def addSuccess(self, test): super(unittest.TextTestResult, self).addSuccess(test) if self.showAll: if self.starttime is not None: - duration = test.utcnow() - self.starttime + duration = datetime.utcnow() - self.starttime msg = (" " + test.msg) if test.msg else "" self.stream.writeln("ok ({:>6.2f}s){}".format(duration.total_seconds(), msg)) else: diff --git a/test/cpu/Makefile b/test/cpu/Makefile index c32e56e..9e04cc1 100644 --- a/test/cpu/Makefile +++ b/test/cpu/Makefile @@ -1,29 +1,15 @@ -include ../../Makefile.conf - +#CC=clang -fno-integrated-as -fverbose-asm +CC=gcc +CFLAGS=-Wall -O2 -g -fno-strict-aliasing -fno-pic -fno-pie -no-pie DJGPP = i586-pc-msdosdjgpp-gcc -DJFLAGS=-Wall -O2 -g -gdwarf-2 -fno-strict-aliasing -fno-pic -fno-pie -no-pie - -# Force CC to gcc, as clang compiled binary segfaults -CC = gcc - -CFLAGS := $(DJFLAGS) -ifeq ($(CC), clang) - CFLAGS += -fno-integrated-as -fverbose-asm -endif - -LDFLAGS= - SOURCES = test-i386.c test-i386-code16.S test-i386-vm86.S ALL_SRC = $(SOURCES) $(wildcard *.h) -all: dosbin.exe - -reffile.log: native32 - ./native32 --common-tests > $@ +all: dosbin.exe native32 native64 # i386/x86_64 emulation test (test various opcodes) */ dosbin.exe: $(ALL_SRC) - $(DJGPP) $(DJFLAGS) $(LDFLAGS) -o $@ $(SOURCES) -lm + $(DJGPP) $(CFLAGS) $(LDFLAGS) -o $@ $(SOURCES) -lm native32: $(ALL_SRC) $(CC) -m32 $(CFLAGS) $(LDFLAGS) -o $@ $(SOURCES) -lm diff --git a/test/cpu/reffile.log b/test/cpu/reffile.log deleted file mode 100644 index 05846c1..0000000 --- a/test/cpu/reffile.log +++ /dev/null @@ -1,4493 +0,0 @@ -addl A=12345678 B=0812fada R=1a475152 CCIN=0000 CC=0010 -addw A=12345678 B=0812fada R=12345152 CCIN=0000 CC=0011 -addb A=12345678 B=0812fada R=12345652 CCIN=0000 CC=0011 -addl A=00012341 B=00012341 R=00024682 CCIN=0000 CC=0004 -addw A=00012341 B=00012341 R=00014682 CCIN=0000 CC=0004 -addb A=00012341 B=00012341 R=00012382 CCIN=0000 CC=0884 -addl A=00012341 B=fffedcbf R=00000000 CCIN=0000 CC=0055 -addw A=00012341 B=fffedcbf R=00010000 CCIN=0000 CC=0055 -addb A=00012341 B=fffedcbf R=00012300 CCIN=0000 CC=0055 -addl A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -addw A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -addb A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -addl A=ffffffff B=ffffffff R=fffffffe CCIN=0000 CC=0091 -addw A=ffffffff B=ffffffff R=fffffffe CCIN=0000 CC=0091 -addb A=ffffffff B=ffffffff R=fffffffe CCIN=0000 CC=0091 -addl A=ffffffff B=00000001 R=00000000 CCIN=0000 CC=0055 -addw A=ffffffff B=00000001 R=ffff0000 CCIN=0000 CC=0055 -addb A=ffffffff B=00000001 R=ffffff00 CCIN=0000 CC=0055 -addl A=ffffffff B=00000002 R=00000001 CCIN=0000 CC=0011 -addw A=ffffffff B=00000002 R=ffff0001 CCIN=0000 CC=0011 -addb A=ffffffff B=00000002 R=ffffff01 CCIN=0000 CC=0011 -addl A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0004 -addw A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -addb A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -addl A=7fffffff B=00000001 R=80000000 CCIN=0000 CC=0894 -addw A=7fffffff B=00000001 R=7fff0000 CCIN=0000 CC=0055 -addb A=7fffffff B=00000001 R=7fffff00 CCIN=0000 CC=0055 -addl A=7fffffff B=ffffffff R=7ffffffe CCIN=0000 CC=0011 -addw A=7fffffff B=ffffffff R=7ffffffe CCIN=0000 CC=0091 -addb A=7fffffff B=ffffffff R=7ffffffe CCIN=0000 CC=0091 -addl A=80000000 B=ffffffff R=7fffffff CCIN=0000 CC=0805 -addw A=80000000 B=ffffffff R=8000ffff CCIN=0000 CC=0084 -addb A=80000000 B=ffffffff R=800000ff CCIN=0000 CC=0084 -addl A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0080 -addw A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0000 -addb A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0000 -addl A=80000000 B=fffffffe R=7ffffffe CCIN=0000 CC=0801 -addw A=80000000 B=fffffffe R=8000fffe CCIN=0000 CC=0080 -addb A=80000000 B=fffffffe R=800000fe CCIN=0000 CC=0080 -addl A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -addw A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -addb A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0084 -addl A=12347fff B=00000001 R=12348000 CCIN=0000 CC=0014 -addw A=12347fff B=00000001 R=12348000 CCIN=0000 CC=0894 -addb A=12347fff B=00000001 R=12347f00 CCIN=0000 CC=0055 -addl A=12347fff B=ffffffff R=12347ffe CCIN=0000 CC=0011 -addw A=12347fff B=ffffffff R=12347ffe CCIN=0000 CC=0011 -addb A=12347fff B=ffffffff R=12347ffe CCIN=0000 CC=0091 -addl A=12348000 B=ffffffff R=12347fff CCIN=0000 CC=0005 -addw A=12348000 B=ffffffff R=12347fff CCIN=0000 CC=0805 -addb A=12348000 B=ffffffff R=123480ff CCIN=0000 CC=0084 -addl A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0000 -addw A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0080 -addb A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0000 -addl A=12348000 B=fffffffe R=12347ffe CCIN=0000 CC=0001 -addw A=12348000 B=fffffffe R=12347ffe CCIN=0000 CC=0801 -addb A=12348000 B=fffffffe R=123480fe CCIN=0000 CC=0080 -addl A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -addw A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -addb A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -addl A=12347f7f B=00000001 R=12347f80 CCIN=0000 CC=0010 -addw A=12347f7f B=00000001 R=12347f80 CCIN=0000 CC=0010 -addb A=12347f7f B=00000001 R=12347f80 CCIN=0000 CC=0890 -addl A=12347f7f B=ffffffff R=12347f7e CCIN=0000 CC=0015 -addw A=12347f7f B=ffffffff R=12347f7e CCIN=0000 CC=0015 -addb A=12347f7f B=ffffffff R=12347f7e CCIN=0000 CC=0015 -addl A=12348080 B=ffffffff R=1234807f CCIN=0000 CC=0001 -addw A=12348080 B=ffffffff R=1234807f CCIN=0000 CC=0081 -addb A=12348080 B=ffffffff R=1234807f CCIN=0000 CC=0801 -addl A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0004 -addw A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0084 -addb A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0084 -addl A=12348080 B=fffffffe R=1234807e CCIN=0000 CC=0005 -addw A=12348080 B=fffffffe R=1234807e CCIN=0000 CC=0085 -addb A=12348080 B=fffffffe R=1234807e CCIN=0000 CC=0805 -subl A=12345678 B=0812fada R=0a215b9e CCIN=0000 CC=0010 -subw A=12345678 B=0812fada R=12345b9e CCIN=0000 CC=0011 -subb A=12345678 B=0812fada R=1234569e CCIN=0000 CC=0891 -subl A=00012341 B=00012341 R=00000000 CCIN=0000 CC=0044 -subw A=00012341 B=00012341 R=00010000 CCIN=0000 CC=0044 -subb A=00012341 B=00012341 R=00012300 CCIN=0000 CC=0044 -subl A=00012341 B=fffedcbf R=00024682 CCIN=0000 CC=0015 -subw A=00012341 B=fffedcbf R=00014682 CCIN=0000 CC=0015 -subb A=00012341 B=fffedcbf R=00012382 CCIN=0000 CC=0895 -subl A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -subw A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -subb A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -subl A=ffffffff B=ffffffff R=00000000 CCIN=0000 CC=0044 -subw A=ffffffff B=ffffffff R=ffff0000 CCIN=0000 CC=0044 -subb A=ffffffff B=ffffffff R=ffffff00 CCIN=0000 CC=0044 -subl A=ffffffff B=00000001 R=fffffffe CCIN=0000 CC=0080 -subw A=ffffffff B=00000001 R=fffffffe CCIN=0000 CC=0080 -subb A=ffffffff B=00000001 R=fffffffe CCIN=0000 CC=0080 -subl A=ffffffff B=00000002 R=fffffffd CCIN=0000 CC=0080 -subw A=ffffffff B=00000002 R=fffffffd CCIN=0000 CC=0080 -subb A=ffffffff B=00000002 R=fffffffd CCIN=0000 CC=0080 -subl A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0004 -subw A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -subb A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -subl A=7fffffff B=00000001 R=7ffffffe CCIN=0000 CC=0000 -subw A=7fffffff B=00000001 R=7ffffffe CCIN=0000 CC=0080 -subb A=7fffffff B=00000001 R=7ffffffe CCIN=0000 CC=0080 -subl A=7fffffff B=ffffffff R=80000000 CCIN=0000 CC=0885 -subw A=7fffffff B=ffffffff R=7fff0000 CCIN=0000 CC=0044 -subb A=7fffffff B=ffffffff R=7fffff00 CCIN=0000 CC=0044 -subl A=80000000 B=ffffffff R=80000001 CCIN=0000 CC=0091 -subw A=80000000 B=ffffffff R=80000001 CCIN=0000 CC=0011 -subb A=80000000 B=ffffffff R=80000001 CCIN=0000 CC=0011 -subl A=80000000 B=00000001 R=7fffffff CCIN=0000 CC=0814 -subw A=80000000 B=00000001 R=8000ffff CCIN=0000 CC=0095 -subb A=80000000 B=00000001 R=800000ff CCIN=0000 CC=0095 -subl A=80000000 B=fffffffe R=80000002 CCIN=0000 CC=0091 -subw A=80000000 B=fffffffe R=80000002 CCIN=0000 CC=0011 -subb A=80000000 B=fffffffe R=80000002 CCIN=0000 CC=0011 -subl A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -subw A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -subb A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0084 -subl A=12347fff B=00000001 R=12347ffe CCIN=0000 CC=0000 -subw A=12347fff B=00000001 R=12347ffe CCIN=0000 CC=0000 -subb A=12347fff B=00000001 R=12347ffe CCIN=0000 CC=0080 -subl A=12347fff B=ffffffff R=12348000 CCIN=0000 CC=0005 -subw A=12347fff B=ffffffff R=12348000 CCIN=0000 CC=0885 -subb A=12347fff B=ffffffff R=12347f00 CCIN=0000 CC=0044 -subl A=12348000 B=ffffffff R=12348001 CCIN=0000 CC=0011 -subw A=12348000 B=ffffffff R=12348001 CCIN=0000 CC=0091 -subb A=12348000 B=ffffffff R=12348001 CCIN=0000 CC=0011 -subl A=12348000 B=00000001 R=12347fff CCIN=0000 CC=0014 -subw A=12348000 B=00000001 R=12347fff CCIN=0000 CC=0814 -subb A=12348000 B=00000001 R=123480ff CCIN=0000 CC=0095 -subl A=12348000 B=fffffffe R=12348002 CCIN=0000 CC=0011 -subw A=12348000 B=fffffffe R=12348002 CCIN=0000 CC=0091 -subb A=12348000 B=fffffffe R=12348002 CCIN=0000 CC=0011 -subl A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -subw A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -subb A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -subl A=12347f7f B=00000001 R=12347f7e CCIN=0000 CC=0004 -subw A=12347f7f B=00000001 R=12347f7e CCIN=0000 CC=0004 -subb A=12347f7f B=00000001 R=12347f7e CCIN=0000 CC=0004 -subl A=12347f7f B=ffffffff R=12347f80 CCIN=0000 CC=0001 -subw A=12347f7f B=ffffffff R=12347f80 CCIN=0000 CC=0001 -subb A=12347f7f B=ffffffff R=12347f80 CCIN=0000 CC=0881 -subl A=12348080 B=ffffffff R=12348081 CCIN=0000 CC=0015 -subw A=12348080 B=ffffffff R=12348081 CCIN=0000 CC=0095 -subb A=12348080 B=ffffffff R=12348081 CCIN=0000 CC=0095 -subl A=12348080 B=00000001 R=1234807f CCIN=0000 CC=0010 -subw A=12348080 B=00000001 R=1234807f CCIN=0000 CC=0090 -subb A=12348080 B=00000001 R=1234807f CCIN=0000 CC=0810 -subl A=12348080 B=fffffffe R=12348082 CCIN=0000 CC=0015 -subw A=12348080 B=fffffffe R=12348082 CCIN=0000 CC=0095 -subb A=12348080 B=fffffffe R=12348082 CCIN=0000 CC=0095 -xorl A=12345678 B=0812fada R=1a26aca2 CCIN=0000 CC=0000 -xorw A=12345678 B=0812fada R=1234aca2 CCIN=0000 CC=0080 -xorb A=12345678 B=0812fada R=123456a2 CCIN=0000 CC=0080 -xorl A=00012341 B=00012341 R=00000000 CCIN=0000 CC=0044 -xorw A=00012341 B=00012341 R=00010000 CCIN=0000 CC=0044 -xorb A=00012341 B=00012341 R=00012300 CCIN=0000 CC=0044 -xorl A=00012341 B=fffedcbf R=fffffffe CCIN=0000 CC=0080 -xorw A=00012341 B=fffedcbf R=0001fffe CCIN=0000 CC=0080 -xorb A=00012341 B=fffedcbf R=000123fe CCIN=0000 CC=0080 -xorl A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -xorw A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -xorb A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -xorl A=ffffffff B=ffffffff R=00000000 CCIN=0000 CC=0044 -xorw A=ffffffff B=ffffffff R=ffff0000 CCIN=0000 CC=0044 -xorb A=ffffffff B=ffffffff R=ffffff00 CCIN=0000 CC=0044 -xorl A=ffffffff B=00000001 R=fffffffe CCIN=0000 CC=0080 -xorw A=ffffffff B=00000001 R=fffffffe CCIN=0000 CC=0080 -xorb A=ffffffff B=00000001 R=fffffffe CCIN=0000 CC=0080 -xorl A=ffffffff B=00000002 R=fffffffd CCIN=0000 CC=0080 -xorw A=ffffffff B=00000002 R=fffffffd CCIN=0000 CC=0080 -xorb A=ffffffff B=00000002 R=fffffffd CCIN=0000 CC=0080 -xorl A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0004 -xorw A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -xorb A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -xorl A=7fffffff B=00000001 R=7ffffffe CCIN=0000 CC=0000 -xorw A=7fffffff B=00000001 R=7ffffffe CCIN=0000 CC=0080 -xorb A=7fffffff B=00000001 R=7ffffffe CCIN=0000 CC=0080 -xorl A=7fffffff B=ffffffff R=80000000 CCIN=0000 CC=0084 -xorw A=7fffffff B=ffffffff R=7fff0000 CCIN=0000 CC=0044 -xorb A=7fffffff B=ffffffff R=7fffff00 CCIN=0000 CC=0044 -xorl A=80000000 B=ffffffff R=7fffffff CCIN=0000 CC=0004 -xorw A=80000000 B=ffffffff R=8000ffff CCIN=0000 CC=0084 -xorb A=80000000 B=ffffffff R=800000ff CCIN=0000 CC=0084 -xorl A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0080 -xorw A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0000 -xorb A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0000 -xorl A=80000000 B=fffffffe R=7ffffffe CCIN=0000 CC=0000 -xorw A=80000000 B=fffffffe R=8000fffe CCIN=0000 CC=0080 -xorb A=80000000 B=fffffffe R=800000fe CCIN=0000 CC=0080 -xorl A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -xorw A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -xorb A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0084 -xorl A=12347fff B=00000001 R=12347ffe CCIN=0000 CC=0000 -xorw A=12347fff B=00000001 R=12347ffe CCIN=0000 CC=0000 -xorb A=12347fff B=00000001 R=12347ffe CCIN=0000 CC=0080 -xorl A=12347fff B=ffffffff R=edcb8000 CCIN=0000 CC=0084 -xorw A=12347fff B=ffffffff R=12348000 CCIN=0000 CC=0084 -xorb A=12347fff B=ffffffff R=12347f00 CCIN=0000 CC=0044 -xorl A=12348000 B=ffffffff R=edcb7fff CCIN=0000 CC=0084 -xorw A=12348000 B=ffffffff R=12347fff CCIN=0000 CC=0004 -xorb A=12348000 B=ffffffff R=123480ff CCIN=0000 CC=0084 -xorl A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0000 -xorw A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0080 -xorb A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0000 -xorl A=12348000 B=fffffffe R=edcb7ffe CCIN=0000 CC=0080 -xorw A=12348000 B=fffffffe R=12347ffe CCIN=0000 CC=0000 -xorb A=12348000 B=fffffffe R=123480fe CCIN=0000 CC=0080 -xorl A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -xorw A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -xorb A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -xorl A=12347f7f B=00000001 R=12347f7e CCIN=0000 CC=0004 -xorw A=12347f7f B=00000001 R=12347f7e CCIN=0000 CC=0004 -xorb A=12347f7f B=00000001 R=12347f7e CCIN=0000 CC=0004 -xorl A=12347f7f B=ffffffff R=edcb8080 CCIN=0000 CC=0080 -xorw A=12347f7f B=ffffffff R=12348080 CCIN=0000 CC=0080 -xorb A=12347f7f B=ffffffff R=12347f80 CCIN=0000 CC=0080 -xorl A=12348080 B=ffffffff R=edcb7f7f CCIN=0000 CC=0080 -xorw A=12348080 B=ffffffff R=12347f7f CCIN=0000 CC=0000 -xorb A=12348080 B=ffffffff R=1234807f CCIN=0000 CC=0000 -xorl A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0004 -xorw A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0084 -xorb A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0084 -xorl A=12348080 B=fffffffe R=edcb7f7e CCIN=0000 CC=0084 -xorw A=12348080 B=fffffffe R=12347f7e CCIN=0000 CC=0004 -xorb A=12348080 B=fffffffe R=1234807e CCIN=0000 CC=0004 -andl A=12345678 B=0812fada R=00105258 CCIN=0000 CC=0000 -andw A=12345678 B=0812fada R=12345258 CCIN=0000 CC=0000 -andb A=12345678 B=0812fada R=12345658 CCIN=0000 CC=0000 -andl A=00012341 B=00012341 R=00012341 CCIN=0000 CC=0004 -andw A=00012341 B=00012341 R=00012341 CCIN=0000 CC=0004 -andb A=00012341 B=00012341 R=00012341 CCIN=0000 CC=0004 -andl A=00012341 B=fffedcbf R=00000001 CCIN=0000 CC=0000 -andw A=00012341 B=fffedcbf R=00010001 CCIN=0000 CC=0000 -andb A=00012341 B=fffedcbf R=00012301 CCIN=0000 CC=0000 -andl A=ffffffff B=00000000 R=00000000 CCIN=0000 CC=0044 -andw A=ffffffff B=00000000 R=ffff0000 CCIN=0000 CC=0044 -andb A=ffffffff B=00000000 R=ffffff00 CCIN=0000 CC=0044 -andl A=ffffffff B=ffffffff R=ffffffff CCIN=0000 CC=0084 -andw A=ffffffff B=ffffffff R=ffffffff CCIN=0000 CC=0084 -andb A=ffffffff B=ffffffff R=ffffffff CCIN=0000 CC=0084 -andl A=ffffffff B=00000001 R=00000001 CCIN=0000 CC=0000 -andw A=ffffffff B=00000001 R=ffff0001 CCIN=0000 CC=0000 -andb A=ffffffff B=00000001 R=ffffff01 CCIN=0000 CC=0000 -andl A=ffffffff B=00000002 R=00000002 CCIN=0000 CC=0000 -andw A=ffffffff B=00000002 R=ffff0002 CCIN=0000 CC=0000 -andb A=ffffffff B=00000002 R=ffffff02 CCIN=0000 CC=0000 -andl A=7fffffff B=00000000 R=00000000 CCIN=0000 CC=0044 -andw A=7fffffff B=00000000 R=7fff0000 CCIN=0000 CC=0044 -andb A=7fffffff B=00000000 R=7fffff00 CCIN=0000 CC=0044 -andl A=7fffffff B=00000001 R=00000001 CCIN=0000 CC=0000 -andw A=7fffffff B=00000001 R=7fff0001 CCIN=0000 CC=0000 -andb A=7fffffff B=00000001 R=7fffff01 CCIN=0000 CC=0000 -andl A=7fffffff B=ffffffff R=7fffffff CCIN=0000 CC=0004 -andw A=7fffffff B=ffffffff R=7fffffff CCIN=0000 CC=0084 -andb A=7fffffff B=ffffffff R=7fffffff CCIN=0000 CC=0084 -andl A=80000000 B=ffffffff R=80000000 CCIN=0000 CC=0084 -andw A=80000000 B=ffffffff R=80000000 CCIN=0000 CC=0044 -andb A=80000000 B=ffffffff R=80000000 CCIN=0000 CC=0044 -andl A=80000000 B=00000001 R=00000000 CCIN=0000 CC=0044 -andw A=80000000 B=00000001 R=80000000 CCIN=0000 CC=0044 -andb A=80000000 B=00000001 R=80000000 CCIN=0000 CC=0044 -andl A=80000000 B=fffffffe R=80000000 CCIN=0000 CC=0084 -andw A=80000000 B=fffffffe R=80000000 CCIN=0000 CC=0044 -andb A=80000000 B=fffffffe R=80000000 CCIN=0000 CC=0044 -andl A=12347fff B=00000000 R=00000000 CCIN=0000 CC=0044 -andw A=12347fff B=00000000 R=12340000 CCIN=0000 CC=0044 -andb A=12347fff B=00000000 R=12347f00 CCIN=0000 CC=0044 -andl A=12347fff B=00000001 R=00000001 CCIN=0000 CC=0000 -andw A=12347fff B=00000001 R=12340001 CCIN=0000 CC=0000 -andb A=12347fff B=00000001 R=12347f01 CCIN=0000 CC=0000 -andl A=12347fff B=ffffffff R=12347fff CCIN=0000 CC=0004 -andw A=12347fff B=ffffffff R=12347fff CCIN=0000 CC=0004 -andb A=12347fff B=ffffffff R=12347fff CCIN=0000 CC=0084 -andl A=12348000 B=ffffffff R=12348000 CCIN=0000 CC=0004 -andw A=12348000 B=ffffffff R=12348000 CCIN=0000 CC=0084 -andb A=12348000 B=ffffffff R=12348000 CCIN=0000 CC=0044 -andl A=12348000 B=00000001 R=00000000 CCIN=0000 CC=0044 -andw A=12348000 B=00000001 R=12340000 CCIN=0000 CC=0044 -andb A=12348000 B=00000001 R=12348000 CCIN=0000 CC=0044 -andl A=12348000 B=fffffffe R=12348000 CCIN=0000 CC=0004 -andw A=12348000 B=fffffffe R=12348000 CCIN=0000 CC=0084 -andb A=12348000 B=fffffffe R=12348000 CCIN=0000 CC=0044 -andl A=12347f7f B=00000000 R=00000000 CCIN=0000 CC=0044 -andw A=12347f7f B=00000000 R=12340000 CCIN=0000 CC=0044 -andb A=12347f7f B=00000000 R=12347f00 CCIN=0000 CC=0044 -andl A=12347f7f B=00000001 R=00000001 CCIN=0000 CC=0000 -andw A=12347f7f B=00000001 R=12340001 CCIN=0000 CC=0000 -andb A=12347f7f B=00000001 R=12347f01 CCIN=0000 CC=0000 -andl A=12347f7f B=ffffffff R=12347f7f CCIN=0000 CC=0000 -andw A=12347f7f B=ffffffff R=12347f7f CCIN=0000 CC=0000 -andb A=12347f7f B=ffffffff R=12347f7f CCIN=0000 CC=0000 -andl A=12348080 B=ffffffff R=12348080 CCIN=0000 CC=0000 -andw A=12348080 B=ffffffff R=12348080 CCIN=0000 CC=0080 -andb A=12348080 B=ffffffff R=12348080 CCIN=0000 CC=0080 -andl A=12348080 B=00000001 R=00000000 CCIN=0000 CC=0044 -andw A=12348080 B=00000001 R=12340000 CCIN=0000 CC=0044 -andb A=12348080 B=00000001 R=12348000 CCIN=0000 CC=0044 -andl A=12348080 B=fffffffe R=12348080 CCIN=0000 CC=0000 -andw A=12348080 B=fffffffe R=12348080 CCIN=0000 CC=0080 -andb A=12348080 B=fffffffe R=12348080 CCIN=0000 CC=0080 -orl A=12345678 B=0812fada R=1a36fefa CCIN=0000 CC=0004 -orw A=12345678 B=0812fada R=1234fefa CCIN=0000 CC=0084 -orb A=12345678 B=0812fada R=123456fa CCIN=0000 CC=0084 -orl A=00012341 B=00012341 R=00012341 CCIN=0000 CC=0004 -orw A=00012341 B=00012341 R=00012341 CCIN=0000 CC=0004 -orb A=00012341 B=00012341 R=00012341 CCIN=0000 CC=0004 -orl A=00012341 B=fffedcbf R=ffffffff CCIN=0000 CC=0084 -orw A=00012341 B=fffedcbf R=0001ffff CCIN=0000 CC=0084 -orb A=00012341 B=fffedcbf R=000123ff CCIN=0000 CC=0084 -orl A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -orw A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -orb A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -orl A=ffffffff B=ffffffff R=ffffffff CCIN=0000 CC=0084 -orw A=ffffffff B=ffffffff R=ffffffff CCIN=0000 CC=0084 -orb A=ffffffff B=ffffffff R=ffffffff CCIN=0000 CC=0084 -orl A=ffffffff B=00000001 R=ffffffff CCIN=0000 CC=0084 -orw A=ffffffff B=00000001 R=ffffffff CCIN=0000 CC=0084 -orb A=ffffffff B=00000001 R=ffffffff CCIN=0000 CC=0084 -orl A=ffffffff B=00000002 R=ffffffff CCIN=0000 CC=0084 -orw A=ffffffff B=00000002 R=ffffffff CCIN=0000 CC=0084 -orb A=ffffffff B=00000002 R=ffffffff CCIN=0000 CC=0084 -orl A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0004 -orw A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -orb A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -orl A=7fffffff B=00000001 R=7fffffff CCIN=0000 CC=0004 -orw A=7fffffff B=00000001 R=7fffffff CCIN=0000 CC=0084 -orb A=7fffffff B=00000001 R=7fffffff CCIN=0000 CC=0084 -orl A=7fffffff B=ffffffff R=ffffffff CCIN=0000 CC=0084 -orw A=7fffffff B=ffffffff R=7fffffff CCIN=0000 CC=0084 -orb A=7fffffff B=ffffffff R=7fffffff CCIN=0000 CC=0084 -orl A=80000000 B=ffffffff R=ffffffff CCIN=0000 CC=0084 -orw A=80000000 B=ffffffff R=8000ffff CCIN=0000 CC=0084 -orb A=80000000 B=ffffffff R=800000ff CCIN=0000 CC=0084 -orl A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0080 -orw A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0000 -orb A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0000 -orl A=80000000 B=fffffffe R=fffffffe CCIN=0000 CC=0080 -orw A=80000000 B=fffffffe R=8000fffe CCIN=0000 CC=0080 -orb A=80000000 B=fffffffe R=800000fe CCIN=0000 CC=0080 -orl A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -orw A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -orb A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0084 -orl A=12347fff B=00000001 R=12347fff CCIN=0000 CC=0004 -orw A=12347fff B=00000001 R=12347fff CCIN=0000 CC=0004 -orb A=12347fff B=00000001 R=12347fff CCIN=0000 CC=0084 -orl A=12347fff B=ffffffff R=ffffffff CCIN=0000 CC=0084 -orw A=12347fff B=ffffffff R=1234ffff CCIN=0000 CC=0084 -orb A=12347fff B=ffffffff R=12347fff CCIN=0000 CC=0084 -orl A=12348000 B=ffffffff R=ffffffff CCIN=0000 CC=0084 -orw A=12348000 B=ffffffff R=1234ffff CCIN=0000 CC=0084 -orb A=12348000 B=ffffffff R=123480ff CCIN=0000 CC=0084 -orl A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0000 -orw A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0080 -orb A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0000 -orl A=12348000 B=fffffffe R=fffffffe CCIN=0000 CC=0080 -orw A=12348000 B=fffffffe R=1234fffe CCIN=0000 CC=0080 -orb A=12348000 B=fffffffe R=123480fe CCIN=0000 CC=0080 -orl A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -orw A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -orb A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -orl A=12347f7f B=00000001 R=12347f7f CCIN=0000 CC=0000 -orw A=12347f7f B=00000001 R=12347f7f CCIN=0000 CC=0000 -orb A=12347f7f B=00000001 R=12347f7f CCIN=0000 CC=0000 -orl A=12347f7f B=ffffffff R=ffffffff CCIN=0000 CC=0084 -orw A=12347f7f B=ffffffff R=1234ffff CCIN=0000 CC=0084 -orb A=12347f7f B=ffffffff R=12347fff CCIN=0000 CC=0084 -orl A=12348080 B=ffffffff R=ffffffff CCIN=0000 CC=0084 -orw A=12348080 B=ffffffff R=1234ffff CCIN=0000 CC=0084 -orb A=12348080 B=ffffffff R=123480ff CCIN=0000 CC=0084 -orl A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0004 -orw A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0084 -orb A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0084 -orl A=12348080 B=fffffffe R=fffffffe CCIN=0000 CC=0080 -orw A=12348080 B=fffffffe R=1234fffe CCIN=0000 CC=0080 -orb A=12348080 B=fffffffe R=123480fe CCIN=0000 CC=0080 -cmpl A=12345678 B=0812fada R=12345678 CCIN=0000 CC=0010 -cmpw A=12345678 B=0812fada R=12345678 CCIN=0000 CC=0011 -cmpb A=12345678 B=0812fada R=12345678 CCIN=0000 CC=0891 -cmpl A=00012341 B=00012341 R=00012341 CCIN=0000 CC=0044 -cmpw A=00012341 B=00012341 R=00012341 CCIN=0000 CC=0044 -cmpb A=00012341 B=00012341 R=00012341 CCIN=0000 CC=0044 -cmpl A=00012341 B=fffedcbf R=00012341 CCIN=0000 CC=0015 -cmpw A=00012341 B=fffedcbf R=00012341 CCIN=0000 CC=0015 -cmpb A=00012341 B=fffedcbf R=00012341 CCIN=0000 CC=0895 -cmpl A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -cmpw A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -cmpb A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -cmpl A=ffffffff B=ffffffff R=ffffffff CCIN=0000 CC=0044 -cmpw A=ffffffff B=ffffffff R=ffffffff CCIN=0000 CC=0044 -cmpb A=ffffffff B=ffffffff R=ffffffff CCIN=0000 CC=0044 -cmpl A=ffffffff B=00000001 R=ffffffff CCIN=0000 CC=0080 -cmpw A=ffffffff B=00000001 R=ffffffff CCIN=0000 CC=0080 -cmpb A=ffffffff B=00000001 R=ffffffff CCIN=0000 CC=0080 -cmpl A=ffffffff B=00000002 R=ffffffff CCIN=0000 CC=0080 -cmpw A=ffffffff B=00000002 R=ffffffff CCIN=0000 CC=0080 -cmpb A=ffffffff B=00000002 R=ffffffff CCIN=0000 CC=0080 -cmpl A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0004 -cmpw A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -cmpb A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -cmpl A=7fffffff B=00000001 R=7fffffff CCIN=0000 CC=0000 -cmpw A=7fffffff B=00000001 R=7fffffff CCIN=0000 CC=0080 -cmpb A=7fffffff B=00000001 R=7fffffff CCIN=0000 CC=0080 -cmpl A=7fffffff B=ffffffff R=7fffffff CCIN=0000 CC=0885 -cmpw A=7fffffff B=ffffffff R=7fffffff CCIN=0000 CC=0044 -cmpb A=7fffffff B=ffffffff R=7fffffff CCIN=0000 CC=0044 -cmpl A=80000000 B=ffffffff R=80000000 CCIN=0000 CC=0091 -cmpw A=80000000 B=ffffffff R=80000000 CCIN=0000 CC=0011 -cmpb A=80000000 B=ffffffff R=80000000 CCIN=0000 CC=0011 -cmpl A=80000000 B=00000001 R=80000000 CCIN=0000 CC=0814 -cmpw A=80000000 B=00000001 R=80000000 CCIN=0000 CC=0095 -cmpb A=80000000 B=00000001 R=80000000 CCIN=0000 CC=0095 -cmpl A=80000000 B=fffffffe R=80000000 CCIN=0000 CC=0091 -cmpw A=80000000 B=fffffffe R=80000000 CCIN=0000 CC=0011 -cmpb A=80000000 B=fffffffe R=80000000 CCIN=0000 CC=0011 -cmpl A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -cmpw A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -cmpb A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0084 -cmpl A=12347fff B=00000001 R=12347fff CCIN=0000 CC=0000 -cmpw A=12347fff B=00000001 R=12347fff CCIN=0000 CC=0000 -cmpb A=12347fff B=00000001 R=12347fff CCIN=0000 CC=0080 -cmpl A=12347fff B=ffffffff R=12347fff CCIN=0000 CC=0005 -cmpw A=12347fff B=ffffffff R=12347fff CCIN=0000 CC=0885 -cmpb A=12347fff B=ffffffff R=12347fff CCIN=0000 CC=0044 -cmpl A=12348000 B=ffffffff R=12348000 CCIN=0000 CC=0011 -cmpw A=12348000 B=ffffffff R=12348000 CCIN=0000 CC=0091 -cmpb A=12348000 B=ffffffff R=12348000 CCIN=0000 CC=0011 -cmpl A=12348000 B=00000001 R=12348000 CCIN=0000 CC=0014 -cmpw A=12348000 B=00000001 R=12348000 CCIN=0000 CC=0814 -cmpb A=12348000 B=00000001 R=12348000 CCIN=0000 CC=0095 -cmpl A=12348000 B=fffffffe R=12348000 CCIN=0000 CC=0011 -cmpw A=12348000 B=fffffffe R=12348000 CCIN=0000 CC=0091 -cmpb A=12348000 B=fffffffe R=12348000 CCIN=0000 CC=0011 -cmpl A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -cmpw A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -cmpb A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -cmpl A=12347f7f B=00000001 R=12347f7f CCIN=0000 CC=0004 -cmpw A=12347f7f B=00000001 R=12347f7f CCIN=0000 CC=0004 -cmpb A=12347f7f B=00000001 R=12347f7f CCIN=0000 CC=0004 -cmpl A=12347f7f B=ffffffff R=12347f7f CCIN=0000 CC=0001 -cmpw A=12347f7f B=ffffffff R=12347f7f CCIN=0000 CC=0001 -cmpb A=12347f7f B=ffffffff R=12347f7f CCIN=0000 CC=0881 -cmpl A=12348080 B=ffffffff R=12348080 CCIN=0000 CC=0015 -cmpw A=12348080 B=ffffffff R=12348080 CCIN=0000 CC=0095 -cmpb A=12348080 B=ffffffff R=12348080 CCIN=0000 CC=0095 -cmpl A=12348080 B=00000001 R=12348080 CCIN=0000 CC=0010 -cmpw A=12348080 B=00000001 R=12348080 CCIN=0000 CC=0090 -cmpb A=12348080 B=00000001 R=12348080 CCIN=0000 CC=0810 -cmpl A=12348080 B=fffffffe R=12348080 CCIN=0000 CC=0015 -cmpw A=12348080 B=fffffffe R=12348080 CCIN=0000 CC=0095 -cmpb A=12348080 B=fffffffe R=12348080 CCIN=0000 CC=0095 -adcl A=12345678 B=0812fada R=1a475152 CCIN=0000 CC=0010 -adcw A=12345678 B=0812fada R=12345152 CCIN=0000 CC=0011 -adcb A=12345678 B=0812fada R=12345652 CCIN=0000 CC=0011 -adcl A=12345678 B=0812fada R=1a475153 CCIN=0001 CC=0014 -adcw A=12345678 B=0812fada R=12345153 CCIN=0001 CC=0015 -adcb A=12345678 B=0812fada R=12345653 CCIN=0001 CC=0015 -adcl A=00012341 B=00012341 R=00024682 CCIN=0000 CC=0004 -adcw A=00012341 B=00012341 R=00014682 CCIN=0000 CC=0004 -adcb A=00012341 B=00012341 R=00012382 CCIN=0000 CC=0884 -adcl A=00012341 B=00012341 R=00024683 CCIN=0001 CC=0000 -adcw A=00012341 B=00012341 R=00014683 CCIN=0001 CC=0000 -adcb A=00012341 B=00012341 R=00012383 CCIN=0001 CC=0880 -adcl A=00012341 B=fffedcbf R=00000000 CCIN=0000 CC=0055 -adcw A=00012341 B=fffedcbf R=00010000 CCIN=0000 CC=0055 -adcb A=00012341 B=fffedcbf R=00012300 CCIN=0000 CC=0055 -adcl A=00012341 B=fffedcbf R=00000001 CCIN=0001 CC=0011 -adcw A=00012341 B=fffedcbf R=00010001 CCIN=0001 CC=0011 -adcb A=00012341 B=fffedcbf R=00012301 CCIN=0001 CC=0011 -adcl A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -adcw A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -adcb A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -adcl A=ffffffff B=00000000 R=00000000 CCIN=0001 CC=0055 -adcw A=ffffffff B=00000000 R=ffff0000 CCIN=0001 CC=0055 -adcb A=ffffffff B=00000000 R=ffffff00 CCIN=0001 CC=0055 -adcl A=ffffffff B=ffffffff R=fffffffe CCIN=0000 CC=0091 -adcw A=ffffffff B=ffffffff R=fffffffe CCIN=0000 CC=0091 -adcb A=ffffffff B=ffffffff R=fffffffe CCIN=0000 CC=0091 -adcl A=ffffffff B=ffffffff R=ffffffff CCIN=0001 CC=0095 -adcw A=ffffffff B=ffffffff R=ffffffff CCIN=0001 CC=0095 -adcb A=ffffffff B=ffffffff R=ffffffff CCIN=0001 CC=0095 -adcl A=ffffffff B=00000001 R=00000000 CCIN=0000 CC=0055 -adcw A=ffffffff B=00000001 R=ffff0000 CCIN=0000 CC=0055 -adcb A=ffffffff B=00000001 R=ffffff00 CCIN=0000 CC=0055 -adcl A=ffffffff B=00000001 R=00000001 CCIN=0001 CC=0011 -adcw A=ffffffff B=00000001 R=ffff0001 CCIN=0001 CC=0011 -adcb A=ffffffff B=00000001 R=ffffff01 CCIN=0001 CC=0011 -adcl A=ffffffff B=00000002 R=00000001 CCIN=0000 CC=0011 -adcw A=ffffffff B=00000002 R=ffff0001 CCIN=0000 CC=0011 -adcb A=ffffffff B=00000002 R=ffffff01 CCIN=0000 CC=0011 -adcl A=ffffffff B=00000002 R=00000002 CCIN=0001 CC=0011 -adcw A=ffffffff B=00000002 R=ffff0002 CCIN=0001 CC=0011 -adcb A=ffffffff B=00000002 R=ffffff02 CCIN=0001 CC=0011 -adcl A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0004 -adcw A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -adcb A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -adcl A=7fffffff B=00000000 R=80000000 CCIN=0001 CC=0894 -adcw A=7fffffff B=00000000 R=7fff0000 CCIN=0001 CC=0055 -adcb A=7fffffff B=00000000 R=7fffff00 CCIN=0001 CC=0055 -adcl A=7fffffff B=00000001 R=80000000 CCIN=0000 CC=0894 -adcw A=7fffffff B=00000001 R=7fff0000 CCIN=0000 CC=0055 -adcb A=7fffffff B=00000001 R=7fffff00 CCIN=0000 CC=0055 -adcl A=7fffffff B=00000001 R=80000001 CCIN=0001 CC=0890 -adcw A=7fffffff B=00000001 R=7fff0001 CCIN=0001 CC=0011 -adcb A=7fffffff B=00000001 R=7fffff01 CCIN=0001 CC=0011 -adcl A=7fffffff B=ffffffff R=7ffffffe CCIN=0000 CC=0011 -adcw A=7fffffff B=ffffffff R=7ffffffe CCIN=0000 CC=0091 -adcb A=7fffffff B=ffffffff R=7ffffffe CCIN=0000 CC=0091 -adcl A=7fffffff B=ffffffff R=7fffffff CCIN=0001 CC=0015 -adcw A=7fffffff B=ffffffff R=7fffffff CCIN=0001 CC=0095 -adcb A=7fffffff B=ffffffff R=7fffffff CCIN=0001 CC=0095 -adcl A=80000000 B=ffffffff R=7fffffff CCIN=0000 CC=0805 -adcw A=80000000 B=ffffffff R=8000ffff CCIN=0000 CC=0084 -adcb A=80000000 B=ffffffff R=800000ff CCIN=0000 CC=0084 -adcl A=80000000 B=ffffffff R=80000000 CCIN=0001 CC=0095 -adcw A=80000000 B=ffffffff R=80000000 CCIN=0001 CC=0055 -adcb A=80000000 B=ffffffff R=80000000 CCIN=0001 CC=0055 -adcl A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0080 -adcw A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0000 -adcb A=80000000 B=00000001 R=80000001 CCIN=0000 CC=0000 -adcl A=80000000 B=00000001 R=80000002 CCIN=0001 CC=0080 -adcw A=80000000 B=00000001 R=80000002 CCIN=0001 CC=0000 -adcb A=80000000 B=00000001 R=80000002 CCIN=0001 CC=0000 -adcl A=80000000 B=fffffffe R=7ffffffe CCIN=0000 CC=0801 -adcw A=80000000 B=fffffffe R=8000fffe CCIN=0000 CC=0080 -adcb A=80000000 B=fffffffe R=800000fe CCIN=0000 CC=0080 -adcl A=80000000 B=fffffffe R=7fffffff CCIN=0001 CC=0805 -adcw A=80000000 B=fffffffe R=8000ffff CCIN=0001 CC=0084 -adcb A=80000000 B=fffffffe R=800000ff CCIN=0001 CC=0084 -adcl A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -adcw A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -adcb A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0084 -adcl A=12347fff B=00000000 R=12348000 CCIN=0001 CC=0014 -adcw A=12347fff B=00000000 R=12348000 CCIN=0001 CC=0894 -adcb A=12347fff B=00000000 R=12347f00 CCIN=0001 CC=0055 -adcl A=12347fff B=00000001 R=12348000 CCIN=0000 CC=0014 -adcw A=12347fff B=00000001 R=12348000 CCIN=0000 CC=0894 -adcb A=12347fff B=00000001 R=12347f00 CCIN=0000 CC=0055 -adcl A=12347fff B=00000001 R=12348001 CCIN=0001 CC=0010 -adcw A=12347fff B=00000001 R=12348001 CCIN=0001 CC=0890 -adcb A=12347fff B=00000001 R=12347f01 CCIN=0001 CC=0011 -adcl A=12347fff B=ffffffff R=12347ffe CCIN=0000 CC=0011 -adcw A=12347fff B=ffffffff R=12347ffe CCIN=0000 CC=0011 -adcb A=12347fff B=ffffffff R=12347ffe CCIN=0000 CC=0091 -adcl A=12347fff B=ffffffff R=12347fff CCIN=0001 CC=0015 -adcw A=12347fff B=ffffffff R=12347fff CCIN=0001 CC=0015 -adcb A=12347fff B=ffffffff R=12347fff CCIN=0001 CC=0095 -adcl A=12348000 B=ffffffff R=12347fff CCIN=0000 CC=0005 -adcw A=12348000 B=ffffffff R=12347fff CCIN=0000 CC=0805 -adcb A=12348000 B=ffffffff R=123480ff CCIN=0000 CC=0084 -adcl A=12348000 B=ffffffff R=12348000 CCIN=0001 CC=0015 -adcw A=12348000 B=ffffffff R=12348000 CCIN=0001 CC=0095 -adcb A=12348000 B=ffffffff R=12348000 CCIN=0001 CC=0055 -adcl A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0000 -adcw A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0080 -adcb A=12348000 B=00000001 R=12348001 CCIN=0000 CC=0000 -adcl A=12348000 B=00000001 R=12348002 CCIN=0001 CC=0000 -adcw A=12348000 B=00000001 R=12348002 CCIN=0001 CC=0080 -adcb A=12348000 B=00000001 R=12348002 CCIN=0001 CC=0000 -adcl A=12348000 B=fffffffe R=12347ffe CCIN=0000 CC=0001 -adcw A=12348000 B=fffffffe R=12347ffe CCIN=0000 CC=0801 -adcb A=12348000 B=fffffffe R=123480fe CCIN=0000 CC=0080 -adcl A=12348000 B=fffffffe R=12347fff CCIN=0001 CC=0005 -adcw A=12348000 B=fffffffe R=12347fff CCIN=0001 CC=0805 -adcb A=12348000 B=fffffffe R=123480ff CCIN=0001 CC=0084 -adcl A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -adcw A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -adcb A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -adcl A=12347f7f B=00000000 R=12347f80 CCIN=0001 CC=0010 -adcw A=12347f7f B=00000000 R=12347f80 CCIN=0001 CC=0010 -adcb A=12347f7f B=00000000 R=12347f80 CCIN=0001 CC=0890 -adcl A=12347f7f B=00000001 R=12347f80 CCIN=0000 CC=0010 -adcw A=12347f7f B=00000001 R=12347f80 CCIN=0000 CC=0010 -adcb A=12347f7f B=00000001 R=12347f80 CCIN=0000 CC=0890 -adcl A=12347f7f B=00000001 R=12347f81 CCIN=0001 CC=0014 -adcw A=12347f7f B=00000001 R=12347f81 CCIN=0001 CC=0014 -adcb A=12347f7f B=00000001 R=12347f81 CCIN=0001 CC=0894 -adcl A=12347f7f B=ffffffff R=12347f7e CCIN=0000 CC=0015 -adcw A=12347f7f B=ffffffff R=12347f7e CCIN=0000 CC=0015 -adcb A=12347f7f B=ffffffff R=12347f7e CCIN=0000 CC=0015 -adcl A=12347f7f B=ffffffff R=12347f7f CCIN=0001 CC=0011 -adcw A=12347f7f B=ffffffff R=12347f7f CCIN=0001 CC=0011 -adcb A=12347f7f B=ffffffff R=12347f7f CCIN=0001 CC=0011 -adcl A=12348080 B=ffffffff R=1234807f CCIN=0000 CC=0001 -adcw A=12348080 B=ffffffff R=1234807f CCIN=0000 CC=0081 -adcb A=12348080 B=ffffffff R=1234807f CCIN=0000 CC=0801 -adcl A=12348080 B=ffffffff R=12348080 CCIN=0001 CC=0011 -adcw A=12348080 B=ffffffff R=12348080 CCIN=0001 CC=0091 -adcb A=12348080 B=ffffffff R=12348080 CCIN=0001 CC=0091 -adcl A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0004 -adcw A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0084 -adcb A=12348080 B=00000001 R=12348081 CCIN=0000 CC=0084 -adcl A=12348080 B=00000001 R=12348082 CCIN=0001 CC=0004 -adcw A=12348080 B=00000001 R=12348082 CCIN=0001 CC=0084 -adcb A=12348080 B=00000001 R=12348082 CCIN=0001 CC=0084 -adcl A=12348080 B=fffffffe R=1234807e CCIN=0000 CC=0005 -adcw A=12348080 B=fffffffe R=1234807e CCIN=0000 CC=0085 -adcb A=12348080 B=fffffffe R=1234807e CCIN=0000 CC=0805 -adcl A=12348080 B=fffffffe R=1234807f CCIN=0001 CC=0001 -adcw A=12348080 B=fffffffe R=1234807f CCIN=0001 CC=0081 -adcb A=12348080 B=fffffffe R=1234807f CCIN=0001 CC=0801 -sbbl A=12345678 B=0812fada R=0a215b9e CCIN=0000 CC=0010 -sbbw A=12345678 B=0812fada R=12345b9e CCIN=0000 CC=0011 -sbbb A=12345678 B=0812fada R=1234569e CCIN=0000 CC=0891 -sbbl A=12345678 B=0812fada R=0a215b9d CCIN=0001 CC=0010 -sbbw A=12345678 B=0812fada R=12345b9d CCIN=0001 CC=0011 -sbbb A=12345678 B=0812fada R=1234569d CCIN=0001 CC=0891 -sbbl A=00012341 B=00012341 R=00000000 CCIN=0000 CC=0044 -sbbw A=00012341 B=00012341 R=00010000 CCIN=0000 CC=0044 -sbbb A=00012341 B=00012341 R=00012300 CCIN=0000 CC=0044 -sbbl A=00012341 B=00012341 R=ffffffff CCIN=0001 CC=0095 -sbbw A=00012341 B=00012341 R=0001ffff CCIN=0001 CC=0095 -sbbb A=00012341 B=00012341 R=000123ff CCIN=0001 CC=0095 -sbbl A=00012341 B=fffedcbf R=00024682 CCIN=0000 CC=0015 -sbbw A=00012341 B=fffedcbf R=00014682 CCIN=0000 CC=0015 -sbbb A=00012341 B=fffedcbf R=00012382 CCIN=0000 CC=0895 -sbbl A=00012341 B=fffedcbf R=00024681 CCIN=0001 CC=0015 -sbbw A=00012341 B=fffedcbf R=00014681 CCIN=0001 CC=0015 -sbbb A=00012341 B=fffedcbf R=00012381 CCIN=0001 CC=0895 -sbbl A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -sbbw A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -sbbb A=ffffffff B=00000000 R=ffffffff CCIN=0000 CC=0084 -sbbl A=ffffffff B=00000000 R=fffffffe CCIN=0001 CC=0080 -sbbw A=ffffffff B=00000000 R=fffffffe CCIN=0001 CC=0080 -sbbb A=ffffffff B=00000000 R=fffffffe CCIN=0001 CC=0080 -sbbl A=ffffffff B=ffffffff R=00000000 CCIN=0000 CC=0044 -sbbw A=ffffffff B=ffffffff R=ffff0000 CCIN=0000 CC=0044 -sbbb A=ffffffff B=ffffffff R=ffffff00 CCIN=0000 CC=0044 -sbbl A=ffffffff B=ffffffff R=ffffffff CCIN=0001 CC=0095 -sbbw A=ffffffff B=ffffffff R=ffffffff CCIN=0001 CC=0095 -sbbb A=ffffffff B=ffffffff R=ffffffff CCIN=0001 CC=0095 -sbbl A=ffffffff B=00000001 R=fffffffe CCIN=0000 CC=0080 -sbbw A=ffffffff B=00000001 R=fffffffe CCIN=0000 CC=0080 -sbbb A=ffffffff B=00000001 R=fffffffe CCIN=0000 CC=0080 -sbbl A=ffffffff B=00000001 R=fffffffd CCIN=0001 CC=0080 -sbbw A=ffffffff B=00000001 R=fffffffd CCIN=0001 CC=0080 -sbbb A=ffffffff B=00000001 R=fffffffd CCIN=0001 CC=0080 -sbbl A=ffffffff B=00000002 R=fffffffd CCIN=0000 CC=0080 -sbbw A=ffffffff B=00000002 R=fffffffd CCIN=0000 CC=0080 -sbbb A=ffffffff B=00000002 R=fffffffd CCIN=0000 CC=0080 -sbbl A=ffffffff B=00000002 R=fffffffc CCIN=0001 CC=0084 -sbbw A=ffffffff B=00000002 R=fffffffc CCIN=0001 CC=0084 -sbbb A=ffffffff B=00000002 R=fffffffc CCIN=0001 CC=0084 -sbbl A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0004 -sbbw A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -sbbb A=7fffffff B=00000000 R=7fffffff CCIN=0000 CC=0084 -sbbl A=7fffffff B=00000000 R=7ffffffe CCIN=0001 CC=0000 -sbbw A=7fffffff B=00000000 R=7ffffffe CCIN=0001 CC=0080 -sbbb A=7fffffff B=00000000 R=7ffffffe CCIN=0001 CC=0080 -sbbl A=7fffffff B=00000001 R=7ffffffe CCIN=0000 CC=0000 -sbbw A=7fffffff B=00000001 R=7ffffffe CCIN=0000 CC=0080 -sbbb A=7fffffff B=00000001 R=7ffffffe CCIN=0000 CC=0080 -sbbl A=7fffffff B=00000001 R=7ffffffd CCIN=0001 CC=0000 -sbbw A=7fffffff B=00000001 R=7ffffffd CCIN=0001 CC=0080 -sbbb A=7fffffff B=00000001 R=7ffffffd CCIN=0001 CC=0080 -sbbl A=7fffffff B=ffffffff R=80000000 CCIN=0000 CC=0885 -sbbw A=7fffffff B=ffffffff R=7fff0000 CCIN=0000 CC=0044 -sbbb A=7fffffff B=ffffffff R=7fffff00 CCIN=0000 CC=0044 -sbbl A=7fffffff B=ffffffff R=7fffffff CCIN=0001 CC=0015 -sbbw A=7fffffff B=ffffffff R=7fffffff CCIN=0001 CC=0095 -sbbb A=7fffffff B=ffffffff R=7fffffff CCIN=0001 CC=0095 -sbbl A=80000000 B=ffffffff R=80000001 CCIN=0000 CC=0091 -sbbw A=80000000 B=ffffffff R=80000001 CCIN=0000 CC=0011 -sbbb A=80000000 B=ffffffff R=80000001 CCIN=0000 CC=0011 -sbbl A=80000000 B=ffffffff R=80000000 CCIN=0001 CC=0095 -sbbw A=80000000 B=ffffffff R=80000000 CCIN=0001 CC=0055 -sbbb A=80000000 B=ffffffff R=80000000 CCIN=0001 CC=0055 -sbbl A=80000000 B=00000001 R=7fffffff CCIN=0000 CC=0814 -sbbw A=80000000 B=00000001 R=8000ffff CCIN=0000 CC=0095 -sbbb A=80000000 B=00000001 R=800000ff CCIN=0000 CC=0095 -sbbl A=80000000 B=00000001 R=7ffffffe CCIN=0001 CC=0810 -sbbw A=80000000 B=00000001 R=8000fffe CCIN=0001 CC=0091 -sbbb A=80000000 B=00000001 R=800000fe CCIN=0001 CC=0091 -sbbl A=80000000 B=fffffffe R=80000002 CCIN=0000 CC=0091 -sbbw A=80000000 B=fffffffe R=80000002 CCIN=0000 CC=0011 -sbbb A=80000000 B=fffffffe R=80000002 CCIN=0000 CC=0011 -sbbl A=80000000 B=fffffffe R=80000001 CCIN=0001 CC=0091 -sbbw A=80000000 B=fffffffe R=80000001 CCIN=0001 CC=0011 -sbbb A=80000000 B=fffffffe R=80000001 CCIN=0001 CC=0011 -sbbl A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -sbbw A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0004 -sbbb A=12347fff B=00000000 R=12347fff CCIN=0000 CC=0084 -sbbl A=12347fff B=00000000 R=12347ffe CCIN=0001 CC=0000 -sbbw A=12347fff B=00000000 R=12347ffe CCIN=0001 CC=0000 -sbbb A=12347fff B=00000000 R=12347ffe CCIN=0001 CC=0080 -sbbl A=12347fff B=00000001 R=12347ffe CCIN=0000 CC=0000 -sbbw A=12347fff B=00000001 R=12347ffe CCIN=0000 CC=0000 -sbbb A=12347fff B=00000001 R=12347ffe CCIN=0000 CC=0080 -sbbl A=12347fff B=00000001 R=12347ffd CCIN=0001 CC=0000 -sbbw A=12347fff B=00000001 R=12347ffd CCIN=0001 CC=0000 -sbbb A=12347fff B=00000001 R=12347ffd CCIN=0001 CC=0080 -sbbl A=12347fff B=ffffffff R=12348000 CCIN=0000 CC=0005 -sbbw A=12347fff B=ffffffff R=12348000 CCIN=0000 CC=0885 -sbbb A=12347fff B=ffffffff R=12347f00 CCIN=0000 CC=0044 -sbbl A=12347fff B=ffffffff R=12347fff CCIN=0001 CC=0015 -sbbw A=12347fff B=ffffffff R=12347fff CCIN=0001 CC=0015 -sbbb A=12347fff B=ffffffff R=12347fff CCIN=0001 CC=0095 -sbbl A=12348000 B=ffffffff R=12348001 CCIN=0000 CC=0011 -sbbw A=12348000 B=ffffffff R=12348001 CCIN=0000 CC=0091 -sbbb A=12348000 B=ffffffff R=12348001 CCIN=0000 CC=0011 -sbbl A=12348000 B=ffffffff R=12348000 CCIN=0001 CC=0015 -sbbw A=12348000 B=ffffffff R=12348000 CCIN=0001 CC=0095 -sbbb A=12348000 B=ffffffff R=12348000 CCIN=0001 CC=0055 -sbbl A=12348000 B=00000001 R=12347fff CCIN=0000 CC=0014 -sbbw A=12348000 B=00000001 R=12347fff CCIN=0000 CC=0814 -sbbb A=12348000 B=00000001 R=123480ff CCIN=0000 CC=0095 -sbbl A=12348000 B=00000001 R=12347ffe CCIN=0001 CC=0010 -sbbw A=12348000 B=00000001 R=12347ffe CCIN=0001 CC=0810 -sbbb A=12348000 B=00000001 R=123480fe CCIN=0001 CC=0091 -sbbl A=12348000 B=fffffffe R=12348002 CCIN=0000 CC=0011 -sbbw A=12348000 B=fffffffe R=12348002 CCIN=0000 CC=0091 -sbbb A=12348000 B=fffffffe R=12348002 CCIN=0000 CC=0011 -sbbl A=12348000 B=fffffffe R=12348001 CCIN=0001 CC=0011 -sbbw A=12348000 B=fffffffe R=12348001 CCIN=0001 CC=0091 -sbbb A=12348000 B=fffffffe R=12348001 CCIN=0001 CC=0011 -sbbl A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -sbbw A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -sbbb A=12347f7f B=00000000 R=12347f7f CCIN=0000 CC=0000 -sbbl A=12347f7f B=00000000 R=12347f7e CCIN=0001 CC=0004 -sbbw A=12347f7f B=00000000 R=12347f7e CCIN=0001 CC=0004 -sbbb A=12347f7f B=00000000 R=12347f7e CCIN=0001 CC=0004 -sbbl A=12347f7f B=00000001 R=12347f7e CCIN=0000 CC=0004 -sbbw A=12347f7f B=00000001 R=12347f7e CCIN=0000 CC=0004 -sbbb A=12347f7f B=00000001 R=12347f7e CCIN=0000 CC=0004 -sbbl A=12347f7f B=00000001 R=12347f7d CCIN=0001 CC=0004 -sbbw A=12347f7f B=00000001 R=12347f7d CCIN=0001 CC=0004 -sbbb A=12347f7f B=00000001 R=12347f7d CCIN=0001 CC=0004 -sbbl A=12347f7f B=ffffffff R=12347f80 CCIN=0000 CC=0001 -sbbw A=12347f7f B=ffffffff R=12347f80 CCIN=0000 CC=0001 -sbbb A=12347f7f B=ffffffff R=12347f80 CCIN=0000 CC=0881 -sbbl A=12347f7f B=ffffffff R=12347f7f CCIN=0001 CC=0011 -sbbw A=12347f7f B=ffffffff R=12347f7f CCIN=0001 CC=0011 -sbbb A=12347f7f B=ffffffff R=12347f7f CCIN=0001 CC=0011 -sbbl A=12348080 B=ffffffff R=12348081 CCIN=0000 CC=0015 -sbbw A=12348080 B=ffffffff R=12348081 CCIN=0000 CC=0095 -sbbb A=12348080 B=ffffffff R=12348081 CCIN=0000 CC=0095 -sbbl A=12348080 B=ffffffff R=12348080 CCIN=0001 CC=0011 -sbbw A=12348080 B=ffffffff R=12348080 CCIN=0001 CC=0091 -sbbb A=12348080 B=ffffffff R=12348080 CCIN=0001 CC=0091 -sbbl A=12348080 B=00000001 R=1234807f CCIN=0000 CC=0010 -sbbw A=12348080 B=00000001 R=1234807f CCIN=0000 CC=0090 -sbbb A=12348080 B=00000001 R=1234807f CCIN=0000 CC=0810 -sbbl A=12348080 B=00000001 R=1234807e CCIN=0001 CC=0014 -sbbw A=12348080 B=00000001 R=1234807e CCIN=0001 CC=0094 -sbbb A=12348080 B=00000001 R=1234807e CCIN=0001 CC=0814 -sbbl A=12348080 B=fffffffe R=12348082 CCIN=0000 CC=0015 -sbbw A=12348080 B=fffffffe R=12348082 CCIN=0000 CC=0095 -sbbb A=12348080 B=fffffffe R=12348082 CCIN=0000 CC=0095 -sbbl A=12348080 B=fffffffe R=12348081 CCIN=0001 CC=0015 -sbbw A=12348080 B=fffffffe R=12348081 CCIN=0001 CC=0095 -sbbb A=12348080 B=fffffffe R=12348081 CCIN=0001 CC=0095 -incl A=12345678 R=12345679 CCIN=0000 CC=0000 -incw A=12345678 R=12345679 CCIN=0000 CC=0000 -incb A=12345678 R=12345679 CCIN=0000 CC=0000 -incl A=12345678 R=12345679 CCIN=0001 CC=0001 -incw A=12345678 R=12345679 CCIN=0001 CC=0001 -incb A=12345678 R=12345679 CCIN=0001 CC=0001 -incl A=00012341 R=00012342 CCIN=0000 CC=0004 -incw A=00012341 R=00012342 CCIN=0000 CC=0004 -incb A=00012341 R=00012342 CCIN=0000 CC=0004 -incl A=00012341 R=00012342 CCIN=0001 CC=0005 -incw A=00012341 R=00012342 CCIN=0001 CC=0005 -incb A=00012341 R=00012342 CCIN=0001 CC=0005 -incl A=00012341 R=00012342 CCIN=0000 CC=0004 -incw A=00012341 R=00012342 CCIN=0000 CC=0004 -incb A=00012341 R=00012342 CCIN=0000 CC=0004 -incl A=00012341 R=00012342 CCIN=0001 CC=0005 -incw A=00012341 R=00012342 CCIN=0001 CC=0005 -incb A=00012341 R=00012342 CCIN=0001 CC=0005 -incl A=ffffffff R=00000000 CCIN=0000 CC=0054 -incw A=ffffffff R=ffff0000 CCIN=0000 CC=0054 -incb A=ffffffff R=ffffff00 CCIN=0000 CC=0054 -incl A=ffffffff R=00000000 CCIN=0001 CC=0055 -incw A=ffffffff R=ffff0000 CCIN=0001 CC=0055 -incb A=ffffffff R=ffffff00 CCIN=0001 CC=0055 -incl A=ffffffff R=00000000 CCIN=0000 CC=0054 -incw A=ffffffff R=ffff0000 CCIN=0000 CC=0054 -incb A=ffffffff R=ffffff00 CCIN=0000 CC=0054 -incl A=ffffffff R=00000000 CCIN=0001 CC=0055 -incw A=ffffffff R=ffff0000 CCIN=0001 CC=0055 -incb A=ffffffff R=ffffff00 CCIN=0001 CC=0055 -incl A=ffffffff R=00000000 CCIN=0000 CC=0054 -incw A=ffffffff R=ffff0000 CCIN=0000 CC=0054 -incb A=ffffffff R=ffffff00 CCIN=0000 CC=0054 -incl A=ffffffff R=00000000 CCIN=0001 CC=0055 -incw A=ffffffff R=ffff0000 CCIN=0001 CC=0055 -incb A=ffffffff R=ffffff00 CCIN=0001 CC=0055 -incl A=ffffffff R=00000000 CCIN=0000 CC=0054 -incw A=ffffffff R=ffff0000 CCIN=0000 CC=0054 -incb A=ffffffff R=ffffff00 CCIN=0000 CC=0054 -incl A=ffffffff R=00000000 CCIN=0001 CC=0055 -incw A=ffffffff R=ffff0000 CCIN=0001 CC=0055 -incb A=ffffffff R=ffffff00 CCIN=0001 CC=0055 -incl A=7fffffff R=80000000 CCIN=0000 CC=0894 -incw A=7fffffff R=7fff0000 CCIN=0000 CC=0054 -incb A=7fffffff R=7fffff00 CCIN=0000 CC=0054 -incl A=7fffffff R=80000000 CCIN=0001 CC=0895 -incw A=7fffffff R=7fff0000 CCIN=0001 CC=0055 -incb A=7fffffff R=7fffff00 CCIN=0001 CC=0055 -incl A=7fffffff R=80000000 CCIN=0000 CC=0894 -incw A=7fffffff R=7fff0000 CCIN=0000 CC=0054 -incb A=7fffffff R=7fffff00 CCIN=0000 CC=0054 -incl A=7fffffff R=80000000 CCIN=0001 CC=0895 -incw A=7fffffff R=7fff0000 CCIN=0001 CC=0055 -incb A=7fffffff R=7fffff00 CCIN=0001 CC=0055 -incl A=7fffffff R=80000000 CCIN=0000 CC=0894 -incw A=7fffffff R=7fff0000 CCIN=0000 CC=0054 -incb A=7fffffff R=7fffff00 CCIN=0000 CC=0054 -incl A=7fffffff R=80000000 CCIN=0001 CC=0895 -incw A=7fffffff R=7fff0000 CCIN=0001 CC=0055 -incb A=7fffffff R=7fffff00 CCIN=0001 CC=0055 -incl A=80000000 R=80000001 CCIN=0000 CC=0080 -incw A=80000000 R=80000001 CCIN=0000 CC=0000 -incb A=80000000 R=80000001 CCIN=0000 CC=0000 -incl A=80000000 R=80000001 CCIN=0001 CC=0081 -incw A=80000000 R=80000001 CCIN=0001 CC=0001 -incb A=80000000 R=80000001 CCIN=0001 CC=0001 -incl A=80000000 R=80000001 CCIN=0000 CC=0080 -incw A=80000000 R=80000001 CCIN=0000 CC=0000 -incb A=80000000 R=80000001 CCIN=0000 CC=0000 -incl A=80000000 R=80000001 CCIN=0001 CC=0081 -incw A=80000000 R=80000001 CCIN=0001 CC=0001 -incb A=80000000 R=80000001 CCIN=0001 CC=0001 -incl A=80000000 R=80000001 CCIN=0000 CC=0080 -incw A=80000000 R=80000001 CCIN=0000 CC=0000 -incb A=80000000 R=80000001 CCIN=0000 CC=0000 -incl A=80000000 R=80000001 CCIN=0001 CC=0081 -incw A=80000000 R=80000001 CCIN=0001 CC=0001 -incb A=80000000 R=80000001 CCIN=0001 CC=0001 -incl A=12347fff R=12348000 CCIN=0000 CC=0014 -incw A=12347fff R=12348000 CCIN=0000 CC=0894 -incb A=12347fff R=12347f00 CCIN=0000 CC=0054 -incl A=12347fff R=12348000 CCIN=0001 CC=0015 -incw A=12347fff R=12348000 CCIN=0001 CC=0895 -incb A=12347fff R=12347f00 CCIN=0001 CC=0055 -incl A=12347fff R=12348000 CCIN=0000 CC=0014 -incw A=12347fff R=12348000 CCIN=0000 CC=0894 -incb A=12347fff R=12347f00 CCIN=0000 CC=0054 -incl A=12347fff R=12348000 CCIN=0001 CC=0015 -incw A=12347fff R=12348000 CCIN=0001 CC=0895 -incb A=12347fff R=12347f00 CCIN=0001 CC=0055 -incl A=12347fff R=12348000 CCIN=0000 CC=0014 -incw A=12347fff R=12348000 CCIN=0000 CC=0894 -incb A=12347fff R=12347f00 CCIN=0000 CC=0054 -incl A=12347fff R=12348000 CCIN=0001 CC=0015 -incw A=12347fff R=12348000 CCIN=0001 CC=0895 -incb A=12347fff R=12347f00 CCIN=0001 CC=0055 -incl A=12348000 R=12348001 CCIN=0000 CC=0000 -incw A=12348000 R=12348001 CCIN=0000 CC=0080 -incb A=12348000 R=12348001 CCIN=0000 CC=0000 -incl A=12348000 R=12348001 CCIN=0001 CC=0001 -incw A=12348000 R=12348001 CCIN=0001 CC=0081 -incb A=12348000 R=12348001 CCIN=0001 CC=0001 -incl A=12348000 R=12348001 CCIN=0000 CC=0000 -incw A=12348000 R=12348001 CCIN=0000 CC=0080 -incb A=12348000 R=12348001 CCIN=0000 CC=0000 -incl A=12348000 R=12348001 CCIN=0001 CC=0001 -incw A=12348000 R=12348001 CCIN=0001 CC=0081 -incb A=12348000 R=12348001 CCIN=0001 CC=0001 -incl A=12348000 R=12348001 CCIN=0000 CC=0000 -incw A=12348000 R=12348001 CCIN=0000 CC=0080 -incb A=12348000 R=12348001 CCIN=0000 CC=0000 -incl A=12348000 R=12348001 CCIN=0001 CC=0001 -incw A=12348000 R=12348001 CCIN=0001 CC=0081 -incb A=12348000 R=12348001 CCIN=0001 CC=0001 -incl A=12347f7f R=12347f80 CCIN=0000 CC=0010 -incw A=12347f7f R=12347f80 CCIN=0000 CC=0010 -incb A=12347f7f R=12347f80 CCIN=0000 CC=0890 -incl A=12347f7f R=12347f80 CCIN=0001 CC=0011 -incw A=12347f7f R=12347f80 CCIN=0001 CC=0011 -incb A=12347f7f R=12347f80 CCIN=0001 CC=0891 -incl A=12347f7f R=12347f80 CCIN=0000 CC=0010 -incw A=12347f7f R=12347f80 CCIN=0000 CC=0010 -incb A=12347f7f R=12347f80 CCIN=0000 CC=0890 -incl A=12347f7f R=12347f80 CCIN=0001 CC=0011 -incw A=12347f7f R=12347f80 CCIN=0001 CC=0011 -incb A=12347f7f R=12347f80 CCIN=0001 CC=0891 -incl A=12347f7f R=12347f80 CCIN=0000 CC=0010 -incw A=12347f7f R=12347f80 CCIN=0000 CC=0010 -incb A=12347f7f R=12347f80 CCIN=0000 CC=0890 -incl A=12347f7f R=12347f80 CCIN=0001 CC=0011 -incw A=12347f7f R=12347f80 CCIN=0001 CC=0011 -incb A=12347f7f R=12347f80 CCIN=0001 CC=0891 -incl A=12348080 R=12348081 CCIN=0000 CC=0004 -incw A=12348080 R=12348081 CCIN=0000 CC=0084 -incb A=12348080 R=12348081 CCIN=0000 CC=0084 -incl A=12348080 R=12348081 CCIN=0001 CC=0005 -incw A=12348080 R=12348081 CCIN=0001 CC=0085 -incb A=12348080 R=12348081 CCIN=0001 CC=0085 -incl A=12348080 R=12348081 CCIN=0000 CC=0004 -incw A=12348080 R=12348081 CCIN=0000 CC=0084 -incb A=12348080 R=12348081 CCIN=0000 CC=0084 -incl A=12348080 R=12348081 CCIN=0001 CC=0005 -incw A=12348080 R=12348081 CCIN=0001 CC=0085 -incb A=12348080 R=12348081 CCIN=0001 CC=0085 -incl A=12348080 R=12348081 CCIN=0000 CC=0004 -incw A=12348080 R=12348081 CCIN=0000 CC=0084 -incb A=12348080 R=12348081 CCIN=0000 CC=0084 -incl A=12348080 R=12348081 CCIN=0001 CC=0005 -incw A=12348080 R=12348081 CCIN=0001 CC=0085 -incb A=12348080 R=12348081 CCIN=0001 CC=0085 -decl A=12345678 R=12345677 CCIN=0000 CC=0004 -decw A=12345678 R=12345677 CCIN=0000 CC=0004 -decb A=12345678 R=12345677 CCIN=0000 CC=0004 -decl A=12345678 R=12345677 CCIN=0001 CC=0005 -decw A=12345678 R=12345677 CCIN=0001 CC=0005 -decb A=12345678 R=12345677 CCIN=0001 CC=0005 -decl A=00012341 R=00012340 CCIN=0000 CC=0000 -decw A=00012341 R=00012340 CCIN=0000 CC=0000 -decb A=00012341 R=00012340 CCIN=0000 CC=0000 -decl A=00012341 R=00012340 CCIN=0001 CC=0001 -decw A=00012341 R=00012340 CCIN=0001 CC=0001 -decb A=00012341 R=00012340 CCIN=0001 CC=0001 -decl A=00012341 R=00012340 CCIN=0000 CC=0000 -decw A=00012341 R=00012340 CCIN=0000 CC=0000 -decb A=00012341 R=00012340 CCIN=0000 CC=0000 -decl A=00012341 R=00012340 CCIN=0001 CC=0001 -decw A=00012341 R=00012340 CCIN=0001 CC=0001 -decb A=00012341 R=00012340 CCIN=0001 CC=0001 -decl A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decw A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decb A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decl A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decw A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decb A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decl A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decw A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decb A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decl A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decw A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decb A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decl A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decw A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decb A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decl A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decw A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decb A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decl A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decw A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decb A=ffffffff R=fffffffe CCIN=0000 CC=0080 -decl A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decw A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decb A=ffffffff R=fffffffe CCIN=0001 CC=0081 -decl A=7fffffff R=7ffffffe CCIN=0000 CC=0000 -decw A=7fffffff R=7ffffffe CCIN=0000 CC=0080 -decb A=7fffffff R=7ffffffe CCIN=0000 CC=0080 -decl A=7fffffff R=7ffffffe CCIN=0001 CC=0001 -decw A=7fffffff R=7ffffffe CCIN=0001 CC=0081 -decb A=7fffffff R=7ffffffe CCIN=0001 CC=0081 -decl A=7fffffff R=7ffffffe CCIN=0000 CC=0000 -decw A=7fffffff R=7ffffffe CCIN=0000 CC=0080 -decb A=7fffffff R=7ffffffe CCIN=0000 CC=0080 -decl A=7fffffff R=7ffffffe CCIN=0001 CC=0001 -decw A=7fffffff R=7ffffffe CCIN=0001 CC=0081 -decb A=7fffffff R=7ffffffe CCIN=0001 CC=0081 -decl A=7fffffff R=7ffffffe CCIN=0000 CC=0000 -decw A=7fffffff R=7ffffffe CCIN=0000 CC=0080 -decb A=7fffffff R=7ffffffe CCIN=0000 CC=0080 -decl A=7fffffff R=7ffffffe CCIN=0001 CC=0001 -decw A=7fffffff R=7ffffffe CCIN=0001 CC=0081 -decb A=7fffffff R=7ffffffe CCIN=0001 CC=0081 -decl A=80000000 R=7fffffff CCIN=0000 CC=0814 -decw A=80000000 R=8000ffff CCIN=0000 CC=0094 -decb A=80000000 R=800000ff CCIN=0000 CC=0094 -decl A=80000000 R=7fffffff CCIN=0001 CC=0815 -decw A=80000000 R=8000ffff CCIN=0001 CC=0095 -decb A=80000000 R=800000ff CCIN=0001 CC=0095 -decl A=80000000 R=7fffffff CCIN=0000 CC=0814 -decw A=80000000 R=8000ffff CCIN=0000 CC=0094 -decb A=80000000 R=800000ff CCIN=0000 CC=0094 -decl A=80000000 R=7fffffff CCIN=0001 CC=0815 -decw A=80000000 R=8000ffff CCIN=0001 CC=0095 -decb A=80000000 R=800000ff CCIN=0001 CC=0095 -decl A=80000000 R=7fffffff CCIN=0000 CC=0814 -decw A=80000000 R=8000ffff CCIN=0000 CC=0094 -decb A=80000000 R=800000ff CCIN=0000 CC=0094 -decl A=80000000 R=7fffffff CCIN=0001 CC=0815 -decw A=80000000 R=8000ffff CCIN=0001 CC=0095 -decb A=80000000 R=800000ff CCIN=0001 CC=0095 -decl A=12347fff R=12347ffe CCIN=0000 CC=0000 -decw A=12347fff R=12347ffe CCIN=0000 CC=0000 -decb A=12347fff R=12347ffe CCIN=0000 CC=0080 -decl A=12347fff R=12347ffe CCIN=0001 CC=0001 -decw A=12347fff R=12347ffe CCIN=0001 CC=0001 -decb A=12347fff R=12347ffe CCIN=0001 CC=0081 -decl A=12347fff R=12347ffe CCIN=0000 CC=0000 -decw A=12347fff R=12347ffe CCIN=0000 CC=0000 -decb A=12347fff R=12347ffe CCIN=0000 CC=0080 -decl A=12347fff R=12347ffe CCIN=0001 CC=0001 -decw A=12347fff R=12347ffe CCIN=0001 CC=0001 -decb A=12347fff R=12347ffe CCIN=0001 CC=0081 -decl A=12347fff R=12347ffe CCIN=0000 CC=0000 -decw A=12347fff R=12347ffe CCIN=0000 CC=0000 -decb A=12347fff R=12347ffe CCIN=0000 CC=0080 -decl A=12347fff R=12347ffe CCIN=0001 CC=0001 -decw A=12347fff R=12347ffe CCIN=0001 CC=0001 -decb A=12347fff R=12347ffe CCIN=0001 CC=0081 -decl A=12348000 R=12347fff CCIN=0000 CC=0014 -decw A=12348000 R=12347fff CCIN=0000 CC=0814 -decb A=12348000 R=123480ff CCIN=0000 CC=0094 -decl A=12348000 R=12347fff CCIN=0001 CC=0015 -decw A=12348000 R=12347fff CCIN=0001 CC=0815 -decb A=12348000 R=123480ff CCIN=0001 CC=0095 -decl A=12348000 R=12347fff CCIN=0000 CC=0014 -decw A=12348000 R=12347fff CCIN=0000 CC=0814 -decb A=12348000 R=123480ff CCIN=0000 CC=0094 -decl A=12348000 R=12347fff CCIN=0001 CC=0015 -decw A=12348000 R=12347fff CCIN=0001 CC=0815 -decb A=12348000 R=123480ff CCIN=0001 CC=0095 -decl A=12348000 R=12347fff CCIN=0000 CC=0014 -decw A=12348000 R=12347fff CCIN=0000 CC=0814 -decb A=12348000 R=123480ff CCIN=0000 CC=0094 -decl A=12348000 R=12347fff CCIN=0001 CC=0015 -decw A=12348000 R=12347fff CCIN=0001 CC=0815 -decb A=12348000 R=123480ff CCIN=0001 CC=0095 -decl A=12347f7f R=12347f7e CCIN=0000 CC=0004 -decw A=12347f7f R=12347f7e CCIN=0000 CC=0004 -decb A=12347f7f R=12347f7e CCIN=0000 CC=0004 -decl A=12347f7f R=12347f7e CCIN=0001 CC=0005 -decw A=12347f7f R=12347f7e CCIN=0001 CC=0005 -decb A=12347f7f R=12347f7e CCIN=0001 CC=0005 -decl A=12347f7f R=12347f7e CCIN=0000 CC=0004 -decw A=12347f7f R=12347f7e CCIN=0000 CC=0004 -decb A=12347f7f R=12347f7e CCIN=0000 CC=0004 -decl A=12347f7f R=12347f7e CCIN=0001 CC=0005 -decw A=12347f7f R=12347f7e CCIN=0001 CC=0005 -decb A=12347f7f R=12347f7e CCIN=0001 CC=0005 -decl A=12347f7f R=12347f7e CCIN=0000 CC=0004 -decw A=12347f7f R=12347f7e CCIN=0000 CC=0004 -decb A=12347f7f R=12347f7e CCIN=0000 CC=0004 -decl A=12347f7f R=12347f7e CCIN=0001 CC=0005 -decw A=12347f7f R=12347f7e CCIN=0001 CC=0005 -decb A=12347f7f R=12347f7e CCIN=0001 CC=0005 -decl A=12348080 R=1234807f CCIN=0000 CC=0010 -decw A=12348080 R=1234807f CCIN=0000 CC=0090 -decb A=12348080 R=1234807f CCIN=0000 CC=0810 -decl A=12348080 R=1234807f CCIN=0001 CC=0011 -decw A=12348080 R=1234807f CCIN=0001 CC=0091 -decb A=12348080 R=1234807f CCIN=0001 CC=0811 -decl A=12348080 R=1234807f CCIN=0000 CC=0010 -decw A=12348080 R=1234807f CCIN=0000 CC=0090 -decb A=12348080 R=1234807f CCIN=0000 CC=0810 -decl A=12348080 R=1234807f CCIN=0001 CC=0011 -decw A=12348080 R=1234807f CCIN=0001 CC=0091 -decb A=12348080 R=1234807f CCIN=0001 CC=0811 -decl A=12348080 R=1234807f CCIN=0000 CC=0010 -decw A=12348080 R=1234807f CCIN=0000 CC=0090 -decb A=12348080 R=1234807f CCIN=0000 CC=0810 -decl A=12348080 R=1234807f CCIN=0001 CC=0011 -decw A=12348080 R=1234807f CCIN=0001 CC=0091 -decb A=12348080 R=1234807f CCIN=0001 CC=0811 -negl A=12345678 R=edcba988 CCIN=0000 CC=0095 -negw A=12345678 R=1234a988 CCIN=0000 CC=0095 -negb A=12345678 R=12345688 CCIN=0000 CC=0095 -negl A=12345678 R=edcba988 CCIN=0001 CC=0095 -negw A=12345678 R=1234a988 CCIN=0001 CC=0095 -negb A=12345678 R=12345688 CCIN=0001 CC=0095 -negl A=00012341 R=fffedcbf CCIN=0000 CC=0091 -negw A=00012341 R=0001dcbf CCIN=0000 CC=0091 -negb A=00012341 R=000123bf CCIN=0000 CC=0091 -negl A=00012341 R=fffedcbf CCIN=0001 CC=0091 -negw A=00012341 R=0001dcbf CCIN=0001 CC=0091 -negb A=00012341 R=000123bf CCIN=0001 CC=0091 -negl A=00012341 R=fffedcbf CCIN=0000 CC=0091 -negw A=00012341 R=0001dcbf CCIN=0000 CC=0091 -negb A=00012341 R=000123bf CCIN=0000 CC=0091 -negl A=00012341 R=fffedcbf CCIN=0001 CC=0091 -negw A=00012341 R=0001dcbf CCIN=0001 CC=0091 -negb A=00012341 R=000123bf CCIN=0001 CC=0091 -negl A=ffffffff R=00000001 CCIN=0000 CC=0011 -negw A=ffffffff R=ffff0001 CCIN=0000 CC=0011 -negb A=ffffffff R=ffffff01 CCIN=0000 CC=0011 -negl A=ffffffff R=00000001 CCIN=0001 CC=0011 -negw A=ffffffff R=ffff0001 CCIN=0001 CC=0011 -negb A=ffffffff R=ffffff01 CCIN=0001 CC=0011 -negl A=ffffffff R=00000001 CCIN=0000 CC=0011 -negw A=ffffffff R=ffff0001 CCIN=0000 CC=0011 -negb A=ffffffff R=ffffff01 CCIN=0000 CC=0011 -negl A=ffffffff R=00000001 CCIN=0001 CC=0011 -negw A=ffffffff R=ffff0001 CCIN=0001 CC=0011 -negb A=ffffffff R=ffffff01 CCIN=0001 CC=0011 -negl A=ffffffff R=00000001 CCIN=0000 CC=0011 -negw A=ffffffff R=ffff0001 CCIN=0000 CC=0011 -negb A=ffffffff R=ffffff01 CCIN=0000 CC=0011 -negl A=ffffffff R=00000001 CCIN=0001 CC=0011 -negw A=ffffffff R=ffff0001 CCIN=0001 CC=0011 -negb A=ffffffff R=ffffff01 CCIN=0001 CC=0011 -negl A=ffffffff R=00000001 CCIN=0000 CC=0011 -negw A=ffffffff R=ffff0001 CCIN=0000 CC=0011 -negb A=ffffffff R=ffffff01 CCIN=0000 CC=0011 -negl A=ffffffff R=00000001 CCIN=0001 CC=0011 -negw A=ffffffff R=ffff0001 CCIN=0001 CC=0011 -negb A=ffffffff R=ffffff01 CCIN=0001 CC=0011 -negl A=7fffffff R=80000001 CCIN=0000 CC=0091 -negw A=7fffffff R=7fff0001 CCIN=0000 CC=0011 -negb A=7fffffff R=7fffff01 CCIN=0000 CC=0011 -negl A=7fffffff R=80000001 CCIN=0001 CC=0091 -negw A=7fffffff R=7fff0001 CCIN=0001 CC=0011 -negb A=7fffffff R=7fffff01 CCIN=0001 CC=0011 -negl A=7fffffff R=80000001 CCIN=0000 CC=0091 -negw A=7fffffff R=7fff0001 CCIN=0000 CC=0011 -negb A=7fffffff R=7fffff01 CCIN=0000 CC=0011 -negl A=7fffffff R=80000001 CCIN=0001 CC=0091 -negw A=7fffffff R=7fff0001 CCIN=0001 CC=0011 -negb A=7fffffff R=7fffff01 CCIN=0001 CC=0011 -negl A=7fffffff R=80000001 CCIN=0000 CC=0091 -negw A=7fffffff R=7fff0001 CCIN=0000 CC=0011 -negb A=7fffffff R=7fffff01 CCIN=0000 CC=0011 -negl A=7fffffff R=80000001 CCIN=0001 CC=0091 -negw A=7fffffff R=7fff0001 CCIN=0001 CC=0011 -negb A=7fffffff R=7fffff01 CCIN=0001 CC=0011 -negl A=80000000 R=80000000 CCIN=0000 CC=0885 -negw A=80000000 R=80000000 CCIN=0000 CC=0044 -negb A=80000000 R=80000000 CCIN=0000 CC=0044 -negl A=80000000 R=80000000 CCIN=0001 CC=0885 -negw A=80000000 R=80000000 CCIN=0001 CC=0044 -negb A=80000000 R=80000000 CCIN=0001 CC=0044 -negl A=80000000 R=80000000 CCIN=0000 CC=0885 -negw A=80000000 R=80000000 CCIN=0000 CC=0044 -negb A=80000000 R=80000000 CCIN=0000 CC=0044 -negl A=80000000 R=80000000 CCIN=0001 CC=0885 -negw A=80000000 R=80000000 CCIN=0001 CC=0044 -negb A=80000000 R=80000000 CCIN=0001 CC=0044 -negl A=80000000 R=80000000 CCIN=0000 CC=0885 -negw A=80000000 R=80000000 CCIN=0000 CC=0044 -negb A=80000000 R=80000000 CCIN=0000 CC=0044 -negl A=80000000 R=80000000 CCIN=0001 CC=0885 -negw A=80000000 R=80000000 CCIN=0001 CC=0044 -negb A=80000000 R=80000000 CCIN=0001 CC=0044 -negl A=12347fff R=edcb8001 CCIN=0000 CC=0091 -negw A=12347fff R=12348001 CCIN=0000 CC=0091 -negb A=12347fff R=12347f01 CCIN=0000 CC=0011 -negl A=12347fff R=edcb8001 CCIN=0001 CC=0091 -negw A=12347fff R=12348001 CCIN=0001 CC=0091 -negb A=12347fff R=12347f01 CCIN=0001 CC=0011 -negl A=12347fff R=edcb8001 CCIN=0000 CC=0091 -negw A=12347fff R=12348001 CCIN=0000 CC=0091 -negb A=12347fff R=12347f01 CCIN=0000 CC=0011 -negl A=12347fff R=edcb8001 CCIN=0001 CC=0091 -negw A=12347fff R=12348001 CCIN=0001 CC=0091 -negb A=12347fff R=12347f01 CCIN=0001 CC=0011 -negl A=12347fff R=edcb8001 CCIN=0000 CC=0091 -negw A=12347fff R=12348001 CCIN=0000 CC=0091 -negb A=12347fff R=12347f01 CCIN=0000 CC=0011 -negl A=12347fff R=edcb8001 CCIN=0001 CC=0091 -negw A=12347fff R=12348001 CCIN=0001 CC=0091 -negb A=12347fff R=12347f01 CCIN=0001 CC=0011 -negl A=12348000 R=edcb8000 CCIN=0000 CC=0085 -negw A=12348000 R=12348000 CCIN=0000 CC=0885 -negb A=12348000 R=12348000 CCIN=0000 CC=0044 -negl A=12348000 R=edcb8000 CCIN=0001 CC=0085 -negw A=12348000 R=12348000 CCIN=0001 CC=0885 -negb A=12348000 R=12348000 CCIN=0001 CC=0044 -negl A=12348000 R=edcb8000 CCIN=0000 CC=0085 -negw A=12348000 R=12348000 CCIN=0000 CC=0885 -negb A=12348000 R=12348000 CCIN=0000 CC=0044 -negl A=12348000 R=edcb8000 CCIN=0001 CC=0085 -negw A=12348000 R=12348000 CCIN=0001 CC=0885 -negb A=12348000 R=12348000 CCIN=0001 CC=0044 -negl A=12348000 R=edcb8000 CCIN=0000 CC=0085 -negw A=12348000 R=12348000 CCIN=0000 CC=0885 -negb A=12348000 R=12348000 CCIN=0000 CC=0044 -negl A=12348000 R=edcb8000 CCIN=0001 CC=0085 -negw A=12348000 R=12348000 CCIN=0001 CC=0885 -negb A=12348000 R=12348000 CCIN=0001 CC=0044 -negl A=12347f7f R=edcb8081 CCIN=0000 CC=0095 -negw A=12347f7f R=12348081 CCIN=0000 CC=0095 -negb A=12347f7f R=12347f81 CCIN=0000 CC=0095 -negl A=12347f7f R=edcb8081 CCIN=0001 CC=0095 -negw A=12347f7f R=12348081 CCIN=0001 CC=0095 -negb A=12347f7f R=12347f81 CCIN=0001 CC=0095 -negl A=12347f7f R=edcb8081 CCIN=0000 CC=0095 -negw A=12347f7f R=12348081 CCIN=0000 CC=0095 -negb A=12347f7f R=12347f81 CCIN=0000 CC=0095 -negl A=12347f7f R=edcb8081 CCIN=0001 CC=0095 -negw A=12347f7f R=12348081 CCIN=0001 CC=0095 -negb A=12347f7f R=12347f81 CCIN=0001 CC=0095 -negl A=12347f7f R=edcb8081 CCIN=0000 CC=0095 -negw A=12347f7f R=12348081 CCIN=0000 CC=0095 -negb A=12347f7f R=12347f81 CCIN=0000 CC=0095 -negl A=12347f7f R=edcb8081 CCIN=0001 CC=0095 -negw A=12347f7f R=12348081 CCIN=0001 CC=0095 -negb A=12347f7f R=12347f81 CCIN=0001 CC=0095 -negl A=12348080 R=edcb7f80 CCIN=0000 CC=0081 -negw A=12348080 R=12347f80 CCIN=0000 CC=0001 -negb A=12348080 R=12348080 CCIN=0000 CC=0881 -negl A=12348080 R=edcb7f80 CCIN=0001 CC=0081 -negw A=12348080 R=12347f80 CCIN=0001 CC=0001 -negb A=12348080 R=12348080 CCIN=0001 CC=0881 -negl A=12348080 R=edcb7f80 CCIN=0000 CC=0081 -negw A=12348080 R=12347f80 CCIN=0000 CC=0001 -negb A=12348080 R=12348080 CCIN=0000 CC=0881 -negl A=12348080 R=edcb7f80 CCIN=0001 CC=0081 -negw A=12348080 R=12347f80 CCIN=0001 CC=0001 -negb A=12348080 R=12348080 CCIN=0001 CC=0881 -negl A=12348080 R=edcb7f80 CCIN=0000 CC=0081 -negw A=12348080 R=12347f80 CCIN=0000 CC=0001 -negb A=12348080 R=12348080 CCIN=0000 CC=0881 -negl A=12348080 R=edcb7f80 CCIN=0001 CC=0081 -negw A=12348080 R=12347f80 CCIN=0001 CC=0001 -negb A=12348080 R=12348080 CCIN=0001 CC=0881 -notl A=12345678 R=edcba987 CCIN=0000 CC=0000 -notw A=12345678 R=1234a987 CCIN=0000 CC=0000 -notb A=12345678 R=12345687 CCIN=0000 CC=0000 -notl A=12345678 R=edcba987 CCIN=0001 CC=0001 -notw A=12345678 R=1234a987 CCIN=0001 CC=0001 -notb A=12345678 R=12345687 CCIN=0001 CC=0001 -notl A=00012341 R=fffedcbe CCIN=0000 CC=0000 -notw A=00012341 R=0001dcbe CCIN=0000 CC=0000 -notb A=00012341 R=000123be CCIN=0000 CC=0000 -notl A=00012341 R=fffedcbe CCIN=0001 CC=0001 -notw A=00012341 R=0001dcbe CCIN=0001 CC=0001 -notb A=00012341 R=000123be CCIN=0001 CC=0001 -notl A=00012341 R=fffedcbe CCIN=0000 CC=0000 -notw A=00012341 R=0001dcbe CCIN=0000 CC=0000 -notb A=00012341 R=000123be CCIN=0000 CC=0000 -notl A=00012341 R=fffedcbe CCIN=0001 CC=0001 -notw A=00012341 R=0001dcbe CCIN=0001 CC=0001 -notb A=00012341 R=000123be CCIN=0001 CC=0001 -notl A=ffffffff R=00000000 CCIN=0000 CC=0000 -notw A=ffffffff R=ffff0000 CCIN=0000 CC=0000 -notb A=ffffffff R=ffffff00 CCIN=0000 CC=0000 -notl A=ffffffff R=00000000 CCIN=0001 CC=0001 -notw A=ffffffff R=ffff0000 CCIN=0001 CC=0001 -notb A=ffffffff R=ffffff00 CCIN=0001 CC=0001 -notl A=ffffffff R=00000000 CCIN=0000 CC=0000 -notw A=ffffffff R=ffff0000 CCIN=0000 CC=0000 -notb A=ffffffff R=ffffff00 CCIN=0000 CC=0000 -notl A=ffffffff R=00000000 CCIN=0001 CC=0001 -notw A=ffffffff R=ffff0000 CCIN=0001 CC=0001 -notb A=ffffffff R=ffffff00 CCIN=0001 CC=0001 -notl A=ffffffff R=00000000 CCIN=0000 CC=0000 -notw A=ffffffff R=ffff0000 CCIN=0000 CC=0000 -notb A=ffffffff R=ffffff00 CCIN=0000 CC=0000 -notl A=ffffffff R=00000000 CCIN=0001 CC=0001 -notw A=ffffffff R=ffff0000 CCIN=0001 CC=0001 -notb A=ffffffff R=ffffff00 CCIN=0001 CC=0001 -notl A=ffffffff R=00000000 CCIN=0000 CC=0000 -notw A=ffffffff R=ffff0000 CCIN=0000 CC=0000 -notb A=ffffffff R=ffffff00 CCIN=0000 CC=0000 -notl A=ffffffff R=00000000 CCIN=0001 CC=0001 -notw A=ffffffff R=ffff0000 CCIN=0001 CC=0001 -notb A=ffffffff R=ffffff00 CCIN=0001 CC=0001 -notl A=7fffffff R=80000000 CCIN=0000 CC=0000 -notw A=7fffffff R=7fff0000 CCIN=0000 CC=0000 -notb A=7fffffff R=7fffff00 CCIN=0000 CC=0000 -notl A=7fffffff R=80000000 CCIN=0001 CC=0001 -notw A=7fffffff R=7fff0000 CCIN=0001 CC=0001 -notb A=7fffffff R=7fffff00 CCIN=0001 CC=0001 -notl A=7fffffff R=80000000 CCIN=0000 CC=0000 -notw A=7fffffff R=7fff0000 CCIN=0000 CC=0000 -notb A=7fffffff R=7fffff00 CCIN=0000 CC=0000 -notl A=7fffffff R=80000000 CCIN=0001 CC=0001 -notw A=7fffffff R=7fff0000 CCIN=0001 CC=0001 -notb A=7fffffff R=7fffff00 CCIN=0001 CC=0001 -notl A=7fffffff R=80000000 CCIN=0000 CC=0000 -notw A=7fffffff R=7fff0000 CCIN=0000 CC=0000 -notb A=7fffffff R=7fffff00 CCIN=0000 CC=0000 -notl A=7fffffff R=80000000 CCIN=0001 CC=0001 -notw A=7fffffff R=7fff0000 CCIN=0001 CC=0001 -notb A=7fffffff R=7fffff00 CCIN=0001 CC=0001 -notl A=80000000 R=7fffffff CCIN=0000 CC=0000 -notw A=80000000 R=8000ffff CCIN=0000 CC=0000 -notb A=80000000 R=800000ff CCIN=0000 CC=0000 -notl A=80000000 R=7fffffff CCIN=0001 CC=0001 -notw A=80000000 R=8000ffff CCIN=0001 CC=0001 -notb A=80000000 R=800000ff CCIN=0001 CC=0001 -notl A=80000000 R=7fffffff CCIN=0000 CC=0000 -notw A=80000000 R=8000ffff CCIN=0000 CC=0000 -notb A=80000000 R=800000ff CCIN=0000 CC=0000 -notl A=80000000 R=7fffffff CCIN=0001 CC=0001 -notw A=80000000 R=8000ffff CCIN=0001 CC=0001 -notb A=80000000 R=800000ff CCIN=0001 CC=0001 -notl A=80000000 R=7fffffff CCIN=0000 CC=0000 -notw A=80000000 R=8000ffff CCIN=0000 CC=0000 -notb A=80000000 R=800000ff CCIN=0000 CC=0000 -notl A=80000000 R=7fffffff CCIN=0001 CC=0001 -notw A=80000000 R=8000ffff CCIN=0001 CC=0001 -notb A=80000000 R=800000ff CCIN=0001 CC=0001 -notl A=12347fff R=edcb8000 CCIN=0000 CC=0000 -notw A=12347fff R=12348000 CCIN=0000 CC=0000 -notb A=12347fff R=12347f00 CCIN=0000 CC=0000 -notl A=12347fff R=edcb8000 CCIN=0001 CC=0001 -notw A=12347fff R=12348000 CCIN=0001 CC=0001 -notb A=12347fff R=12347f00 CCIN=0001 CC=0001 -notl A=12347fff R=edcb8000 CCIN=0000 CC=0000 -notw A=12347fff R=12348000 CCIN=0000 CC=0000 -notb A=12347fff R=12347f00 CCIN=0000 CC=0000 -notl A=12347fff R=edcb8000 CCIN=0001 CC=0001 -notw A=12347fff R=12348000 CCIN=0001 CC=0001 -notb A=12347fff R=12347f00 CCIN=0001 CC=0001 -notl A=12347fff R=edcb8000 CCIN=0000 CC=0000 -notw A=12347fff R=12348000 CCIN=0000 CC=0000 -notb A=12347fff R=12347f00 CCIN=0000 CC=0000 -notl A=12347fff R=edcb8000 CCIN=0001 CC=0001 -notw A=12347fff R=12348000 CCIN=0001 CC=0001 -notb A=12347fff R=12347f00 CCIN=0001 CC=0001 -notl A=12348000 R=edcb7fff CCIN=0000 CC=0000 -notw A=12348000 R=12347fff CCIN=0000 CC=0000 -notb A=12348000 R=123480ff CCIN=0000 CC=0000 -notl A=12348000 R=edcb7fff CCIN=0001 CC=0001 -notw A=12348000 R=12347fff CCIN=0001 CC=0001 -notb A=12348000 R=123480ff CCIN=0001 CC=0001 -notl A=12348000 R=edcb7fff CCIN=0000 CC=0000 -notw A=12348000 R=12347fff CCIN=0000 CC=0000 -notb A=12348000 R=123480ff CCIN=0000 CC=0000 -notl A=12348000 R=edcb7fff CCIN=0001 CC=0001 -notw A=12348000 R=12347fff CCIN=0001 CC=0001 -notb A=12348000 R=123480ff CCIN=0001 CC=0001 -notl A=12348000 R=edcb7fff CCIN=0000 CC=0000 -notw A=12348000 R=12347fff CCIN=0000 CC=0000 -notb A=12348000 R=123480ff CCIN=0000 CC=0000 -notl A=12348000 R=edcb7fff CCIN=0001 CC=0001 -notw A=12348000 R=12347fff CCIN=0001 CC=0001 -notb A=12348000 R=123480ff CCIN=0001 CC=0001 -notl A=12347f7f R=edcb8080 CCIN=0000 CC=0000 -notw A=12347f7f R=12348080 CCIN=0000 CC=0000 -notb A=12347f7f R=12347f80 CCIN=0000 CC=0000 -notl A=12347f7f R=edcb8080 CCIN=0001 CC=0001 -notw A=12347f7f R=12348080 CCIN=0001 CC=0001 -notb A=12347f7f R=12347f80 CCIN=0001 CC=0001 -notl A=12347f7f R=edcb8080 CCIN=0000 CC=0000 -notw A=12347f7f R=12348080 CCIN=0000 CC=0000 -notb A=12347f7f R=12347f80 CCIN=0000 CC=0000 -notl A=12347f7f R=edcb8080 CCIN=0001 CC=0001 -notw A=12347f7f R=12348080 CCIN=0001 CC=0001 -notb A=12347f7f R=12347f80 CCIN=0001 CC=0001 -notl A=12347f7f R=edcb8080 CCIN=0000 CC=0000 -notw A=12347f7f R=12348080 CCIN=0000 CC=0000 -notb A=12347f7f R=12347f80 CCIN=0000 CC=0000 -notl A=12347f7f R=edcb8080 CCIN=0001 CC=0001 -notw A=12347f7f R=12348080 CCIN=0001 CC=0001 -notb A=12347f7f R=12347f80 CCIN=0001 CC=0001 -notl A=12348080 R=edcb7f7f CCIN=0000 CC=0000 -notw A=12348080 R=12347f7f CCIN=0000 CC=0000 -notb A=12348080 R=1234807f CCIN=0000 CC=0000 -notl A=12348080 R=edcb7f7f CCIN=0001 CC=0001 -notw A=12348080 R=12347f7f CCIN=0001 CC=0001 -notb A=12348080 R=1234807f CCIN=0001 CC=0001 -notl A=12348080 R=edcb7f7f CCIN=0000 CC=0000 -notw A=12348080 R=12347f7f CCIN=0000 CC=0000 -notb A=12348080 R=1234807f CCIN=0000 CC=0000 -notl A=12348080 R=edcb7f7f CCIN=0001 CC=0001 -notw A=12348080 R=12347f7f CCIN=0001 CC=0001 -notb A=12348080 R=1234807f CCIN=0001 CC=0001 -notl A=12348080 R=edcb7f7f CCIN=0000 CC=0000 -notw A=12348080 R=12347f7f CCIN=0000 CC=0000 -notb A=12348080 R=1234807f CCIN=0000 CC=0000 -notl A=12348080 R=edcb7f7f CCIN=0001 CC=0001 -notw A=12348080 R=12347f7f CCIN=0001 CC=0001 -notb A=12348080 R=1234807f CCIN=0001 CC=0001 -shll A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -shlw A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -shlb A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -shll A=12345678 B=00000001 R=2468acf0 CCIN=0000 CC=0004 -shlw A=12345678 B=00000001 R=1234acf0 CCIN=0000 CC=0884 -shlb A=12345678 B=00000001 R=123456f0 CCIN=0000 CC=0884 -shll A=12345678 B=00000002 R=48d159e0 CCIN=0000 CC=0000 -shlw A=12345678 B=00000002 R=123459e0 CCIN=0000 CC=0001 -shlb A=12345678 B=00000002 R=123456e0 CCIN=0000 CC=0081 -shll A=12345678 B=00000003 R=91a2b3c0 CCIN=0000 CC=0084 -shlw A=12345678 B=00000003 R=1234b3c0 CCIN=0000 CC=0084 -shlb A=12345678 B=00000003 R=123456c0 CCIN=0000 CC=0085 -shll A=12345678 B=00000004 R=23456780 CCIN=0000 CC=0001 -shlw A=12345678 B=00000004 R=12346780 CCIN=0000 CC=0001 -shlb A=12345678 B=00000004 R=12345680 CCIN=0000 CC=0081 -shll A=12345678 B=00000005 R=468acf00 CCIN=0000 CC=0004 -shlw A=12345678 B=00000005 R=1234cf00 CCIN=0000 CC=0084 -shlb A=12345678 B=00000005 R=12345600 CCIN=0000 CC=0045 -shll A=12345678 B=00000006 R=8d159e00 CCIN=0000 CC=0084 -shlw A=12345678 B=00000006 R=12349e00 CCIN=0000 CC=0085 -shlb A=12345678 B=00000006 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000007 R=1a2b3c00 CCIN=0000 CC=0005 -shlw A=12345678 B=00000007 R=12343c00 CCIN=0000 CC=0005 -shlb A=12345678 B=00000007 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000008 R=34567800 CCIN=0000 CC=0004 -shlw A=12345678 B=00000008 R=12347800 CCIN=0000 CC=0004 -shlb A=12345678 B=00000008 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000009 R=68acf000 CCIN=0000 CC=0004 -shlw A=12345678 B=00000009 R=1234f000 CCIN=0000 CC=0084 -shlb A=12345678 B=00000009 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000000a R=d159e000 CCIN=0000 CC=0084 -shlw A=12345678 B=0000000a R=1234e000 CCIN=0000 CC=0085 -shlb A=12345678 B=0000000a R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000000b R=a2b3c000 CCIN=0000 CC=0085 -shlw A=12345678 B=0000000b R=1234c000 CCIN=0000 CC=0085 -shlb A=12345678 B=0000000b R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000000c R=45678000 CCIN=0000 CC=0005 -shlw A=12345678 B=0000000c R=12348000 CCIN=0000 CC=0085 -shlb A=12345678 B=0000000c R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000000d R=8acf0000 CCIN=0000 CC=0084 -shlw A=12345678 B=0000000d R=12340000 CCIN=0000 CC=0045 -shlb A=12345678 B=0000000d R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000000e R=159e0000 CCIN=0000 CC=0005 -shlw A=12345678 B=0000000e R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=0000000e R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000000f R=2b3c0000 CCIN=0000 CC=0004 -shlw A=12345678 B=0000000f R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=0000000f R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000010 R=56780000 CCIN=0000 CC=0004 -shlw A=12345678 B=00000010 R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=00000010 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000011 R=acf00000 CCIN=0000 CC=0084 -shlw A=12345678 B=00000011 R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=00000011 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000012 R=59e00000 CCIN=0000 CC=0005 -shlw A=12345678 B=00000012 R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=00000012 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000013 R=b3c00000 CCIN=0000 CC=0084 -shlw A=12345678 B=00000013 R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=00000013 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000014 R=67800000 CCIN=0000 CC=0005 -shlw A=12345678 B=00000014 R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=00000014 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000015 R=cf000000 CCIN=0000 CC=0084 -shlw A=12345678 B=00000015 R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=00000015 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000016 R=9e000000 CCIN=0000 CC=0085 -shlw A=12345678 B=00000016 R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=00000016 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000017 R=3c000000 CCIN=0000 CC=0005 -shlw A=12345678 B=00000017 R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=00000017 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000018 R=78000000 CCIN=0000 CC=0004 -shlw A=12345678 B=00000018 R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=00000018 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=00000019 R=f0000000 CCIN=0000 CC=0084 -shlw A=12345678 B=00000019 R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=00000019 R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000001a R=e0000000 CCIN=0000 CC=0085 -shlw A=12345678 B=0000001a R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=0000001a R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000001b R=c0000000 CCIN=0000 CC=0085 -shlw A=12345678 B=0000001b R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=0000001b R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000001c R=80000000 CCIN=0000 CC=0085 -shlw A=12345678 B=0000001c R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=0000001c R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000001d R=00000000 CCIN=0000 CC=0045 -shlw A=12345678 B=0000001d R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=0000001d R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000001e R=00000000 CCIN=0000 CC=0044 -shlw A=12345678 B=0000001e R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=0000001e R=12345600 CCIN=0000 CC=0044 -shll A=12345678 B=0000001f R=00000000 CCIN=0000 CC=0044 -shlw A=12345678 B=0000001f R=12340000 CCIN=0000 CC=0044 -shlb A=12345678 B=0000001f R=12345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -shlw A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -shlb A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -shll A=82345679 B=00000001 R=0468acf2 CCIN=0000 CC=0801 -shlw A=82345679 B=00000001 R=8234acf2 CCIN=0000 CC=0880 -shlb A=82345679 B=00000001 R=823456f2 CCIN=0000 CC=0880 -shll A=82345679 B=00000002 R=08d159e4 CCIN=0000 CC=0004 -shlw A=82345679 B=00000002 R=823459e4 CCIN=0000 CC=0005 -shlb A=82345679 B=00000002 R=823456e4 CCIN=0000 CC=0085 -shll A=82345679 B=00000003 R=11a2b3c8 CCIN=0000 CC=0000 -shlw A=82345679 B=00000003 R=8234b3c8 CCIN=0000 CC=0080 -shlb A=82345679 B=00000003 R=823456c8 CCIN=0000 CC=0081 -shll A=82345679 B=00000004 R=23456790 CCIN=0000 CC=0004 -shlw A=82345679 B=00000004 R=82346790 CCIN=0000 CC=0005 -shlb A=82345679 B=00000004 R=82345690 CCIN=0000 CC=0085 -shll A=82345679 B=00000005 R=468acf20 CCIN=0000 CC=0000 -shlw A=82345679 B=00000005 R=8234cf20 CCIN=0000 CC=0080 -shlb A=82345679 B=00000005 R=82345620 CCIN=0000 CC=0001 -shll A=82345679 B=00000006 R=8d159e40 CCIN=0000 CC=0080 -shlw A=82345679 B=00000006 R=82349e40 CCIN=0000 CC=0081 -shlb A=82345679 B=00000006 R=82345640 CCIN=0000 CC=0000 -shll A=82345679 B=00000007 R=1a2b3c80 CCIN=0000 CC=0001 -shlw A=82345679 B=00000007 R=82343c80 CCIN=0000 CC=0001 -shlb A=82345679 B=00000007 R=82345680 CCIN=0000 CC=0080 -shll A=82345679 B=00000008 R=34567900 CCIN=0000 CC=0004 -shlw A=82345679 B=00000008 R=82347900 CCIN=0000 CC=0004 -shlb A=82345679 B=00000008 R=82345600 CCIN=0000 CC=0045 -shll A=82345679 B=00000009 R=68acf200 CCIN=0000 CC=0004 -shlw A=82345679 B=00000009 R=8234f200 CCIN=0000 CC=0084 -shlb A=82345679 B=00000009 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000000a R=d159e400 CCIN=0000 CC=0084 -shlw A=82345679 B=0000000a R=8234e400 CCIN=0000 CC=0085 -shlb A=82345679 B=0000000a R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000000b R=a2b3c800 CCIN=0000 CC=0085 -shlw A=82345679 B=0000000b R=8234c800 CCIN=0000 CC=0085 -shlb A=82345679 B=0000000b R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000000c R=45679000 CCIN=0000 CC=0005 -shlw A=82345679 B=0000000c R=82349000 CCIN=0000 CC=0085 -shlb A=82345679 B=0000000c R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000000d R=8acf2000 CCIN=0000 CC=0084 -shlw A=82345679 B=0000000d R=82342000 CCIN=0000 CC=0005 -shlb A=82345679 B=0000000d R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000000e R=159e4000 CCIN=0000 CC=0005 -shlw A=82345679 B=0000000e R=82344000 CCIN=0000 CC=0004 -shlb A=82345679 B=0000000e R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000000f R=2b3c8000 CCIN=0000 CC=0004 -shlw A=82345679 B=0000000f R=82348000 CCIN=0000 CC=0084 -shlb A=82345679 B=0000000f R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000010 R=56790000 CCIN=0000 CC=0004 -shlw A=82345679 B=00000010 R=82340000 CCIN=0000 CC=0045 -shlb A=82345679 B=00000010 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000011 R=acf20000 CCIN=0000 CC=0084 -shlw A=82345679 B=00000011 R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=00000011 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000012 R=59e40000 CCIN=0000 CC=0005 -shlw A=82345679 B=00000012 R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=00000012 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000013 R=b3c80000 CCIN=0000 CC=0084 -shlw A=82345679 B=00000013 R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=00000013 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000014 R=67900000 CCIN=0000 CC=0005 -shlw A=82345679 B=00000014 R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=00000014 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000015 R=cf200000 CCIN=0000 CC=0084 -shlw A=82345679 B=00000015 R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=00000015 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000016 R=9e400000 CCIN=0000 CC=0085 -shlw A=82345679 B=00000016 R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=00000016 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000017 R=3c800000 CCIN=0000 CC=0005 -shlw A=82345679 B=00000017 R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=00000017 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000018 R=79000000 CCIN=0000 CC=0004 -shlw A=82345679 B=00000018 R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=00000018 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=00000019 R=f2000000 CCIN=0000 CC=0084 -shlw A=82345679 B=00000019 R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=00000019 R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000001a R=e4000000 CCIN=0000 CC=0085 -shlw A=82345679 B=0000001a R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=0000001a R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000001b R=c8000000 CCIN=0000 CC=0085 -shlw A=82345679 B=0000001b R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=0000001b R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000001c R=90000000 CCIN=0000 CC=0085 -shlw A=82345679 B=0000001c R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=0000001c R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000001d R=20000000 CCIN=0000 CC=0005 -shlw A=82345679 B=0000001d R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=0000001d R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000001e R=40000000 CCIN=0000 CC=0004 -shlw A=82345679 B=0000001e R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=0000001e R=82345600 CCIN=0000 CC=0044 -shll A=82345679 B=0000001f R=80000000 CCIN=0000 CC=0084 -shlw A=82345679 B=0000001f R=82340000 CCIN=0000 CC=0044 -shlb A=82345679 B=0000001f R=82345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -shrw A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -shrb A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -shrl A=12345678 B=00000001 R=091a2b3c CCIN=0000 CC=0004 -shrw A=12345678 B=00000001 R=12342b3c CCIN=0000 CC=0004 -shrb A=12345678 B=00000001 R=1234563c CCIN=0000 CC=0004 -shrl A=12345678 B=00000002 R=048d159e CCIN=0000 CC=0000 -shrw A=12345678 B=00000002 R=1234159e CCIN=0000 CC=0000 -shrb A=12345678 B=00000002 R=1234561e CCIN=0000 CC=0004 -shrl A=12345678 B=00000003 R=02468acf CCIN=0000 CC=0004 -shrw A=12345678 B=00000003 R=12340acf CCIN=0000 CC=0004 -shrb A=12345678 B=00000003 R=1234560f CCIN=0000 CC=0004 -shrl A=12345678 B=00000004 R=01234567 CCIN=0000 CC=0001 -shrw A=12345678 B=00000004 R=12340567 CCIN=0000 CC=0001 -shrb A=12345678 B=00000004 R=12345607 CCIN=0000 CC=0001 -shrl A=12345678 B=00000005 R=0091a2b3 CCIN=0000 CC=0001 -shrw A=12345678 B=00000005 R=123402b3 CCIN=0000 CC=0001 -shrb A=12345678 B=00000005 R=12345603 CCIN=0000 CC=0005 -shrl A=12345678 B=00000006 R=0048d159 CCIN=0000 CC=0005 -shrw A=12345678 B=00000006 R=12340159 CCIN=0000 CC=0005 -shrb A=12345678 B=00000006 R=12345601 CCIN=0000 CC=0001 -shrl A=12345678 B=00000007 R=002468ac CCIN=0000 CC=0005 -shrw A=12345678 B=00000007 R=123400ac CCIN=0000 CC=0005 -shrb A=12345678 B=00000007 R=12345600 CCIN=0000 CC=0045 -shrl A=12345678 B=00000008 R=00123456 CCIN=0000 CC=0004 -shrw A=12345678 B=00000008 R=12340056 CCIN=0000 CC=0004 -shrb A=12345678 B=00000008 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000009 R=00091a2b CCIN=0000 CC=0004 -shrw A=12345678 B=00000009 R=1234002b CCIN=0000 CC=0004 -shrb A=12345678 B=00000009 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000000a R=00048d15 CCIN=0000 CC=0001 -shrw A=12345678 B=0000000a R=12340015 CCIN=0000 CC=0001 -shrb A=12345678 B=0000000a R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000000b R=0002468a CCIN=0000 CC=0001 -shrw A=12345678 B=0000000b R=1234000a CCIN=0000 CC=0005 -shrb A=12345678 B=0000000b R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000000c R=00012345 CCIN=0000 CC=0000 -shrw A=12345678 B=0000000c R=12340005 CCIN=0000 CC=0004 -shrb A=12345678 B=0000000c R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000000d R=000091a2 CCIN=0000 CC=0001 -shrw A=12345678 B=0000000d R=12340002 CCIN=0000 CC=0001 -shrb A=12345678 B=0000000d R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000000e R=000048d1 CCIN=0000 CC=0004 -shrw A=12345678 B=0000000e R=12340001 CCIN=0000 CC=0000 -shrb A=12345678 B=0000000e R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000000f R=00002468 CCIN=0000 CC=0001 -shrw A=12345678 B=0000000f R=12340000 CCIN=0000 CC=0045 -shrb A=12345678 B=0000000f R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000010 R=00001234 CCIN=0000 CC=0000 -shrw A=12345678 B=00000010 R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=00000010 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000011 R=0000091a CCIN=0000 CC=0000 -shrw A=12345678 B=00000011 R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=00000011 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000012 R=0000048d CCIN=0000 CC=0004 -shrw A=12345678 B=00000012 R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=00000012 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000013 R=00000246 CCIN=0000 CC=0001 -shrw A=12345678 B=00000013 R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=00000013 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000014 R=00000123 CCIN=0000 CC=0000 -shrw A=12345678 B=00000014 R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=00000014 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000015 R=00000091 CCIN=0000 CC=0001 -shrw A=12345678 B=00000015 R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=00000015 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000016 R=00000048 CCIN=0000 CC=0005 -shrw A=12345678 B=00000016 R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=00000016 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000017 R=00000024 CCIN=0000 CC=0004 -shrw A=12345678 B=00000017 R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=00000017 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000018 R=00000012 CCIN=0000 CC=0004 -shrw A=12345678 B=00000018 R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=00000018 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=00000019 R=00000009 CCIN=0000 CC=0004 -shrw A=12345678 B=00000019 R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=00000019 R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000001a R=00000004 CCIN=0000 CC=0001 -shrw A=12345678 B=0000001a R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=0000001a R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000001b R=00000002 CCIN=0000 CC=0000 -shrw A=12345678 B=0000001b R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=0000001b R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000001c R=00000001 CCIN=0000 CC=0000 -shrw A=12345678 B=0000001c R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=0000001c R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000001d R=00000000 CCIN=0000 CC=0045 -shrw A=12345678 B=0000001d R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=0000001d R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000001e R=00000000 CCIN=0000 CC=0044 -shrw A=12345678 B=0000001e R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=0000001e R=12345600 CCIN=0000 CC=0044 -shrl A=12345678 B=0000001f R=00000000 CCIN=0000 CC=0044 -shrw A=12345678 B=0000001f R=12340000 CCIN=0000 CC=0044 -shrb A=12345678 B=0000001f R=12345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -shrw A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -shrb A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -shrl A=82345679 B=00000001 R=411a2b3c CCIN=0000 CC=0805 -shrw A=82345679 B=00000001 R=82342b3c CCIN=0000 CC=0005 -shrb A=82345679 B=00000001 R=8234563c CCIN=0000 CC=0005 -shrl A=82345679 B=00000002 R=208d159e CCIN=0000 CC=0000 -shrw A=82345679 B=00000002 R=8234159e CCIN=0000 CC=0000 -shrb A=82345679 B=00000002 R=8234561e CCIN=0000 CC=0004 -shrl A=82345679 B=00000003 R=10468acf CCIN=0000 CC=0004 -shrw A=82345679 B=00000003 R=82340acf CCIN=0000 CC=0004 -shrb A=82345679 B=00000003 R=8234560f CCIN=0000 CC=0004 -shrl A=82345679 B=00000004 R=08234567 CCIN=0000 CC=0001 -shrw A=82345679 B=00000004 R=82340567 CCIN=0000 CC=0001 -shrb A=82345679 B=00000004 R=82345607 CCIN=0000 CC=0001 -shrl A=82345679 B=00000005 R=0411a2b3 CCIN=0000 CC=0001 -shrw A=82345679 B=00000005 R=823402b3 CCIN=0000 CC=0001 -shrb A=82345679 B=00000005 R=82345603 CCIN=0000 CC=0005 -shrl A=82345679 B=00000006 R=0208d159 CCIN=0000 CC=0005 -shrw A=82345679 B=00000006 R=82340159 CCIN=0000 CC=0005 -shrb A=82345679 B=00000006 R=82345601 CCIN=0000 CC=0001 -shrl A=82345679 B=00000007 R=010468ac CCIN=0000 CC=0005 -shrw A=82345679 B=00000007 R=823400ac CCIN=0000 CC=0005 -shrb A=82345679 B=00000007 R=82345600 CCIN=0000 CC=0045 -shrl A=82345679 B=00000008 R=00823456 CCIN=0000 CC=0004 -shrw A=82345679 B=00000008 R=82340056 CCIN=0000 CC=0004 -shrb A=82345679 B=00000008 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000009 R=00411a2b CCIN=0000 CC=0004 -shrw A=82345679 B=00000009 R=8234002b CCIN=0000 CC=0004 -shrb A=82345679 B=00000009 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000000a R=00208d15 CCIN=0000 CC=0001 -shrw A=82345679 B=0000000a R=82340015 CCIN=0000 CC=0001 -shrb A=82345679 B=0000000a R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000000b R=0010468a CCIN=0000 CC=0001 -shrw A=82345679 B=0000000b R=8234000a CCIN=0000 CC=0005 -shrb A=82345679 B=0000000b R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000000c R=00082345 CCIN=0000 CC=0000 -shrw A=82345679 B=0000000c R=82340005 CCIN=0000 CC=0004 -shrb A=82345679 B=0000000c R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000000d R=000411a2 CCIN=0000 CC=0001 -shrw A=82345679 B=0000000d R=82340002 CCIN=0000 CC=0001 -shrb A=82345679 B=0000000d R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000000e R=000208d1 CCIN=0000 CC=0004 -shrw A=82345679 B=0000000e R=82340001 CCIN=0000 CC=0000 -shrb A=82345679 B=0000000e R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000000f R=00010468 CCIN=0000 CC=0001 -shrw A=82345679 B=0000000f R=82340000 CCIN=0000 CC=0045 -shrb A=82345679 B=0000000f R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000010 R=00008234 CCIN=0000 CC=0000 -shrw A=82345679 B=00000010 R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=00000010 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000011 R=0000411a CCIN=0000 CC=0000 -shrw A=82345679 B=00000011 R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=00000011 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000012 R=0000208d CCIN=0000 CC=0004 -shrw A=82345679 B=00000012 R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=00000012 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000013 R=00001046 CCIN=0000 CC=0001 -shrw A=82345679 B=00000013 R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=00000013 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000014 R=00000823 CCIN=0000 CC=0000 -shrw A=82345679 B=00000014 R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=00000014 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000015 R=00000411 CCIN=0000 CC=0005 -shrw A=82345679 B=00000015 R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=00000015 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000016 R=00000208 CCIN=0000 CC=0001 -shrw A=82345679 B=00000016 R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=00000016 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000017 R=00000104 CCIN=0000 CC=0000 -shrw A=82345679 B=00000017 R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=00000017 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000018 R=00000082 CCIN=0000 CC=0004 -shrw A=82345679 B=00000018 R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=00000018 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=00000019 R=00000041 CCIN=0000 CC=0004 -shrw A=82345679 B=00000019 R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=00000019 R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000001a R=00000020 CCIN=0000 CC=0001 -shrw A=82345679 B=0000001a R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=0000001a R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000001b R=00000010 CCIN=0000 CC=0000 -shrw A=82345679 B=0000001b R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=0000001b R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000001c R=00000008 CCIN=0000 CC=0000 -shrw A=82345679 B=0000001c R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=0000001c R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000001d R=00000004 CCIN=0000 CC=0000 -shrw A=82345679 B=0000001d R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=0000001d R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000001e R=00000002 CCIN=0000 CC=0000 -shrw A=82345679 B=0000001e R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=0000001e R=82345600 CCIN=0000 CC=0044 -shrl A=82345679 B=0000001f R=00000001 CCIN=0000 CC=0000 -shrw A=82345679 B=0000001f R=82340000 CCIN=0000 CC=0044 -shrb A=82345679 B=0000001f R=82345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -sarw A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -sarb A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -sarl A=12345678 B=00000001 R=091a2b3c CCIN=0000 CC=0004 -sarw A=12345678 B=00000001 R=12342b3c CCIN=0000 CC=0004 -sarb A=12345678 B=00000001 R=1234563c CCIN=0000 CC=0004 -sarl A=12345678 B=00000002 R=048d159e CCIN=0000 CC=0000 -sarw A=12345678 B=00000002 R=1234159e CCIN=0000 CC=0000 -sarb A=12345678 B=00000002 R=1234561e CCIN=0000 CC=0004 -sarl A=12345678 B=00000003 R=02468acf CCIN=0000 CC=0004 -sarw A=12345678 B=00000003 R=12340acf CCIN=0000 CC=0004 -sarb A=12345678 B=00000003 R=1234560f CCIN=0000 CC=0004 -sarl A=12345678 B=00000004 R=01234567 CCIN=0000 CC=0001 -sarw A=12345678 B=00000004 R=12340567 CCIN=0000 CC=0001 -sarb A=12345678 B=00000004 R=12345607 CCIN=0000 CC=0001 -sarl A=12345678 B=00000005 R=0091a2b3 CCIN=0000 CC=0001 -sarw A=12345678 B=00000005 R=123402b3 CCIN=0000 CC=0001 -sarb A=12345678 B=00000005 R=12345603 CCIN=0000 CC=0005 -sarl A=12345678 B=00000006 R=0048d159 CCIN=0000 CC=0005 -sarw A=12345678 B=00000006 R=12340159 CCIN=0000 CC=0005 -sarb A=12345678 B=00000006 R=12345601 CCIN=0000 CC=0001 -sarl A=12345678 B=00000007 R=002468ac CCIN=0000 CC=0005 -sarw A=12345678 B=00000007 R=123400ac CCIN=0000 CC=0005 -sarb A=12345678 B=00000007 R=12345600 CCIN=0000 CC=0045 -sarl A=12345678 B=00000008 R=00123456 CCIN=0000 CC=0004 -sarw A=12345678 B=00000008 R=12340056 CCIN=0000 CC=0004 -sarb A=12345678 B=00000008 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000009 R=00091a2b CCIN=0000 CC=0004 -sarw A=12345678 B=00000009 R=1234002b CCIN=0000 CC=0004 -sarb A=12345678 B=00000009 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000000a R=00048d15 CCIN=0000 CC=0001 -sarw A=12345678 B=0000000a R=12340015 CCIN=0000 CC=0001 -sarb A=12345678 B=0000000a R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000000b R=0002468a CCIN=0000 CC=0001 -sarw A=12345678 B=0000000b R=1234000a CCIN=0000 CC=0005 -sarb A=12345678 B=0000000b R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000000c R=00012345 CCIN=0000 CC=0000 -sarw A=12345678 B=0000000c R=12340005 CCIN=0000 CC=0004 -sarb A=12345678 B=0000000c R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000000d R=000091a2 CCIN=0000 CC=0001 -sarw A=12345678 B=0000000d R=12340002 CCIN=0000 CC=0001 -sarb A=12345678 B=0000000d R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000000e R=000048d1 CCIN=0000 CC=0004 -sarw A=12345678 B=0000000e R=12340001 CCIN=0000 CC=0000 -sarb A=12345678 B=0000000e R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000000f R=00002468 CCIN=0000 CC=0001 -sarw A=12345678 B=0000000f R=12340000 CCIN=0000 CC=0045 -sarb A=12345678 B=0000000f R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000010 R=00001234 CCIN=0000 CC=0000 -sarw A=12345678 B=00000010 R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=00000010 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000011 R=0000091a CCIN=0000 CC=0000 -sarw A=12345678 B=00000011 R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=00000011 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000012 R=0000048d CCIN=0000 CC=0004 -sarw A=12345678 B=00000012 R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=00000012 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000013 R=00000246 CCIN=0000 CC=0001 -sarw A=12345678 B=00000013 R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=00000013 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000014 R=00000123 CCIN=0000 CC=0000 -sarw A=12345678 B=00000014 R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=00000014 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000015 R=00000091 CCIN=0000 CC=0001 -sarw A=12345678 B=00000015 R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=00000015 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000016 R=00000048 CCIN=0000 CC=0005 -sarw A=12345678 B=00000016 R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=00000016 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000017 R=00000024 CCIN=0000 CC=0004 -sarw A=12345678 B=00000017 R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=00000017 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000018 R=00000012 CCIN=0000 CC=0004 -sarw A=12345678 B=00000018 R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=00000018 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=00000019 R=00000009 CCIN=0000 CC=0004 -sarw A=12345678 B=00000019 R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=00000019 R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000001a R=00000004 CCIN=0000 CC=0001 -sarw A=12345678 B=0000001a R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=0000001a R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000001b R=00000002 CCIN=0000 CC=0000 -sarw A=12345678 B=0000001b R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=0000001b R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000001c R=00000001 CCIN=0000 CC=0000 -sarw A=12345678 B=0000001c R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=0000001c R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000001d R=00000000 CCIN=0000 CC=0045 -sarw A=12345678 B=0000001d R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=0000001d R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000001e R=00000000 CCIN=0000 CC=0044 -sarw A=12345678 B=0000001e R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=0000001e R=12345600 CCIN=0000 CC=0044 -sarl A=12345678 B=0000001f R=00000000 CCIN=0000 CC=0044 -sarw A=12345678 B=0000001f R=12340000 CCIN=0000 CC=0044 -sarb A=12345678 B=0000001f R=12345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -sarw A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -sarb A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -sarl A=82345679 B=00000001 R=c11a2b3c CCIN=0000 CC=0085 -sarw A=82345679 B=00000001 R=82342b3c CCIN=0000 CC=0005 -sarb A=82345679 B=00000001 R=8234563c CCIN=0000 CC=0005 -sarl A=82345679 B=00000002 R=e08d159e CCIN=0000 CC=0080 -sarw A=82345679 B=00000002 R=8234159e CCIN=0000 CC=0000 -sarb A=82345679 B=00000002 R=8234561e CCIN=0000 CC=0004 -sarl A=82345679 B=00000003 R=f0468acf CCIN=0000 CC=0084 -sarw A=82345679 B=00000003 R=82340acf CCIN=0000 CC=0004 -sarb A=82345679 B=00000003 R=8234560f CCIN=0000 CC=0004 -sarl A=82345679 B=00000004 R=f8234567 CCIN=0000 CC=0081 -sarw A=82345679 B=00000004 R=82340567 CCIN=0000 CC=0001 -sarb A=82345679 B=00000004 R=82345607 CCIN=0000 CC=0001 -sarl A=82345679 B=00000005 R=fc11a2b3 CCIN=0000 CC=0081 -sarw A=82345679 B=00000005 R=823402b3 CCIN=0000 CC=0001 -sarb A=82345679 B=00000005 R=82345603 CCIN=0000 CC=0005 -sarl A=82345679 B=00000006 R=fe08d159 CCIN=0000 CC=0085 -sarw A=82345679 B=00000006 R=82340159 CCIN=0000 CC=0005 -sarb A=82345679 B=00000006 R=82345601 CCIN=0000 CC=0001 -sarl A=82345679 B=00000007 R=ff0468ac CCIN=0000 CC=0085 -sarw A=82345679 B=00000007 R=823400ac CCIN=0000 CC=0005 -sarb A=82345679 B=00000007 R=82345600 CCIN=0000 CC=0045 -sarl A=82345679 B=00000008 R=ff823456 CCIN=0000 CC=0084 -sarw A=82345679 B=00000008 R=82340056 CCIN=0000 CC=0004 -sarb A=82345679 B=00000008 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000009 R=ffc11a2b CCIN=0000 CC=0084 -sarw A=82345679 B=00000009 R=8234002b CCIN=0000 CC=0004 -sarb A=82345679 B=00000009 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000000a R=ffe08d15 CCIN=0000 CC=0081 -sarw A=82345679 B=0000000a R=82340015 CCIN=0000 CC=0001 -sarb A=82345679 B=0000000a R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000000b R=fff0468a CCIN=0000 CC=0081 -sarw A=82345679 B=0000000b R=8234000a CCIN=0000 CC=0005 -sarb A=82345679 B=0000000b R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000000c R=fff82345 CCIN=0000 CC=0080 -sarw A=82345679 B=0000000c R=82340005 CCIN=0000 CC=0004 -sarb A=82345679 B=0000000c R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000000d R=fffc11a2 CCIN=0000 CC=0081 -sarw A=82345679 B=0000000d R=82340002 CCIN=0000 CC=0001 -sarb A=82345679 B=0000000d R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000000e R=fffe08d1 CCIN=0000 CC=0084 -sarw A=82345679 B=0000000e R=82340001 CCIN=0000 CC=0000 -sarb A=82345679 B=0000000e R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000000f R=ffff0468 CCIN=0000 CC=0081 -sarw A=82345679 B=0000000f R=82340000 CCIN=0000 CC=0045 -sarb A=82345679 B=0000000f R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000010 R=ffff8234 CCIN=0000 CC=0080 -sarw A=82345679 B=00000010 R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=00000010 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000011 R=ffffc11a CCIN=0000 CC=0080 -sarw A=82345679 B=00000011 R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=00000011 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000012 R=ffffe08d CCIN=0000 CC=0084 -sarw A=82345679 B=00000012 R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=00000012 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000013 R=fffff046 CCIN=0000 CC=0081 -sarw A=82345679 B=00000013 R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=00000013 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000014 R=fffff823 CCIN=0000 CC=0080 -sarw A=82345679 B=00000014 R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=00000014 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000015 R=fffffc11 CCIN=0000 CC=0085 -sarw A=82345679 B=00000015 R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=00000015 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000016 R=fffffe08 CCIN=0000 CC=0081 -sarw A=82345679 B=00000016 R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=00000016 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000017 R=ffffff04 CCIN=0000 CC=0080 -sarw A=82345679 B=00000017 R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=00000017 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000018 R=ffffff82 CCIN=0000 CC=0084 -sarw A=82345679 B=00000018 R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=00000018 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=00000019 R=ffffffc1 CCIN=0000 CC=0080 -sarw A=82345679 B=00000019 R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=00000019 R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000001a R=ffffffe0 CCIN=0000 CC=0081 -sarw A=82345679 B=0000001a R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=0000001a R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000001b R=fffffff0 CCIN=0000 CC=0084 -sarw A=82345679 B=0000001b R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=0000001b R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000001c R=fffffff8 CCIN=0000 CC=0080 -sarw A=82345679 B=0000001c R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=0000001c R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000001d R=fffffffc CCIN=0000 CC=0084 -sarw A=82345679 B=0000001d R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=0000001d R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000001e R=fffffffe CCIN=0000 CC=0080 -sarw A=82345679 B=0000001e R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=0000001e R=82345600 CCIN=0000 CC=0044 -sarl A=82345679 B=0000001f R=ffffffff CCIN=0000 CC=0084 -sarw A=82345679 B=0000001f R=82340000 CCIN=0000 CC=0044 -sarb A=82345679 B=0000001f R=82345600 CCIN=0000 CC=0044 -roll A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rolw A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rolb A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -roll A=12345678 B=00000001 R=2468acf0 CCIN=0000 CC=0000 -rolw A=12345678 B=00000001 R=1234acf0 CCIN=0000 CC=0800 -rolb A=12345678 B=00000001 R=123456f0 CCIN=0000 CC=0800 -roll A=12345678 B=00000002 R=48d159e0 CCIN=0000 CC=0000 -rolw A=12345678 B=00000002 R=123459e1 CCIN=0000 CC=0001 -rolb A=12345678 B=00000002 R=123456e1 CCIN=0000 CC=0001 -roll A=12345678 B=00000003 R=91a2b3c0 CCIN=0000 CC=0000 -rolw A=12345678 B=00000003 R=1234b3c2 CCIN=0000 CC=0000 -rolb A=12345678 B=00000003 R=123456c3 CCIN=0000 CC=0001 -roll A=12345678 B=00000004 R=23456781 CCIN=0000 CC=0001 -rolw A=12345678 B=00000004 R=12346785 CCIN=0000 CC=0001 -rolb A=12345678 B=00000004 R=12345687 CCIN=0000 CC=0001 -roll A=12345678 B=00000005 R=468acf02 CCIN=0000 CC=0000 -rolw A=12345678 B=00000005 R=1234cf0a CCIN=0000 CC=0000 -rolb A=12345678 B=00000005 R=1234560f CCIN=0000 CC=0001 -roll A=12345678 B=00000006 R=8d159e04 CCIN=0000 CC=0000 -rolw A=12345678 B=00000006 R=12349e15 CCIN=0000 CC=0001 -rolb A=12345678 B=00000006 R=1234561e CCIN=0000 CC=0000 -roll A=12345678 B=00000007 R=1a2b3c09 CCIN=0000 CC=0001 -rolw A=12345678 B=00000007 R=12343c2b CCIN=0000 CC=0001 -rolb A=12345678 B=00000007 R=1234563c CCIN=0000 CC=0000 -roll A=12345678 B=00000008 R=34567812 CCIN=0000 CC=0000 -rolw A=12345678 B=00000008 R=12347856 CCIN=0000 CC=0000 -rolb A=12345678 B=00000008 R=12345678 CCIN=0000 CC=0000 -roll A=12345678 B=00000009 R=68acf024 CCIN=0000 CC=0000 -rolw A=12345678 B=00000009 R=1234f0ac CCIN=0000 CC=0000 -rolb A=12345678 B=00000009 R=123456f0 CCIN=0000 CC=0000 -roll A=12345678 B=0000000a R=d159e048 CCIN=0000 CC=0000 -rolw A=12345678 B=0000000a R=1234e159 CCIN=0000 CC=0001 -rolb A=12345678 B=0000000a R=123456e1 CCIN=0000 CC=0001 -roll A=12345678 B=0000000b R=a2b3c091 CCIN=0000 CC=0001 -rolw A=12345678 B=0000000b R=1234c2b3 CCIN=0000 CC=0001 -rolb A=12345678 B=0000000b R=123456c3 CCIN=0000 CC=0001 -roll A=12345678 B=0000000c R=45678123 CCIN=0000 CC=0001 -rolw A=12345678 B=0000000c R=12348567 CCIN=0000 CC=0001 -rolb A=12345678 B=0000000c R=12345687 CCIN=0000 CC=0001 -roll A=12345678 B=0000000d R=8acf0246 CCIN=0000 CC=0000 -rolw A=12345678 B=0000000d R=12340acf CCIN=0000 CC=0001 -rolb A=12345678 B=0000000d R=1234560f CCIN=0000 CC=0001 -roll A=12345678 B=0000000e R=159e048d CCIN=0000 CC=0001 -rolw A=12345678 B=0000000e R=1234159e CCIN=0000 CC=0000 -rolb A=12345678 B=0000000e R=1234561e CCIN=0000 CC=0000 -roll A=12345678 B=0000000f R=2b3c091a CCIN=0000 CC=0000 -rolw A=12345678 B=0000000f R=12342b3c CCIN=0000 CC=0000 -rolb A=12345678 B=0000000f R=1234563c CCIN=0000 CC=0000 -roll A=12345678 B=00000010 R=56781234 CCIN=0000 CC=0000 -rolw A=12345678 B=00000010 R=12345678 CCIN=0000 CC=0000 -rolb A=12345678 B=00000010 R=12345678 CCIN=0000 CC=0000 -roll A=12345678 B=00000011 R=acf02468 CCIN=0000 CC=0000 -rolw A=12345678 B=00000011 R=1234acf0 CCIN=0000 CC=0000 -rolb A=12345678 B=00000011 R=123456f0 CCIN=0000 CC=0000 -roll A=12345678 B=00000012 R=59e048d1 CCIN=0000 CC=0001 -rolw A=12345678 B=00000012 R=123459e1 CCIN=0000 CC=0001 -rolb A=12345678 B=00000012 R=123456e1 CCIN=0000 CC=0001 -roll A=12345678 B=00000013 R=b3c091a2 CCIN=0000 CC=0000 -rolw A=12345678 B=00000013 R=1234b3c2 CCIN=0000 CC=0000 -rolb A=12345678 B=00000013 R=123456c3 CCIN=0000 CC=0001 -roll A=12345678 B=00000014 R=67812345 CCIN=0000 CC=0001 -rolw A=12345678 B=00000014 R=12346785 CCIN=0000 CC=0001 -rolb A=12345678 B=00000014 R=12345687 CCIN=0000 CC=0001 -roll A=12345678 B=00000015 R=cf02468a CCIN=0000 CC=0000 -rolw A=12345678 B=00000015 R=1234cf0a CCIN=0000 CC=0000 -rolb A=12345678 B=00000015 R=1234560f CCIN=0000 CC=0001 -roll A=12345678 B=00000016 R=9e048d15 CCIN=0000 CC=0001 -rolw A=12345678 B=00000016 R=12349e15 CCIN=0000 CC=0001 -rolb A=12345678 B=00000016 R=1234561e CCIN=0000 CC=0000 -roll A=12345678 B=00000017 R=3c091a2b CCIN=0000 CC=0001 -rolw A=12345678 B=00000017 R=12343c2b CCIN=0000 CC=0001 -rolb A=12345678 B=00000017 R=1234563c CCIN=0000 CC=0000 -roll A=12345678 B=00000018 R=78123456 CCIN=0000 CC=0000 -rolw A=12345678 B=00000018 R=12347856 CCIN=0000 CC=0000 -rolb A=12345678 B=00000018 R=12345678 CCIN=0000 CC=0000 -roll A=12345678 B=00000019 R=f02468ac CCIN=0000 CC=0000 -rolw A=12345678 B=00000019 R=1234f0ac CCIN=0000 CC=0000 -rolb A=12345678 B=00000019 R=123456f0 CCIN=0000 CC=0000 -roll A=12345678 B=0000001a R=e048d159 CCIN=0000 CC=0001 -rolw A=12345678 B=0000001a R=1234e159 CCIN=0000 CC=0001 -rolb A=12345678 B=0000001a R=123456e1 CCIN=0000 CC=0001 -roll A=12345678 B=0000001b R=c091a2b3 CCIN=0000 CC=0001 -rolw A=12345678 B=0000001b R=1234c2b3 CCIN=0000 CC=0001 -rolb A=12345678 B=0000001b R=123456c3 CCIN=0000 CC=0001 -roll A=12345678 B=0000001c R=81234567 CCIN=0000 CC=0001 -rolw A=12345678 B=0000001c R=12348567 CCIN=0000 CC=0001 -rolb A=12345678 B=0000001c R=12345687 CCIN=0000 CC=0001 -roll A=12345678 B=0000001d R=02468acf CCIN=0000 CC=0001 -rolw A=12345678 B=0000001d R=12340acf CCIN=0000 CC=0001 -rolb A=12345678 B=0000001d R=1234560f CCIN=0000 CC=0001 -roll A=12345678 B=0000001e R=048d159e CCIN=0000 CC=0000 -rolw A=12345678 B=0000001e R=1234159e CCIN=0000 CC=0000 -rolb A=12345678 B=0000001e R=1234561e CCIN=0000 CC=0000 -roll A=12345678 B=0000001f R=091a2b3c CCIN=0000 CC=0000 -rolw A=12345678 B=0000001f R=12342b3c CCIN=0000 CC=0000 -rolb A=12345678 B=0000001f R=1234563c CCIN=0000 CC=0000 -roll A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rolw A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rolb A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -roll A=82345679 B=00000001 R=0468acf3 CCIN=0000 CC=0801 -rolw A=82345679 B=00000001 R=8234acf2 CCIN=0000 CC=0800 -rolb A=82345679 B=00000001 R=823456f2 CCIN=0000 CC=0800 -roll A=82345679 B=00000002 R=08d159e6 CCIN=0000 CC=0000 -rolw A=82345679 B=00000002 R=823459e5 CCIN=0000 CC=0001 -rolb A=82345679 B=00000002 R=823456e5 CCIN=0000 CC=0001 -roll A=82345679 B=00000003 R=11a2b3cc CCIN=0000 CC=0000 -rolw A=82345679 B=00000003 R=8234b3ca CCIN=0000 CC=0000 -rolb A=82345679 B=00000003 R=823456cb CCIN=0000 CC=0001 -roll A=82345679 B=00000004 R=23456798 CCIN=0000 CC=0000 -rolw A=82345679 B=00000004 R=82346795 CCIN=0000 CC=0001 -rolb A=82345679 B=00000004 R=82345697 CCIN=0000 CC=0001 -roll A=82345679 B=00000005 R=468acf30 CCIN=0000 CC=0000 -rolw A=82345679 B=00000005 R=8234cf2a CCIN=0000 CC=0000 -rolb A=82345679 B=00000005 R=8234562f CCIN=0000 CC=0001 -roll A=82345679 B=00000006 R=8d159e60 CCIN=0000 CC=0000 -rolw A=82345679 B=00000006 R=82349e55 CCIN=0000 CC=0001 -rolb A=82345679 B=00000006 R=8234565e CCIN=0000 CC=0000 -roll A=82345679 B=00000007 R=1a2b3cc1 CCIN=0000 CC=0001 -rolw A=82345679 B=00000007 R=82343cab CCIN=0000 CC=0001 -rolb A=82345679 B=00000007 R=823456bc CCIN=0000 CC=0000 -roll A=82345679 B=00000008 R=34567982 CCIN=0000 CC=0000 -rolw A=82345679 B=00000008 R=82347956 CCIN=0000 CC=0000 -rolb A=82345679 B=00000008 R=82345679 CCIN=0000 CC=0001 -roll A=82345679 B=00000009 R=68acf304 CCIN=0000 CC=0000 -rolw A=82345679 B=00000009 R=8234f2ac CCIN=0000 CC=0000 -rolb A=82345679 B=00000009 R=823456f2 CCIN=0000 CC=0000 -roll A=82345679 B=0000000a R=d159e608 CCIN=0000 CC=0000 -rolw A=82345679 B=0000000a R=8234e559 CCIN=0000 CC=0001 -rolb A=82345679 B=0000000a R=823456e5 CCIN=0000 CC=0001 -roll A=82345679 B=0000000b R=a2b3cc11 CCIN=0000 CC=0001 -rolw A=82345679 B=0000000b R=8234cab3 CCIN=0000 CC=0001 -rolb A=82345679 B=0000000b R=823456cb CCIN=0000 CC=0001 -roll A=82345679 B=0000000c R=45679823 CCIN=0000 CC=0001 -rolw A=82345679 B=0000000c R=82349567 CCIN=0000 CC=0001 -rolb A=82345679 B=0000000c R=82345697 CCIN=0000 CC=0001 -roll A=82345679 B=0000000d R=8acf3046 CCIN=0000 CC=0000 -rolw A=82345679 B=0000000d R=82342acf CCIN=0000 CC=0001 -rolb A=82345679 B=0000000d R=8234562f CCIN=0000 CC=0001 -roll A=82345679 B=0000000e R=159e608d CCIN=0000 CC=0001 -rolw A=82345679 B=0000000e R=8234559e CCIN=0000 CC=0000 -rolb A=82345679 B=0000000e R=8234565e CCIN=0000 CC=0000 -roll A=82345679 B=0000000f R=2b3cc11a CCIN=0000 CC=0000 -rolw A=82345679 B=0000000f R=8234ab3c CCIN=0000 CC=0000 -rolb A=82345679 B=0000000f R=823456bc CCIN=0000 CC=0000 -roll A=82345679 B=00000010 R=56798234 CCIN=0000 CC=0000 -rolw A=82345679 B=00000010 R=82345679 CCIN=0000 CC=0001 -rolb A=82345679 B=00000010 R=82345679 CCIN=0000 CC=0001 -roll A=82345679 B=00000011 R=acf30468 CCIN=0000 CC=0000 -rolw A=82345679 B=00000011 R=8234acf2 CCIN=0000 CC=0000 -rolb A=82345679 B=00000011 R=823456f2 CCIN=0000 CC=0000 -roll A=82345679 B=00000012 R=59e608d1 CCIN=0000 CC=0001 -rolw A=82345679 B=00000012 R=823459e5 CCIN=0000 CC=0001 -rolb A=82345679 B=00000012 R=823456e5 CCIN=0000 CC=0001 -roll A=82345679 B=00000013 R=b3cc11a2 CCIN=0000 CC=0000 -rolw A=82345679 B=00000013 R=8234b3ca CCIN=0000 CC=0000 -rolb A=82345679 B=00000013 R=823456cb CCIN=0000 CC=0001 -roll A=82345679 B=00000014 R=67982345 CCIN=0000 CC=0001 -rolw A=82345679 B=00000014 R=82346795 CCIN=0000 CC=0001 -rolb A=82345679 B=00000014 R=82345697 CCIN=0000 CC=0001 -roll A=82345679 B=00000015 R=cf30468a CCIN=0000 CC=0000 -rolw A=82345679 B=00000015 R=8234cf2a CCIN=0000 CC=0000 -rolb A=82345679 B=00000015 R=8234562f CCIN=0000 CC=0001 -roll A=82345679 B=00000016 R=9e608d15 CCIN=0000 CC=0001 -rolw A=82345679 B=00000016 R=82349e55 CCIN=0000 CC=0001 -rolb A=82345679 B=00000016 R=8234565e CCIN=0000 CC=0000 -roll A=82345679 B=00000017 R=3cc11a2b CCIN=0000 CC=0001 -rolw A=82345679 B=00000017 R=82343cab CCIN=0000 CC=0001 -rolb A=82345679 B=00000017 R=823456bc CCIN=0000 CC=0000 -roll A=82345679 B=00000018 R=79823456 CCIN=0000 CC=0000 -rolw A=82345679 B=00000018 R=82347956 CCIN=0000 CC=0000 -rolb A=82345679 B=00000018 R=82345679 CCIN=0000 CC=0001 -roll A=82345679 B=00000019 R=f30468ac CCIN=0000 CC=0000 -rolw A=82345679 B=00000019 R=8234f2ac CCIN=0000 CC=0000 -rolb A=82345679 B=00000019 R=823456f2 CCIN=0000 CC=0000 -roll A=82345679 B=0000001a R=e608d159 CCIN=0000 CC=0001 -rolw A=82345679 B=0000001a R=8234e559 CCIN=0000 CC=0001 -rolb A=82345679 B=0000001a R=823456e5 CCIN=0000 CC=0001 -roll A=82345679 B=0000001b R=cc11a2b3 CCIN=0000 CC=0001 -rolw A=82345679 B=0000001b R=8234cab3 CCIN=0000 CC=0001 -rolb A=82345679 B=0000001b R=823456cb CCIN=0000 CC=0001 -roll A=82345679 B=0000001c R=98234567 CCIN=0000 CC=0001 -rolw A=82345679 B=0000001c R=82349567 CCIN=0000 CC=0001 -rolb A=82345679 B=0000001c R=82345697 CCIN=0000 CC=0001 -roll A=82345679 B=0000001d R=30468acf CCIN=0000 CC=0001 -rolw A=82345679 B=0000001d R=82342acf CCIN=0000 CC=0001 -rolb A=82345679 B=0000001d R=8234562f CCIN=0000 CC=0001 -roll A=82345679 B=0000001e R=608d159e CCIN=0000 CC=0000 -rolw A=82345679 B=0000001e R=8234559e CCIN=0000 CC=0000 -rolb A=82345679 B=0000001e R=8234565e CCIN=0000 CC=0000 -roll A=82345679 B=0000001f R=c11a2b3c CCIN=0000 CC=0000 -rolw A=82345679 B=0000001f R=8234ab3c CCIN=0000 CC=0000 -rolb A=82345679 B=0000001f R=823456bc CCIN=0000 CC=0000 -rorl A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rorw A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rorb A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rorl A=12345678 B=00000001 R=091a2b3c CCIN=0000 CC=0000 -rorw A=12345678 B=00000001 R=12342b3c CCIN=0000 CC=0000 -rorb A=12345678 B=00000001 R=1234563c CCIN=0000 CC=0000 -rorl A=12345678 B=00000002 R=048d159e CCIN=0000 CC=0000 -rorw A=12345678 B=00000002 R=1234159e CCIN=0000 CC=0000 -rorb A=12345678 B=00000002 R=1234561e CCIN=0000 CC=0000 -rorl A=12345678 B=00000003 R=02468acf CCIN=0000 CC=0000 -rorw A=12345678 B=00000003 R=12340acf CCIN=0000 CC=0000 -rorb A=12345678 B=00000003 R=1234560f CCIN=0000 CC=0000 -rorl A=12345678 B=00000004 R=81234567 CCIN=0000 CC=0001 -rorw A=12345678 B=00000004 R=12348567 CCIN=0000 CC=0001 -rorb A=12345678 B=00000004 R=12345687 CCIN=0000 CC=0001 -rorl A=12345678 B=00000005 R=c091a2b3 CCIN=0000 CC=0001 -rorw A=12345678 B=00000005 R=1234c2b3 CCIN=0000 CC=0001 -rorb A=12345678 B=00000005 R=123456c3 CCIN=0000 CC=0001 -rorl A=12345678 B=00000006 R=e048d159 CCIN=0000 CC=0001 -rorw A=12345678 B=00000006 R=1234e159 CCIN=0000 CC=0001 -rorb A=12345678 B=00000006 R=123456e1 CCIN=0000 CC=0001 -rorl A=12345678 B=00000007 R=f02468ac CCIN=0000 CC=0001 -rorw A=12345678 B=00000007 R=1234f0ac CCIN=0000 CC=0001 -rorb A=12345678 B=00000007 R=123456f0 CCIN=0000 CC=0001 -rorl A=12345678 B=00000008 R=78123456 CCIN=0000 CC=0000 -rorw A=12345678 B=00000008 R=12347856 CCIN=0000 CC=0000 -rorb A=12345678 B=00000008 R=12345678 CCIN=0000 CC=0000 -rorl A=12345678 B=00000009 R=3c091a2b CCIN=0000 CC=0000 -rorw A=12345678 B=00000009 R=12343c2b CCIN=0000 CC=0000 -rorb A=12345678 B=00000009 R=1234563c CCIN=0000 CC=0000 -rorl A=12345678 B=0000000a R=9e048d15 CCIN=0000 CC=0001 -rorw A=12345678 B=0000000a R=12349e15 CCIN=0000 CC=0001 -rorb A=12345678 B=0000000a R=1234561e CCIN=0000 CC=0000 -rorl A=12345678 B=0000000b R=cf02468a CCIN=0000 CC=0001 -rorw A=12345678 B=0000000b R=1234cf0a CCIN=0000 CC=0001 -rorb A=12345678 B=0000000b R=1234560f CCIN=0000 CC=0000 -rorl A=12345678 B=0000000c R=67812345 CCIN=0000 CC=0000 -rorw A=12345678 B=0000000c R=12346785 CCIN=0000 CC=0000 -rorb A=12345678 B=0000000c R=12345687 CCIN=0000 CC=0001 -rorl A=12345678 B=0000000d R=b3c091a2 CCIN=0000 CC=0001 -rorw A=12345678 B=0000000d R=1234b3c2 CCIN=0000 CC=0001 -rorb A=12345678 B=0000000d R=123456c3 CCIN=0000 CC=0001 -rorl A=12345678 B=0000000e R=59e048d1 CCIN=0000 CC=0000 -rorw A=12345678 B=0000000e R=123459e1 CCIN=0000 CC=0000 -rorb A=12345678 B=0000000e R=123456e1 CCIN=0000 CC=0001 -rorl A=12345678 B=0000000f R=acf02468 CCIN=0000 CC=0001 -rorw A=12345678 B=0000000f R=1234acf0 CCIN=0000 CC=0001 -rorb A=12345678 B=0000000f R=123456f0 CCIN=0000 CC=0001 -rorl A=12345678 B=00000010 R=56781234 CCIN=0000 CC=0000 -rorw A=12345678 B=00000010 R=12345678 CCIN=0000 CC=0000 -rorb A=12345678 B=00000010 R=12345678 CCIN=0000 CC=0000 -rorl A=12345678 B=00000011 R=2b3c091a CCIN=0000 CC=0000 -rorw A=12345678 B=00000011 R=12342b3c CCIN=0000 CC=0000 -rorb A=12345678 B=00000011 R=1234563c CCIN=0000 CC=0000 -rorl A=12345678 B=00000012 R=159e048d CCIN=0000 CC=0000 -rorw A=12345678 B=00000012 R=1234159e CCIN=0000 CC=0000 -rorb A=12345678 B=00000012 R=1234561e CCIN=0000 CC=0000 -rorl A=12345678 B=00000013 R=8acf0246 CCIN=0000 CC=0001 -rorw A=12345678 B=00000013 R=12340acf CCIN=0000 CC=0000 -rorb A=12345678 B=00000013 R=1234560f CCIN=0000 CC=0000 -rorl A=12345678 B=00000014 R=45678123 CCIN=0000 CC=0000 -rorw A=12345678 B=00000014 R=12348567 CCIN=0000 CC=0001 -rorb A=12345678 B=00000014 R=12345687 CCIN=0000 CC=0001 -rorl A=12345678 B=00000015 R=a2b3c091 CCIN=0000 CC=0001 -rorw A=12345678 B=00000015 R=1234c2b3 CCIN=0000 CC=0001 -rorb A=12345678 B=00000015 R=123456c3 CCIN=0000 CC=0001 -rorl A=12345678 B=00000016 R=d159e048 CCIN=0000 CC=0001 -rorw A=12345678 B=00000016 R=1234e159 CCIN=0000 CC=0001 -rorb A=12345678 B=00000016 R=123456e1 CCIN=0000 CC=0001 -rorl A=12345678 B=00000017 R=68acf024 CCIN=0000 CC=0000 -rorw A=12345678 B=00000017 R=1234f0ac CCIN=0000 CC=0001 -rorb A=12345678 B=00000017 R=123456f0 CCIN=0000 CC=0001 -rorl A=12345678 B=00000018 R=34567812 CCIN=0000 CC=0000 -rorw A=12345678 B=00000018 R=12347856 CCIN=0000 CC=0000 -rorb A=12345678 B=00000018 R=12345678 CCIN=0000 CC=0000 -rorl A=12345678 B=00000019 R=1a2b3c09 CCIN=0000 CC=0000 -rorw A=12345678 B=00000019 R=12343c2b CCIN=0000 CC=0000 -rorb A=12345678 B=00000019 R=1234563c CCIN=0000 CC=0000 -rorl A=12345678 B=0000001a R=8d159e04 CCIN=0000 CC=0001 -rorw A=12345678 B=0000001a R=12349e15 CCIN=0000 CC=0001 -rorb A=12345678 B=0000001a R=1234561e CCIN=0000 CC=0000 -rorl A=12345678 B=0000001b R=468acf02 CCIN=0000 CC=0000 -rorw A=12345678 B=0000001b R=1234cf0a CCIN=0000 CC=0001 -rorb A=12345678 B=0000001b R=1234560f CCIN=0000 CC=0000 -rorl A=12345678 B=0000001c R=23456781 CCIN=0000 CC=0000 -rorw A=12345678 B=0000001c R=12346785 CCIN=0000 CC=0000 -rorb A=12345678 B=0000001c R=12345687 CCIN=0000 CC=0001 -rorl A=12345678 B=0000001d R=91a2b3c0 CCIN=0000 CC=0001 -rorw A=12345678 B=0000001d R=1234b3c2 CCIN=0000 CC=0001 -rorb A=12345678 B=0000001d R=123456c3 CCIN=0000 CC=0001 -rorl A=12345678 B=0000001e R=48d159e0 CCIN=0000 CC=0000 -rorw A=12345678 B=0000001e R=123459e1 CCIN=0000 CC=0000 -rorb A=12345678 B=0000001e R=123456e1 CCIN=0000 CC=0001 -rorl A=12345678 B=0000001f R=2468acf0 CCIN=0000 CC=0000 -rorw A=12345678 B=0000001f R=1234acf0 CCIN=0000 CC=0001 -rorb A=12345678 B=0000001f R=123456f0 CCIN=0000 CC=0001 -rorl A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rorw A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rorb A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rorl A=82345679 B=00000001 R=c11a2b3c CCIN=0000 CC=0001 -rorw A=82345679 B=00000001 R=8234ab3c CCIN=0000 CC=0801 -rorb A=82345679 B=00000001 R=823456bc CCIN=0000 CC=0801 -rorl A=82345679 B=00000002 R=608d159e CCIN=0000 CC=0000 -rorw A=82345679 B=00000002 R=8234559e CCIN=0000 CC=0000 -rorb A=82345679 B=00000002 R=8234565e CCIN=0000 CC=0000 -rorl A=82345679 B=00000003 R=30468acf CCIN=0000 CC=0000 -rorw A=82345679 B=00000003 R=82342acf CCIN=0000 CC=0000 -rorb A=82345679 B=00000003 R=8234562f CCIN=0000 CC=0000 -rorl A=82345679 B=00000004 R=98234567 CCIN=0000 CC=0001 -rorw A=82345679 B=00000004 R=82349567 CCIN=0000 CC=0001 -rorb A=82345679 B=00000004 R=82345697 CCIN=0000 CC=0001 -rorl A=82345679 B=00000005 R=cc11a2b3 CCIN=0000 CC=0001 -rorw A=82345679 B=00000005 R=8234cab3 CCIN=0000 CC=0001 -rorb A=82345679 B=00000005 R=823456cb CCIN=0000 CC=0001 -rorl A=82345679 B=00000006 R=e608d159 CCIN=0000 CC=0001 -rorw A=82345679 B=00000006 R=8234e559 CCIN=0000 CC=0001 -rorb A=82345679 B=00000006 R=823456e5 CCIN=0000 CC=0001 -rorl A=82345679 B=00000007 R=f30468ac CCIN=0000 CC=0001 -rorw A=82345679 B=00000007 R=8234f2ac CCIN=0000 CC=0001 -rorb A=82345679 B=00000007 R=823456f2 CCIN=0000 CC=0001 -rorl A=82345679 B=00000008 R=79823456 CCIN=0000 CC=0000 -rorw A=82345679 B=00000008 R=82347956 CCIN=0000 CC=0000 -rorb A=82345679 B=00000008 R=82345679 CCIN=0000 CC=0000 -rorl A=82345679 B=00000009 R=3cc11a2b CCIN=0000 CC=0000 -rorw A=82345679 B=00000009 R=82343cab CCIN=0000 CC=0000 -rorb A=82345679 B=00000009 R=823456bc CCIN=0000 CC=0001 -rorl A=82345679 B=0000000a R=9e608d15 CCIN=0000 CC=0001 -rorw A=82345679 B=0000000a R=82349e55 CCIN=0000 CC=0001 -rorb A=82345679 B=0000000a R=8234565e CCIN=0000 CC=0000 -rorl A=82345679 B=0000000b R=cf30468a CCIN=0000 CC=0001 -rorw A=82345679 B=0000000b R=8234cf2a CCIN=0000 CC=0001 -rorb A=82345679 B=0000000b R=8234562f CCIN=0000 CC=0000 -rorl A=82345679 B=0000000c R=67982345 CCIN=0000 CC=0000 -rorw A=82345679 B=0000000c R=82346795 CCIN=0000 CC=0000 -rorb A=82345679 B=0000000c R=82345697 CCIN=0000 CC=0001 -rorl A=82345679 B=0000000d R=b3cc11a2 CCIN=0000 CC=0001 -rorw A=82345679 B=0000000d R=8234b3ca CCIN=0000 CC=0001 -rorb A=82345679 B=0000000d R=823456cb CCIN=0000 CC=0001 -rorl A=82345679 B=0000000e R=59e608d1 CCIN=0000 CC=0000 -rorw A=82345679 B=0000000e R=823459e5 CCIN=0000 CC=0000 -rorb A=82345679 B=0000000e R=823456e5 CCIN=0000 CC=0001 -rorl A=82345679 B=0000000f R=acf30468 CCIN=0000 CC=0001 -rorw A=82345679 B=0000000f R=8234acf2 CCIN=0000 CC=0001 -rorb A=82345679 B=0000000f R=823456f2 CCIN=0000 CC=0001 -rorl A=82345679 B=00000010 R=56798234 CCIN=0000 CC=0000 -rorw A=82345679 B=00000010 R=82345679 CCIN=0000 CC=0000 -rorb A=82345679 B=00000010 R=82345679 CCIN=0000 CC=0000 -rorl A=82345679 B=00000011 R=2b3cc11a CCIN=0000 CC=0000 -rorw A=82345679 B=00000011 R=8234ab3c CCIN=0000 CC=0001 -rorb A=82345679 B=00000011 R=823456bc CCIN=0000 CC=0001 -rorl A=82345679 B=00000012 R=159e608d CCIN=0000 CC=0000 -rorw A=82345679 B=00000012 R=8234559e CCIN=0000 CC=0000 -rorb A=82345679 B=00000012 R=8234565e CCIN=0000 CC=0000 -rorl A=82345679 B=00000013 R=8acf3046 CCIN=0000 CC=0001 -rorw A=82345679 B=00000013 R=82342acf CCIN=0000 CC=0000 -rorb A=82345679 B=00000013 R=8234562f CCIN=0000 CC=0000 -rorl A=82345679 B=00000014 R=45679823 CCIN=0000 CC=0000 -rorw A=82345679 B=00000014 R=82349567 CCIN=0000 CC=0001 -rorb A=82345679 B=00000014 R=82345697 CCIN=0000 CC=0001 -rorl A=82345679 B=00000015 R=a2b3cc11 CCIN=0000 CC=0001 -rorw A=82345679 B=00000015 R=8234cab3 CCIN=0000 CC=0001 -rorb A=82345679 B=00000015 R=823456cb CCIN=0000 CC=0001 -rorl A=82345679 B=00000016 R=d159e608 CCIN=0000 CC=0001 -rorw A=82345679 B=00000016 R=8234e559 CCIN=0000 CC=0001 -rorb A=82345679 B=00000016 R=823456e5 CCIN=0000 CC=0001 -rorl A=82345679 B=00000017 R=68acf304 CCIN=0000 CC=0000 -rorw A=82345679 B=00000017 R=8234f2ac CCIN=0000 CC=0001 -rorb A=82345679 B=00000017 R=823456f2 CCIN=0000 CC=0001 -rorl A=82345679 B=00000018 R=34567982 CCIN=0000 CC=0000 -rorw A=82345679 B=00000018 R=82347956 CCIN=0000 CC=0000 -rorb A=82345679 B=00000018 R=82345679 CCIN=0000 CC=0000 -rorl A=82345679 B=00000019 R=1a2b3cc1 CCIN=0000 CC=0000 -rorw A=82345679 B=00000019 R=82343cab CCIN=0000 CC=0000 -rorb A=82345679 B=00000019 R=823456bc CCIN=0000 CC=0001 -rorl A=82345679 B=0000001a R=8d159e60 CCIN=0000 CC=0001 -rorw A=82345679 B=0000001a R=82349e55 CCIN=0000 CC=0001 -rorb A=82345679 B=0000001a R=8234565e CCIN=0000 CC=0000 -rorl A=82345679 B=0000001b R=468acf30 CCIN=0000 CC=0000 -rorw A=82345679 B=0000001b R=8234cf2a CCIN=0000 CC=0001 -rorb A=82345679 B=0000001b R=8234562f CCIN=0000 CC=0000 -rorl A=82345679 B=0000001c R=23456798 CCIN=0000 CC=0000 -rorw A=82345679 B=0000001c R=82346795 CCIN=0000 CC=0000 -rorb A=82345679 B=0000001c R=82345697 CCIN=0000 CC=0001 -rorl A=82345679 B=0000001d R=11a2b3cc CCIN=0000 CC=0000 -rorw A=82345679 B=0000001d R=8234b3ca CCIN=0000 CC=0001 -rorb A=82345679 B=0000001d R=823456cb CCIN=0000 CC=0001 -rorl A=82345679 B=0000001e R=08d159e6 CCIN=0000 CC=0000 -rorw A=82345679 B=0000001e R=823459e5 CCIN=0000 CC=0000 -rorb A=82345679 B=0000001e R=823456e5 CCIN=0000 CC=0001 -rorl A=82345679 B=0000001f R=0468acf3 CCIN=0000 CC=0000 -rorw A=82345679 B=0000001f R=8234acf2 CCIN=0000 CC=0001 -rorb A=82345679 B=0000001f R=823456f2 CCIN=0000 CC=0001 -rcrl A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rcrw A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rcrb A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rcrl A=12345678 B=00000000 R=12345678 CCIN=0001 CC=0001 -rcrw A=12345678 B=00000000 R=12345678 CCIN=0001 CC=0001 -rcrb A=12345678 B=00000000 R=12345678 CCIN=0001 CC=0001 -rcrl A=12345678 B=00000001 R=091a2b3c CCIN=0000 CC=0000 -rcrw A=12345678 B=00000001 R=12342b3c CCIN=0000 CC=0000 -rcrb A=12345678 B=00000001 R=1234563c CCIN=0000 CC=0000 -rcrl A=12345678 B=00000001 R=891a2b3c CCIN=0001 CC=0800 -rcrw A=12345678 B=00000001 R=1234ab3c CCIN=0001 CC=0800 -rcrb A=12345678 B=00000001 R=123456bc CCIN=0001 CC=0800 -rcrl A=12345678 B=00000002 R=048d159e CCIN=0000 CC=0000 -rcrw A=12345678 B=00000002 R=1234159e CCIN=0000 CC=0000 -rcrb A=12345678 B=00000002 R=1234561e CCIN=0000 CC=0000 -rcrl A=12345678 B=00000002 R=448d159e CCIN=0001 CC=0000 -rcrw A=12345678 B=00000002 R=1234559e CCIN=0001 CC=0000 -rcrb A=12345678 B=00000002 R=1234565e CCIN=0001 CC=0000 -rcrl A=12345678 B=00000003 R=02468acf CCIN=0000 CC=0000 -rcrw A=12345678 B=00000003 R=12340acf CCIN=0000 CC=0000 -rcrb A=12345678 B=00000003 R=1234560f CCIN=0000 CC=0000 -rcrl A=12345678 B=00000003 R=22468acf CCIN=0001 CC=0000 -rcrw A=12345678 B=00000003 R=12342acf CCIN=0001 CC=0000 -rcrb A=12345678 B=00000003 R=1234562f CCIN=0001 CC=0000 -rcrl A=12345678 B=00000004 R=01234567 CCIN=0000 CC=0001 -rcrw A=12345678 B=00000004 R=12340567 CCIN=0000 CC=0001 -rcrb A=12345678 B=00000004 R=12345607 CCIN=0000 CC=0001 -rcrl A=12345678 B=00000004 R=11234567 CCIN=0001 CC=0001 -rcrw A=12345678 B=00000004 R=12341567 CCIN=0001 CC=0001 -rcrb A=12345678 B=00000004 R=12345617 CCIN=0001 CC=0001 -rcrl A=12345678 B=00000005 R=8091a2b3 CCIN=0000 CC=0001 -rcrw A=12345678 B=00000005 R=123482b3 CCIN=0000 CC=0001 -rcrb A=12345678 B=00000005 R=12345683 CCIN=0000 CC=0001 -rcrl A=12345678 B=00000005 R=8891a2b3 CCIN=0001 CC=0001 -rcrw A=12345678 B=00000005 R=12348ab3 CCIN=0001 CC=0001 -rcrb A=12345678 B=00000005 R=1234568b CCIN=0001 CC=0001 -rcrl A=12345678 B=00000006 R=c048d159 CCIN=0000 CC=0001 -rcrw A=12345678 B=00000006 R=1234c159 CCIN=0000 CC=0001 -rcrb A=12345678 B=00000006 R=123456c1 CCIN=0000 CC=0001 -rcrl A=12345678 B=00000006 R=c448d159 CCIN=0001 CC=0001 -rcrw A=12345678 B=00000006 R=1234c559 CCIN=0001 CC=0001 -rcrb A=12345678 B=00000006 R=123456c5 CCIN=0001 CC=0001 -rcrl A=12345678 B=00000007 R=e02468ac CCIN=0000 CC=0001 -rcrw A=12345678 B=00000007 R=1234e0ac CCIN=0000 CC=0001 -rcrb A=12345678 B=00000007 R=123456e0 CCIN=0000 CC=0001 -rcrl A=12345678 B=00000007 R=e22468ac CCIN=0001 CC=0001 -rcrw A=12345678 B=00000007 R=1234e2ac CCIN=0001 CC=0001 -rcrb A=12345678 B=00000007 R=123456e2 CCIN=0001 CC=0001 -rcrl A=12345678 B=00000008 R=f0123456 CCIN=0000 CC=0000 -rcrw A=12345678 B=00000008 R=1234f056 CCIN=0000 CC=0000 -rcrb A=12345678 B=00000008 R=123456f0 CCIN=0000 CC=0000 -rcrl A=12345678 B=00000008 R=f1123456 CCIN=0001 CC=0000 -rcrw A=12345678 B=00000008 R=1234f156 CCIN=0001 CC=0000 -rcrb A=12345678 B=00000008 R=123456f1 CCIN=0001 CC=0000 -rcrl A=12345678 B=00000009 R=78091a2b CCIN=0000 CC=0000 -rcrw A=12345678 B=00000009 R=1234782b CCIN=0000 CC=0000 -rcrb A=12345678 B=00000009 R=12345678 CCIN=0000 CC=0000 -rcrl A=12345678 B=00000009 R=78891a2b CCIN=0001 CC=0000 -rcrw A=12345678 B=00000009 R=123478ab CCIN=0001 CC=0000 -rcrb A=12345678 B=00000009 R=12345678 CCIN=0001 CC=0001 -rcrl A=12345678 B=0000000a R=3c048d15 CCIN=0000 CC=0001 -rcrw A=12345678 B=0000000a R=12343c15 CCIN=0000 CC=0001 -rcrb A=12345678 B=0000000a R=1234563c CCIN=0000 CC=0000 -rcrl A=12345678 B=0000000a R=3c448d15 CCIN=0001 CC=0001 -rcrw A=12345678 B=0000000a R=12343c55 CCIN=0001 CC=0001 -rcrb A=12345678 B=0000000a R=123456bc CCIN=0001 CC=0000 -rcrl A=12345678 B=0000000b R=9e02468a CCIN=0000 CC=0001 -rcrw A=12345678 B=0000000b R=12349e0a CCIN=0000 CC=0001 -rcrb A=12345678 B=0000000b R=1234561e CCIN=0000 CC=0000 -rcrl A=12345678 B=0000000b R=9e22468a CCIN=0001 CC=0001 -rcrw A=12345678 B=0000000b R=12349e2a CCIN=0001 CC=0001 -rcrb A=12345678 B=0000000b R=1234565e CCIN=0001 CC=0000 -rcrl A=12345678 B=0000000c R=cf012345 CCIN=0000 CC=0000 -rcrw A=12345678 B=0000000c R=1234cf05 CCIN=0000 CC=0000 -rcrb A=12345678 B=0000000c R=1234560f CCIN=0000 CC=0000 -rcrl A=12345678 B=0000000c R=cf112345 CCIN=0001 CC=0000 -rcrw A=12345678 B=0000000c R=1234cf15 CCIN=0001 CC=0000 -rcrb A=12345678 B=0000000c R=1234562f CCIN=0001 CC=0000 -rcrl A=12345678 B=0000000d R=678091a2 CCIN=0000 CC=0001 -rcrw A=12345678 B=0000000d R=12346782 CCIN=0000 CC=0001 -rcrb A=12345678 B=0000000d R=12345607 CCIN=0000 CC=0001 -rcrl A=12345678 B=0000000d R=678891a2 CCIN=0001 CC=0001 -rcrw A=12345678 B=0000000d R=1234678a CCIN=0001 CC=0001 -rcrb A=12345678 B=0000000d R=12345617 CCIN=0001 CC=0001 -rcrl A=12345678 B=0000000e R=b3c048d1 CCIN=0000 CC=0000 -rcrw A=12345678 B=0000000e R=1234b3c1 CCIN=0000 CC=0000 -rcrb A=12345678 B=0000000e R=12345683 CCIN=0000 CC=0001 -rcrl A=12345678 B=0000000e R=b3c448d1 CCIN=0001 CC=0000 -rcrw A=12345678 B=0000000e R=1234b3c5 CCIN=0001 CC=0000 -rcrb A=12345678 B=0000000e R=1234568b CCIN=0001 CC=0001 -rcrl A=12345678 B=0000000f R=59e02468 CCIN=0000 CC=0001 -rcrw A=12345678 B=0000000f R=123459e0 CCIN=0000 CC=0001 -rcrb A=12345678 B=0000000f R=123456c1 CCIN=0000 CC=0001 -rcrl A=12345678 B=0000000f R=59e22468 CCIN=0001 CC=0001 -rcrw A=12345678 B=0000000f R=123459e2 CCIN=0001 CC=0001 -rcrb A=12345678 B=0000000f R=123456c5 CCIN=0001 CC=0001 -rcrl A=12345678 B=00000010 R=acf01234 CCIN=0000 CC=0000 -rcrw A=12345678 B=00000010 R=1234acf0 CCIN=0000 CC=0000 -rcrb A=12345678 B=00000010 R=123456e0 CCIN=0000 CC=0001 -rcrl A=12345678 B=00000010 R=acf11234 CCIN=0001 CC=0000 -rcrw A=12345678 B=00000010 R=1234acf1 CCIN=0001 CC=0000 -rcrb A=12345678 B=00000010 R=123456e2 CCIN=0001 CC=0001 -rcrl A=12345678 B=00000011 R=5678091a CCIN=0000 CC=0000 -rcrw A=12345678 B=00000011 R=12345678 CCIN=0000 CC=0000 -rcrb A=12345678 B=00000011 R=123456f0 CCIN=0000 CC=0000 -rcrl A=12345678 B=00000011 R=5678891a CCIN=0001 CC=0000 -rcrw A=12345678 B=00000011 R=12345678 CCIN=0001 CC=0001 -rcrb A=12345678 B=00000011 R=123456f1 CCIN=0001 CC=0000 -rcrl A=12345678 B=00000012 R=2b3c048d CCIN=0000 CC=0000 -rcrw A=12345678 B=00000012 R=12342b3c CCIN=0000 CC=0000 -rcrb A=12345678 B=00000012 R=12345678 CCIN=0000 CC=0000 -rcrl A=12345678 B=00000012 R=2b3c448d CCIN=0001 CC=0000 -rcrw A=12345678 B=00000012 R=1234ab3c CCIN=0001 CC=0000 -rcrb A=12345678 B=00000012 R=12345678 CCIN=0001 CC=0001 -rcrl A=12345678 B=00000013 R=159e0246 CCIN=0000 CC=0001 -rcrw A=12345678 B=00000013 R=1234159e CCIN=0000 CC=0000 -rcrb A=12345678 B=00000013 R=1234563c CCIN=0000 CC=0000 -rcrl A=12345678 B=00000013 R=159e2246 CCIN=0001 CC=0001 -rcrw A=12345678 B=00000013 R=1234559e CCIN=0001 CC=0000 -rcrb A=12345678 B=00000013 R=123456bc CCIN=0001 CC=0000 -rcrl A=12345678 B=00000014 R=8acf0123 CCIN=0000 CC=0000 -rcrw A=12345678 B=00000014 R=12340acf CCIN=0000 CC=0000 -rcrb A=12345678 B=00000014 R=1234561e CCIN=0000 CC=0000 -rcrl A=12345678 B=00000014 R=8acf1123 CCIN=0001 CC=0000 -rcrw A=12345678 B=00000014 R=12342acf CCIN=0001 CC=0000 -rcrb A=12345678 B=00000014 R=1234565e CCIN=0001 CC=0000 -rcrl A=12345678 B=00000015 R=45678091 CCIN=0000 CC=0001 -rcrw A=12345678 B=00000015 R=12340567 CCIN=0000 CC=0001 -rcrb A=12345678 B=00000015 R=1234560f CCIN=0000 CC=0000 -rcrl A=12345678 B=00000015 R=45678891 CCIN=0001 CC=0001 -rcrw A=12345678 B=00000015 R=12341567 CCIN=0001 CC=0001 -rcrb A=12345678 B=00000015 R=1234562f CCIN=0001 CC=0000 -rcrl A=12345678 B=00000016 R=a2b3c048 CCIN=0000 CC=0001 -rcrw A=12345678 B=00000016 R=123482b3 CCIN=0000 CC=0001 -rcrb A=12345678 B=00000016 R=12345607 CCIN=0000 CC=0001 -rcrl A=12345678 B=00000016 R=a2b3c448 CCIN=0001 CC=0001 -rcrw A=12345678 B=00000016 R=12348ab3 CCIN=0001 CC=0001 -rcrb A=12345678 B=00000016 R=12345617 CCIN=0001 CC=0001 -rcrl A=12345678 B=00000017 R=d159e024 CCIN=0000 CC=0000 -rcrw A=12345678 B=00000017 R=1234c159 CCIN=0000 CC=0001 -rcrb A=12345678 B=00000017 R=12345683 CCIN=0000 CC=0001 -rcrl A=12345678 B=00000017 R=d159e224 CCIN=0001 CC=0000 -rcrw A=12345678 B=00000017 R=1234c559 CCIN=0001 CC=0001 -rcrb A=12345678 B=00000017 R=1234568b CCIN=0001 CC=0001 -rcrl A=12345678 B=00000018 R=68acf012 CCIN=0000 CC=0000 -rcrw A=12345678 B=00000018 R=1234e0ac CCIN=0000 CC=0001 -rcrb A=12345678 B=00000018 R=123456c1 CCIN=0000 CC=0001 -rcrl A=12345678 B=00000018 R=68acf112 CCIN=0001 CC=0000 -rcrw A=12345678 B=00000018 R=1234e2ac CCIN=0001 CC=0001 -rcrb A=12345678 B=00000018 R=123456c5 CCIN=0001 CC=0001 -rcrl A=12345678 B=00000019 R=34567809 CCIN=0000 CC=0000 -rcrw A=12345678 B=00000019 R=1234f056 CCIN=0000 CC=0000 -rcrb A=12345678 B=00000019 R=123456e0 CCIN=0000 CC=0001 -rcrl A=12345678 B=00000019 R=34567889 CCIN=0001 CC=0000 -rcrw A=12345678 B=00000019 R=1234f156 CCIN=0001 CC=0000 -rcrb A=12345678 B=00000019 R=123456e2 CCIN=0001 CC=0001 -rcrl A=12345678 B=0000001a R=1a2b3c04 CCIN=0000 CC=0001 -rcrw A=12345678 B=0000001a R=1234782b CCIN=0000 CC=0000 -rcrb A=12345678 B=0000001a R=123456f0 CCIN=0000 CC=0000 -rcrl A=12345678 B=0000001a R=1a2b3c44 CCIN=0001 CC=0001 -rcrw A=12345678 B=0000001a R=123478ab CCIN=0001 CC=0000 -rcrb A=12345678 B=0000001a R=123456f1 CCIN=0001 CC=0000 -rcrl A=12345678 B=0000001b R=8d159e02 CCIN=0000 CC=0000 -rcrw A=12345678 B=0000001b R=12343c15 CCIN=0000 CC=0001 -rcrb A=12345678 B=0000001b R=12345678 CCIN=0000 CC=0000 -rcrl A=12345678 B=0000001b R=8d159e22 CCIN=0001 CC=0000 -rcrw A=12345678 B=0000001b R=12343c55 CCIN=0001 CC=0001 -rcrb A=12345678 B=0000001b R=12345678 CCIN=0001 CC=0001 -rcrl A=12345678 B=0000001c R=468acf01 CCIN=0000 CC=0000 -rcrw A=12345678 B=0000001c R=12349e0a CCIN=0000 CC=0001 -rcrb A=12345678 B=0000001c R=1234563c CCIN=0000 CC=0000 -rcrl A=12345678 B=0000001c R=468acf11 CCIN=0001 CC=0000 -rcrw A=12345678 B=0000001c R=12349e2a CCIN=0001 CC=0001 -rcrb A=12345678 B=0000001c R=123456bc CCIN=0001 CC=0000 -rcrl A=12345678 B=0000001d R=23456780 CCIN=0000 CC=0001 -rcrw A=12345678 B=0000001d R=1234cf05 CCIN=0000 CC=0000 -rcrb A=12345678 B=0000001d R=1234561e CCIN=0000 CC=0000 -rcrl A=12345678 B=0000001d R=23456788 CCIN=0001 CC=0001 -rcrw A=12345678 B=0000001d R=1234cf15 CCIN=0001 CC=0000 -rcrb A=12345678 B=0000001d R=1234565e CCIN=0001 CC=0000 -rcrl A=12345678 B=0000001e R=91a2b3c0 CCIN=0000 CC=0000 -rcrw A=12345678 B=0000001e R=12346782 CCIN=0000 CC=0001 -rcrb A=12345678 B=0000001e R=1234560f CCIN=0000 CC=0000 -rcrl A=12345678 B=0000001e R=91a2b3c4 CCIN=0001 CC=0000 -rcrw A=12345678 B=0000001e R=1234678a CCIN=0001 CC=0001 -rcrb A=12345678 B=0000001e R=1234562f CCIN=0001 CC=0000 -rcrl A=12345678 B=0000001f R=48d159e0 CCIN=0000 CC=0000 -rcrw A=12345678 B=0000001f R=1234b3c1 CCIN=0000 CC=0000 -rcrb A=12345678 B=0000001f R=12345607 CCIN=0000 CC=0001 -rcrl A=12345678 B=0000001f R=48d159e2 CCIN=0001 CC=0000 -rcrw A=12345678 B=0000001f R=1234b3c5 CCIN=0001 CC=0000 -rcrb A=12345678 B=0000001f R=12345617 CCIN=0001 CC=0001 -rcrl A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rcrw A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rcrb A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rcrl A=82345679 B=00000000 R=82345679 CCIN=0001 CC=0001 -rcrw A=82345679 B=00000000 R=82345679 CCIN=0001 CC=0001 -rcrb A=82345679 B=00000000 R=82345679 CCIN=0001 CC=0001 -rcrl A=82345679 B=00000001 R=411a2b3c CCIN=0000 CC=0801 -rcrw A=82345679 B=00000001 R=82342b3c CCIN=0000 CC=0001 -rcrb A=82345679 B=00000001 R=8234563c CCIN=0000 CC=0001 -rcrl A=82345679 B=00000001 R=c11a2b3c CCIN=0001 CC=0001 -rcrw A=82345679 B=00000001 R=8234ab3c CCIN=0001 CC=0801 -rcrb A=82345679 B=00000001 R=823456bc CCIN=0001 CC=0801 -rcrl A=82345679 B=00000002 R=a08d159e CCIN=0000 CC=0000 -rcrw A=82345679 B=00000002 R=8234959e CCIN=0000 CC=0000 -rcrb A=82345679 B=00000002 R=8234569e CCIN=0000 CC=0000 -rcrl A=82345679 B=00000002 R=e08d159e CCIN=0001 CC=0000 -rcrw A=82345679 B=00000002 R=8234d59e CCIN=0001 CC=0000 -rcrb A=82345679 B=00000002 R=823456de CCIN=0001 CC=0000 -rcrl A=82345679 B=00000003 R=50468acf CCIN=0000 CC=0000 -rcrw A=82345679 B=00000003 R=82344acf CCIN=0000 CC=0000 -rcrb A=82345679 B=00000003 R=8234564f CCIN=0000 CC=0000 -rcrl A=82345679 B=00000003 R=70468acf CCIN=0001 CC=0000 -rcrw A=82345679 B=00000003 R=82346acf CCIN=0001 CC=0000 -rcrb A=82345679 B=00000003 R=8234566f CCIN=0001 CC=0000 -rcrl A=82345679 B=00000004 R=28234567 CCIN=0000 CC=0001 -rcrw A=82345679 B=00000004 R=82342567 CCIN=0000 CC=0001 -rcrb A=82345679 B=00000004 R=82345627 CCIN=0000 CC=0001 -rcrl A=82345679 B=00000004 R=38234567 CCIN=0001 CC=0001 -rcrw A=82345679 B=00000004 R=82343567 CCIN=0001 CC=0001 -rcrb A=82345679 B=00000004 R=82345637 CCIN=0001 CC=0001 -rcrl A=82345679 B=00000005 R=9411a2b3 CCIN=0000 CC=0001 -rcrw A=82345679 B=00000005 R=823492b3 CCIN=0000 CC=0001 -rcrb A=82345679 B=00000005 R=82345693 CCIN=0000 CC=0001 -rcrl A=82345679 B=00000005 R=9c11a2b3 CCIN=0001 CC=0001 -rcrw A=82345679 B=00000005 R=82349ab3 CCIN=0001 CC=0001 -rcrb A=82345679 B=00000005 R=8234569b CCIN=0001 CC=0001 -rcrl A=82345679 B=00000006 R=ca08d159 CCIN=0000 CC=0001 -rcrw A=82345679 B=00000006 R=8234c959 CCIN=0000 CC=0001 -rcrb A=82345679 B=00000006 R=823456c9 CCIN=0000 CC=0001 -rcrl A=82345679 B=00000006 R=ce08d159 CCIN=0001 CC=0001 -rcrw A=82345679 B=00000006 R=8234cd59 CCIN=0001 CC=0001 -rcrb A=82345679 B=00000006 R=823456cd CCIN=0001 CC=0001 -rcrl A=82345679 B=00000007 R=e50468ac CCIN=0000 CC=0001 -rcrw A=82345679 B=00000007 R=8234e4ac CCIN=0000 CC=0001 -rcrb A=82345679 B=00000007 R=823456e4 CCIN=0000 CC=0001 -rcrl A=82345679 B=00000007 R=e70468ac CCIN=0001 CC=0001 -rcrw A=82345679 B=00000007 R=8234e6ac CCIN=0001 CC=0001 -rcrb A=82345679 B=00000007 R=823456e6 CCIN=0001 CC=0001 -rcrl A=82345679 B=00000008 R=f2823456 CCIN=0000 CC=0000 -rcrw A=82345679 B=00000008 R=8234f256 CCIN=0000 CC=0000 -rcrb A=82345679 B=00000008 R=823456f2 CCIN=0000 CC=0000 -rcrl A=82345679 B=00000008 R=f3823456 CCIN=0001 CC=0000 -rcrw A=82345679 B=00000008 R=8234f356 CCIN=0001 CC=0000 -rcrb A=82345679 B=00000008 R=823456f3 CCIN=0001 CC=0000 -rcrl A=82345679 B=00000009 R=79411a2b CCIN=0000 CC=0000 -rcrw A=82345679 B=00000009 R=8234792b CCIN=0000 CC=0000 -rcrb A=82345679 B=00000009 R=82345679 CCIN=0000 CC=0000 -rcrl A=82345679 B=00000009 R=79c11a2b CCIN=0001 CC=0000 -rcrw A=82345679 B=00000009 R=823479ab CCIN=0001 CC=0000 -rcrb A=82345679 B=00000009 R=82345679 CCIN=0001 CC=0001 -rcrl A=82345679 B=0000000a R=3ca08d15 CCIN=0000 CC=0001 -rcrw A=82345679 B=0000000a R=82343c95 CCIN=0000 CC=0001 -rcrb A=82345679 B=0000000a R=8234563c CCIN=0000 CC=0001 -rcrl A=82345679 B=0000000a R=3ce08d15 CCIN=0001 CC=0001 -rcrw A=82345679 B=0000000a R=82343cd5 CCIN=0001 CC=0001 -rcrb A=82345679 B=0000000a R=823456bc CCIN=0001 CC=0001 -rcrl A=82345679 B=0000000b R=9e50468a CCIN=0000 CC=0001 -rcrw A=82345679 B=0000000b R=82349e4a CCIN=0000 CC=0001 -rcrb A=82345679 B=0000000b R=8234569e CCIN=0000 CC=0000 -rcrl A=82345679 B=0000000b R=9e70468a CCIN=0001 CC=0001 -rcrw A=82345679 B=0000000b R=82349e6a CCIN=0001 CC=0001 -rcrb A=82345679 B=0000000b R=823456de CCIN=0001 CC=0000 -rcrl A=82345679 B=0000000c R=cf282345 CCIN=0000 CC=0000 -rcrw A=82345679 B=0000000c R=8234cf25 CCIN=0000 CC=0000 -rcrb A=82345679 B=0000000c R=8234564f CCIN=0000 CC=0000 -rcrl A=82345679 B=0000000c R=cf382345 CCIN=0001 CC=0000 -rcrw A=82345679 B=0000000c R=8234cf35 CCIN=0001 CC=0000 -rcrb A=82345679 B=0000000c R=8234566f CCIN=0001 CC=0000 -rcrl A=82345679 B=0000000d R=679411a2 CCIN=0000 CC=0001 -rcrw A=82345679 B=0000000d R=82346792 CCIN=0000 CC=0001 -rcrb A=82345679 B=0000000d R=82345627 CCIN=0000 CC=0001 -rcrl A=82345679 B=0000000d R=679c11a2 CCIN=0001 CC=0001 -rcrw A=82345679 B=0000000d R=8234679a CCIN=0001 CC=0001 -rcrb A=82345679 B=0000000d R=82345637 CCIN=0001 CC=0001 -rcrl A=82345679 B=0000000e R=b3ca08d1 CCIN=0000 CC=0000 -rcrw A=82345679 B=0000000e R=8234b3c9 CCIN=0000 CC=0000 -rcrb A=82345679 B=0000000e R=82345693 CCIN=0000 CC=0001 -rcrl A=82345679 B=0000000e R=b3ce08d1 CCIN=0001 CC=0000 -rcrw A=82345679 B=0000000e R=8234b3cd CCIN=0001 CC=0000 -rcrb A=82345679 B=0000000e R=8234569b CCIN=0001 CC=0001 -rcrl A=82345679 B=0000000f R=59e50468 CCIN=0000 CC=0001 -rcrw A=82345679 B=0000000f R=823459e4 CCIN=0000 CC=0001 -rcrb A=82345679 B=0000000f R=823456c9 CCIN=0000 CC=0001 -rcrl A=82345679 B=0000000f R=59e70468 CCIN=0001 CC=0001 -rcrw A=82345679 B=0000000f R=823459e6 CCIN=0001 CC=0001 -rcrb A=82345679 B=0000000f R=823456cd CCIN=0001 CC=0001 -rcrl A=82345679 B=00000010 R=acf28234 CCIN=0000 CC=0000 -rcrw A=82345679 B=00000010 R=8234acf2 CCIN=0000 CC=0000 -rcrb A=82345679 B=00000010 R=823456e4 CCIN=0000 CC=0001 -rcrl A=82345679 B=00000010 R=acf38234 CCIN=0001 CC=0000 -rcrw A=82345679 B=00000010 R=8234acf3 CCIN=0001 CC=0000 -rcrb A=82345679 B=00000010 R=823456e6 CCIN=0001 CC=0001 -rcrl A=82345679 B=00000011 R=5679411a CCIN=0000 CC=0000 -rcrw A=82345679 B=00000011 R=82345679 CCIN=0000 CC=0000 -rcrb A=82345679 B=00000011 R=823456f2 CCIN=0000 CC=0000 -rcrl A=82345679 B=00000011 R=5679c11a CCIN=0001 CC=0000 -rcrw A=82345679 B=00000011 R=82345679 CCIN=0001 CC=0001 -rcrb A=82345679 B=00000011 R=823456f3 CCIN=0001 CC=0000 -rcrl A=82345679 B=00000012 R=2b3ca08d CCIN=0000 CC=0000 -rcrw A=82345679 B=00000012 R=82342b3c CCIN=0000 CC=0001 -rcrb A=82345679 B=00000012 R=82345679 CCIN=0000 CC=0000 -rcrl A=82345679 B=00000012 R=2b3ce08d CCIN=0001 CC=0000 -rcrw A=82345679 B=00000012 R=8234ab3c CCIN=0001 CC=0001 -rcrb A=82345679 B=00000012 R=82345679 CCIN=0001 CC=0001 -rcrl A=82345679 B=00000013 R=159e5046 CCIN=0000 CC=0001 -rcrw A=82345679 B=00000013 R=8234959e CCIN=0000 CC=0000 -rcrb A=82345679 B=00000013 R=8234563c CCIN=0000 CC=0001 -rcrl A=82345679 B=00000013 R=159e7046 CCIN=0001 CC=0001 -rcrw A=82345679 B=00000013 R=8234d59e CCIN=0001 CC=0000 -rcrb A=82345679 B=00000013 R=823456bc CCIN=0001 CC=0001 -rcrl A=82345679 B=00000014 R=8acf2823 CCIN=0000 CC=0000 -rcrw A=82345679 B=00000014 R=82344acf CCIN=0000 CC=0000 -rcrb A=82345679 B=00000014 R=8234569e CCIN=0000 CC=0000 -rcrl A=82345679 B=00000014 R=8acf3823 CCIN=0001 CC=0000 -rcrw A=82345679 B=00000014 R=82346acf CCIN=0001 CC=0000 -rcrb A=82345679 B=00000014 R=823456de CCIN=0001 CC=0000 -rcrl A=82345679 B=00000015 R=45679411 CCIN=0000 CC=0001 -rcrw A=82345679 B=00000015 R=82342567 CCIN=0000 CC=0001 -rcrb A=82345679 B=00000015 R=8234564f CCIN=0000 CC=0000 -rcrl A=82345679 B=00000015 R=45679c11 CCIN=0001 CC=0001 -rcrw A=82345679 B=00000015 R=82343567 CCIN=0001 CC=0001 -rcrb A=82345679 B=00000015 R=8234566f CCIN=0001 CC=0000 -rcrl A=82345679 B=00000016 R=a2b3ca08 CCIN=0000 CC=0001 -rcrw A=82345679 B=00000016 R=823492b3 CCIN=0000 CC=0001 -rcrb A=82345679 B=00000016 R=82345627 CCIN=0000 CC=0001 -rcrl A=82345679 B=00000016 R=a2b3ce08 CCIN=0001 CC=0001 -rcrw A=82345679 B=00000016 R=82349ab3 CCIN=0001 CC=0001 -rcrb A=82345679 B=00000016 R=82345637 CCIN=0001 CC=0001 -rcrl A=82345679 B=00000017 R=d159e504 CCIN=0000 CC=0000 -rcrw A=82345679 B=00000017 R=8234c959 CCIN=0000 CC=0001 -rcrb A=82345679 B=00000017 R=82345693 CCIN=0000 CC=0001 -rcrl A=82345679 B=00000017 R=d159e704 CCIN=0001 CC=0000 -rcrw A=82345679 B=00000017 R=8234cd59 CCIN=0001 CC=0001 -rcrb A=82345679 B=00000017 R=8234569b CCIN=0001 CC=0001 -rcrl A=82345679 B=00000018 R=68acf282 CCIN=0000 CC=0000 -rcrw A=82345679 B=00000018 R=8234e4ac CCIN=0000 CC=0001 -rcrb A=82345679 B=00000018 R=823456c9 CCIN=0000 CC=0001 -rcrl A=82345679 B=00000018 R=68acf382 CCIN=0001 CC=0000 -rcrw A=82345679 B=00000018 R=8234e6ac CCIN=0001 CC=0001 -rcrb A=82345679 B=00000018 R=823456cd CCIN=0001 CC=0001 -rcrl A=82345679 B=00000019 R=34567941 CCIN=0000 CC=0000 -rcrw A=82345679 B=00000019 R=8234f256 CCIN=0000 CC=0000 -rcrb A=82345679 B=00000019 R=823456e4 CCIN=0000 CC=0001 -rcrl A=82345679 B=00000019 R=345679c1 CCIN=0001 CC=0000 -rcrw A=82345679 B=00000019 R=8234f356 CCIN=0001 CC=0000 -rcrb A=82345679 B=00000019 R=823456e6 CCIN=0001 CC=0001 -rcrl A=82345679 B=0000001a R=1a2b3ca0 CCIN=0000 CC=0001 -rcrw A=82345679 B=0000001a R=8234792b CCIN=0000 CC=0000 -rcrb A=82345679 B=0000001a R=823456f2 CCIN=0000 CC=0000 -rcrl A=82345679 B=0000001a R=1a2b3ce0 CCIN=0001 CC=0001 -rcrw A=82345679 B=0000001a R=823479ab CCIN=0001 CC=0000 -rcrb A=82345679 B=0000001a R=823456f3 CCIN=0001 CC=0000 -rcrl A=82345679 B=0000001b R=8d159e50 CCIN=0000 CC=0000 -rcrw A=82345679 B=0000001b R=82343c95 CCIN=0000 CC=0001 -rcrb A=82345679 B=0000001b R=82345679 CCIN=0000 CC=0000 -rcrl A=82345679 B=0000001b R=8d159e70 CCIN=0001 CC=0000 -rcrw A=82345679 B=0000001b R=82343cd5 CCIN=0001 CC=0001 -rcrb A=82345679 B=0000001b R=82345679 CCIN=0001 CC=0001 -rcrl A=82345679 B=0000001c R=468acf28 CCIN=0000 CC=0000 -rcrw A=82345679 B=0000001c R=82349e4a CCIN=0000 CC=0001 -rcrb A=82345679 B=0000001c R=8234563c CCIN=0000 CC=0001 -rcrl A=82345679 B=0000001c R=468acf38 CCIN=0001 CC=0000 -rcrw A=82345679 B=0000001c R=82349e6a CCIN=0001 CC=0001 -rcrb A=82345679 B=0000001c R=823456bc CCIN=0001 CC=0001 -rcrl A=82345679 B=0000001d R=23456794 CCIN=0000 CC=0000 -rcrw A=82345679 B=0000001d R=8234cf25 CCIN=0000 CC=0000 -rcrb A=82345679 B=0000001d R=8234569e CCIN=0000 CC=0000 -rcrl A=82345679 B=0000001d R=2345679c CCIN=0001 CC=0000 -rcrw A=82345679 B=0000001d R=8234cf35 CCIN=0001 CC=0000 -rcrb A=82345679 B=0000001d R=823456de CCIN=0001 CC=0000 -rcrl A=82345679 B=0000001e R=11a2b3ca CCIN=0000 CC=0000 -rcrw A=82345679 B=0000001e R=82346792 CCIN=0000 CC=0001 -rcrb A=82345679 B=0000001e R=8234564f CCIN=0000 CC=0000 -rcrl A=82345679 B=0000001e R=11a2b3ce CCIN=0001 CC=0000 -rcrw A=82345679 B=0000001e R=8234679a CCIN=0001 CC=0001 -rcrb A=82345679 B=0000001e R=8234566f CCIN=0001 CC=0000 -rcrl A=82345679 B=0000001f R=08d159e5 CCIN=0000 CC=0000 -rcrw A=82345679 B=0000001f R=8234b3c9 CCIN=0000 CC=0000 -rcrb A=82345679 B=0000001f R=82345627 CCIN=0000 CC=0001 -rcrl A=82345679 B=0000001f R=08d159e7 CCIN=0001 CC=0000 -rcrw A=82345679 B=0000001f R=8234b3cd CCIN=0001 CC=0000 -rcrb A=82345679 B=0000001f R=82345637 CCIN=0001 CC=0001 -rcll A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rclw A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rclb A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -rcll A=12345678 B=00000000 R=12345678 CCIN=0001 CC=0001 -rclw A=12345678 B=00000000 R=12345678 CCIN=0001 CC=0001 -rclb A=12345678 B=00000000 R=12345678 CCIN=0001 CC=0001 -rcll A=12345678 B=00000001 R=2468acf0 CCIN=0000 CC=0000 -rclw A=12345678 B=00000001 R=1234acf0 CCIN=0000 CC=0800 -rclb A=12345678 B=00000001 R=123456f0 CCIN=0000 CC=0800 -rcll A=12345678 B=00000001 R=2468acf1 CCIN=0001 CC=0000 -rclw A=12345678 B=00000001 R=1234acf1 CCIN=0001 CC=0800 -rclb A=12345678 B=00000001 R=123456f1 CCIN=0001 CC=0800 -rcll A=12345678 B=00000002 R=48d159e0 CCIN=0000 CC=0000 -rclw A=12345678 B=00000002 R=123459e0 CCIN=0000 CC=0001 -rclb A=12345678 B=00000002 R=123456e0 CCIN=0000 CC=0001 -rcll A=12345678 B=00000002 R=48d159e2 CCIN=0001 CC=0000 -rclw A=12345678 B=00000002 R=123459e2 CCIN=0001 CC=0001 -rclb A=12345678 B=00000002 R=123456e2 CCIN=0001 CC=0001 -rcll A=12345678 B=00000003 R=91a2b3c0 CCIN=0000 CC=0000 -rclw A=12345678 B=00000003 R=1234b3c1 CCIN=0000 CC=0000 -rclb A=12345678 B=00000003 R=123456c1 CCIN=0000 CC=0001 -rcll A=12345678 B=00000003 R=91a2b3c4 CCIN=0001 CC=0000 -rclw A=12345678 B=00000003 R=1234b3c5 CCIN=0001 CC=0000 -rclb A=12345678 B=00000003 R=123456c5 CCIN=0001 CC=0001 -rcll A=12345678 B=00000004 R=23456780 CCIN=0000 CC=0001 -rclw A=12345678 B=00000004 R=12346782 CCIN=0000 CC=0001 -rclb A=12345678 B=00000004 R=12345683 CCIN=0000 CC=0001 -rcll A=12345678 B=00000004 R=23456788 CCIN=0001 CC=0001 -rclw A=12345678 B=00000004 R=1234678a CCIN=0001 CC=0001 -rclb A=12345678 B=00000004 R=1234568b CCIN=0001 CC=0001 -rcll A=12345678 B=00000005 R=468acf01 CCIN=0000 CC=0000 -rclw A=12345678 B=00000005 R=1234cf05 CCIN=0000 CC=0000 -rclb A=12345678 B=00000005 R=12345607 CCIN=0000 CC=0001 -rcll A=12345678 B=00000005 R=468acf11 CCIN=0001 CC=0000 -rclw A=12345678 B=00000005 R=1234cf15 CCIN=0001 CC=0000 -rclb A=12345678 B=00000005 R=12345617 CCIN=0001 CC=0001 -rcll A=12345678 B=00000006 R=8d159e02 CCIN=0000 CC=0000 -rclw A=12345678 B=00000006 R=12349e0a CCIN=0000 CC=0001 -rclb A=12345678 B=00000006 R=1234560f CCIN=0000 CC=0000 -rcll A=12345678 B=00000006 R=8d159e22 CCIN=0001 CC=0000 -rclw A=12345678 B=00000006 R=12349e2a CCIN=0001 CC=0001 -rclb A=12345678 B=00000006 R=1234562f CCIN=0001 CC=0000 -rcll A=12345678 B=00000007 R=1a2b3c04 CCIN=0000 CC=0001 -rclw A=12345678 B=00000007 R=12343c15 CCIN=0000 CC=0001 -rclb A=12345678 B=00000007 R=1234561e CCIN=0000 CC=0000 -rcll A=12345678 B=00000007 R=1a2b3c44 CCIN=0001 CC=0001 -rclw A=12345678 B=00000007 R=12343c55 CCIN=0001 CC=0001 -rclb A=12345678 B=00000007 R=1234565e CCIN=0001 CC=0000 -rcll A=12345678 B=00000008 R=34567809 CCIN=0000 CC=0000 -rclw A=12345678 B=00000008 R=1234782b CCIN=0000 CC=0000 -rclb A=12345678 B=00000008 R=1234563c CCIN=0000 CC=0000 -rcll A=12345678 B=00000008 R=34567889 CCIN=0001 CC=0000 -rclw A=12345678 B=00000008 R=123478ab CCIN=0001 CC=0000 -rclb A=12345678 B=00000008 R=123456bc CCIN=0001 CC=0000 -rcll A=12345678 B=00000009 R=68acf012 CCIN=0000 CC=0000 -rclw A=12345678 B=00000009 R=1234f056 CCIN=0000 CC=0000 -rclb A=12345678 B=00000009 R=12345678 CCIN=0000 CC=0000 -rcll A=12345678 B=00000009 R=68acf112 CCIN=0001 CC=0000 -rclw A=12345678 B=00000009 R=1234f156 CCIN=0001 CC=0000 -rclb A=12345678 B=00000009 R=12345678 CCIN=0001 CC=0001 -rcll A=12345678 B=0000000a R=d159e024 CCIN=0000 CC=0000 -rclw A=12345678 B=0000000a R=1234e0ac CCIN=0000 CC=0001 -rclb A=12345678 B=0000000a R=123456f0 CCIN=0000 CC=0000 -rcll A=12345678 B=0000000a R=d159e224 CCIN=0001 CC=0000 -rclw A=12345678 B=0000000a R=1234e2ac CCIN=0001 CC=0001 -rclb A=12345678 B=0000000a R=123456f1 CCIN=0001 CC=0000 -rcll A=12345678 B=0000000b R=a2b3c048 CCIN=0000 CC=0001 -rclw A=12345678 B=0000000b R=1234c159 CCIN=0000 CC=0001 -rclb A=12345678 B=0000000b R=123456e0 CCIN=0000 CC=0001 -rcll A=12345678 B=0000000b R=a2b3c448 CCIN=0001 CC=0001 -rclw A=12345678 B=0000000b R=1234c559 CCIN=0001 CC=0001 -rclb A=12345678 B=0000000b R=123456e2 CCIN=0001 CC=0001 -rcll A=12345678 B=0000000c R=45678091 CCIN=0000 CC=0001 -rclw A=12345678 B=0000000c R=123482b3 CCIN=0000 CC=0001 -rclb A=12345678 B=0000000c R=123456c1 CCIN=0000 CC=0001 -rcll A=12345678 B=0000000c R=45678891 CCIN=0001 CC=0001 -rclw A=12345678 B=0000000c R=12348ab3 CCIN=0001 CC=0001 -rclb A=12345678 B=0000000c R=123456c5 CCIN=0001 CC=0001 -rcll A=12345678 B=0000000d R=8acf0123 CCIN=0000 CC=0000 -rclw A=12345678 B=0000000d R=12340567 CCIN=0000 CC=0001 -rclb A=12345678 B=0000000d R=12345683 CCIN=0000 CC=0001 -rcll A=12345678 B=0000000d R=8acf1123 CCIN=0001 CC=0000 -rclw A=12345678 B=0000000d R=12341567 CCIN=0001 CC=0001 -rclb A=12345678 B=0000000d R=1234568b CCIN=0001 CC=0001 -rcll A=12345678 B=0000000e R=159e0246 CCIN=0000 CC=0001 -rclw A=12345678 B=0000000e R=12340acf CCIN=0000 CC=0000 -rclb A=12345678 B=0000000e R=12345607 CCIN=0000 CC=0001 -rcll A=12345678 B=0000000e R=159e2246 CCIN=0001 CC=0001 -rclw A=12345678 B=0000000e R=12342acf CCIN=0001 CC=0000 -rclb A=12345678 B=0000000e R=12345617 CCIN=0001 CC=0001 -rcll A=12345678 B=0000000f R=2b3c048d CCIN=0000 CC=0000 -rclw A=12345678 B=0000000f R=1234159e CCIN=0000 CC=0000 -rclb A=12345678 B=0000000f R=1234560f CCIN=0000 CC=0000 -rcll A=12345678 B=0000000f R=2b3c448d CCIN=0001 CC=0000 -rclw A=12345678 B=0000000f R=1234559e CCIN=0001 CC=0000 -rclb A=12345678 B=0000000f R=1234562f CCIN=0001 CC=0000 -rcll A=12345678 B=00000010 R=5678091a CCIN=0000 CC=0000 -rclw A=12345678 B=00000010 R=12342b3c CCIN=0000 CC=0000 -rclb A=12345678 B=00000010 R=1234561e CCIN=0000 CC=0000 -rcll A=12345678 B=00000010 R=5678891a CCIN=0001 CC=0000 -rclw A=12345678 B=00000010 R=1234ab3c CCIN=0001 CC=0000 -rclb A=12345678 B=00000010 R=1234565e CCIN=0001 CC=0000 -rcll A=12345678 B=00000011 R=acf01234 CCIN=0000 CC=0000 -rclw A=12345678 B=00000011 R=12345678 CCIN=0000 CC=0000 -rclb A=12345678 B=00000011 R=1234563c CCIN=0000 CC=0000 -rcll A=12345678 B=00000011 R=acf11234 CCIN=0001 CC=0000 -rclw A=12345678 B=00000011 R=12345678 CCIN=0001 CC=0001 -rclb A=12345678 B=00000011 R=123456bc CCIN=0001 CC=0000 -rcll A=12345678 B=00000012 R=59e02468 CCIN=0000 CC=0001 -rclw A=12345678 B=00000012 R=1234acf0 CCIN=0000 CC=0000 -rclb A=12345678 B=00000012 R=12345678 CCIN=0000 CC=0000 -rcll A=12345678 B=00000012 R=59e22468 CCIN=0001 CC=0001 -rclw A=12345678 B=00000012 R=1234acf1 CCIN=0001 CC=0000 -rclb A=12345678 B=00000012 R=12345678 CCIN=0001 CC=0001 -rcll A=12345678 B=00000013 R=b3c048d1 CCIN=0000 CC=0000 -rclw A=12345678 B=00000013 R=123459e0 CCIN=0000 CC=0001 -rclb A=12345678 B=00000013 R=123456f0 CCIN=0000 CC=0000 -rcll A=12345678 B=00000013 R=b3c448d1 CCIN=0001 CC=0000 -rclw A=12345678 B=00000013 R=123459e2 CCIN=0001 CC=0001 -rclb A=12345678 B=00000013 R=123456f1 CCIN=0001 CC=0000 -rcll A=12345678 B=00000014 R=678091a2 CCIN=0000 CC=0001 -rclw A=12345678 B=00000014 R=1234b3c1 CCIN=0000 CC=0000 -rclb A=12345678 B=00000014 R=123456e0 CCIN=0000 CC=0001 -rcll A=12345678 B=00000014 R=678891a2 CCIN=0001 CC=0001 -rclw A=12345678 B=00000014 R=1234b3c5 CCIN=0001 CC=0000 -rclb A=12345678 B=00000014 R=123456e2 CCIN=0001 CC=0001 -rcll A=12345678 B=00000015 R=cf012345 CCIN=0000 CC=0000 -rclw A=12345678 B=00000015 R=12346782 CCIN=0000 CC=0001 -rclb A=12345678 B=00000015 R=123456c1 CCIN=0000 CC=0001 -rcll A=12345678 B=00000015 R=cf112345 CCIN=0001 CC=0000 -rclw A=12345678 B=00000015 R=1234678a CCIN=0001 CC=0001 -rclb A=12345678 B=00000015 R=123456c5 CCIN=0001 CC=0001 -rcll A=12345678 B=00000016 R=9e02468a CCIN=0000 CC=0001 -rclw A=12345678 B=00000016 R=1234cf05 CCIN=0000 CC=0000 -rclb A=12345678 B=00000016 R=12345683 CCIN=0000 CC=0001 -rcll A=12345678 B=00000016 R=9e22468a CCIN=0001 CC=0001 -rclw A=12345678 B=00000016 R=1234cf15 CCIN=0001 CC=0000 -rclb A=12345678 B=00000016 R=1234568b CCIN=0001 CC=0001 -rcll A=12345678 B=00000017 R=3c048d15 CCIN=0000 CC=0001 -rclw A=12345678 B=00000017 R=12349e0a CCIN=0000 CC=0001 -rclb A=12345678 B=00000017 R=12345607 CCIN=0000 CC=0001 -rcll A=12345678 B=00000017 R=3c448d15 CCIN=0001 CC=0001 -rclw A=12345678 B=00000017 R=12349e2a CCIN=0001 CC=0001 -rclb A=12345678 B=00000017 R=12345617 CCIN=0001 CC=0001 -rcll A=12345678 B=00000018 R=78091a2b CCIN=0000 CC=0000 -rclw A=12345678 B=00000018 R=12343c15 CCIN=0000 CC=0001 -rclb A=12345678 B=00000018 R=1234560f CCIN=0000 CC=0000 -rcll A=12345678 B=00000018 R=78891a2b CCIN=0001 CC=0000 -rclw A=12345678 B=00000018 R=12343c55 CCIN=0001 CC=0001 -rclb A=12345678 B=00000018 R=1234562f CCIN=0001 CC=0000 -rcll A=12345678 B=00000019 R=f0123456 CCIN=0000 CC=0000 -rclw A=12345678 B=00000019 R=1234782b CCIN=0000 CC=0000 -rclb A=12345678 B=00000019 R=1234561e CCIN=0000 CC=0000 -rcll A=12345678 B=00000019 R=f1123456 CCIN=0001 CC=0000 -rclw A=12345678 B=00000019 R=123478ab CCIN=0001 CC=0000 -rclb A=12345678 B=00000019 R=1234565e CCIN=0001 CC=0000 -rcll A=12345678 B=0000001a R=e02468ac CCIN=0000 CC=0001 -rclw A=12345678 B=0000001a R=1234f056 CCIN=0000 CC=0000 -rclb A=12345678 B=0000001a R=1234563c CCIN=0000 CC=0000 -rcll A=12345678 B=0000001a R=e22468ac CCIN=0001 CC=0001 -rclw A=12345678 B=0000001a R=1234f156 CCIN=0001 CC=0000 -rclb A=12345678 B=0000001a R=123456bc CCIN=0001 CC=0000 -rcll A=12345678 B=0000001b R=c048d159 CCIN=0000 CC=0001 -rclw A=12345678 B=0000001b R=1234e0ac CCIN=0000 CC=0001 -rclb A=12345678 B=0000001b R=12345678 CCIN=0000 CC=0000 -rcll A=12345678 B=0000001b R=c448d159 CCIN=0001 CC=0001 -rclw A=12345678 B=0000001b R=1234e2ac CCIN=0001 CC=0001 -rclb A=12345678 B=0000001b R=12345678 CCIN=0001 CC=0001 -rcll A=12345678 B=0000001c R=8091a2b3 CCIN=0000 CC=0001 -rclw A=12345678 B=0000001c R=1234c159 CCIN=0000 CC=0001 -rclb A=12345678 B=0000001c R=123456f0 CCIN=0000 CC=0000 -rcll A=12345678 B=0000001c R=8891a2b3 CCIN=0001 CC=0001 -rclw A=12345678 B=0000001c R=1234c559 CCIN=0001 CC=0001 -rclb A=12345678 B=0000001c R=123456f1 CCIN=0001 CC=0000 -rcll A=12345678 B=0000001d R=01234567 CCIN=0000 CC=0001 -rclw A=12345678 B=0000001d R=123482b3 CCIN=0000 CC=0001 -rclb A=12345678 B=0000001d R=123456e0 CCIN=0000 CC=0001 -rcll A=12345678 B=0000001d R=11234567 CCIN=0001 CC=0001 -rclw A=12345678 B=0000001d R=12348ab3 CCIN=0001 CC=0001 -rclb A=12345678 B=0000001d R=123456e2 CCIN=0001 CC=0001 -rcll A=12345678 B=0000001e R=02468acf CCIN=0000 CC=0000 -rclw A=12345678 B=0000001e R=12340567 CCIN=0000 CC=0001 -rclb A=12345678 B=0000001e R=123456c1 CCIN=0000 CC=0001 -rcll A=12345678 B=0000001e R=22468acf CCIN=0001 CC=0000 -rclw A=12345678 B=0000001e R=12341567 CCIN=0001 CC=0001 -rclb A=12345678 B=0000001e R=123456c5 CCIN=0001 CC=0001 -rcll A=12345678 B=0000001f R=048d159e CCIN=0000 CC=0000 -rclw A=12345678 B=0000001f R=12340acf CCIN=0000 CC=0000 -rclb A=12345678 B=0000001f R=12345683 CCIN=0000 CC=0001 -rcll A=12345678 B=0000001f R=448d159e CCIN=0001 CC=0000 -rclw A=12345678 B=0000001f R=12342acf CCIN=0001 CC=0000 -rclb A=12345678 B=0000001f R=1234568b CCIN=0001 CC=0001 -rcll A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rclw A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rclb A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0000 -rcll A=82345679 B=00000000 R=82345679 CCIN=0001 CC=0001 -rclw A=82345679 B=00000000 R=82345679 CCIN=0001 CC=0001 -rclb A=82345679 B=00000000 R=82345679 CCIN=0001 CC=0001 -rcll A=82345679 B=00000001 R=0468acf2 CCIN=0000 CC=0801 -rclw A=82345679 B=00000001 R=8234acf2 CCIN=0000 CC=0800 -rclb A=82345679 B=00000001 R=823456f2 CCIN=0000 CC=0800 -rcll A=82345679 B=00000001 R=0468acf3 CCIN=0001 CC=0801 -rclw A=82345679 B=00000001 R=8234acf3 CCIN=0001 CC=0800 -rclb A=82345679 B=00000001 R=823456f3 CCIN=0001 CC=0800 -rcll A=82345679 B=00000002 R=08d159e5 CCIN=0000 CC=0000 -rclw A=82345679 B=00000002 R=823459e4 CCIN=0000 CC=0001 -rclb A=82345679 B=00000002 R=823456e4 CCIN=0000 CC=0001 -rcll A=82345679 B=00000002 R=08d159e7 CCIN=0001 CC=0000 -rclw A=82345679 B=00000002 R=823459e6 CCIN=0001 CC=0001 -rclb A=82345679 B=00000002 R=823456e6 CCIN=0001 CC=0001 -rcll A=82345679 B=00000003 R=11a2b3ca CCIN=0000 CC=0000 -rclw A=82345679 B=00000003 R=8234b3c9 CCIN=0000 CC=0000 -rclb A=82345679 B=00000003 R=823456c9 CCIN=0000 CC=0001 -rcll A=82345679 B=00000003 R=11a2b3ce CCIN=0001 CC=0000 -rclw A=82345679 B=00000003 R=8234b3cd CCIN=0001 CC=0000 -rclb A=82345679 B=00000003 R=823456cd CCIN=0001 CC=0001 -rcll A=82345679 B=00000004 R=23456794 CCIN=0000 CC=0000 -rclw A=82345679 B=00000004 R=82346792 CCIN=0000 CC=0001 -rclb A=82345679 B=00000004 R=82345693 CCIN=0000 CC=0001 -rcll A=82345679 B=00000004 R=2345679c CCIN=0001 CC=0000 -rclw A=82345679 B=00000004 R=8234679a CCIN=0001 CC=0001 -rclb A=82345679 B=00000004 R=8234569b CCIN=0001 CC=0001 -rcll A=82345679 B=00000005 R=468acf28 CCIN=0000 CC=0000 -rclw A=82345679 B=00000005 R=8234cf25 CCIN=0000 CC=0000 -rclb A=82345679 B=00000005 R=82345627 CCIN=0000 CC=0001 -rcll A=82345679 B=00000005 R=468acf38 CCIN=0001 CC=0000 -rclw A=82345679 B=00000005 R=8234cf35 CCIN=0001 CC=0000 -rclb A=82345679 B=00000005 R=82345637 CCIN=0001 CC=0001 -rcll A=82345679 B=00000006 R=8d159e50 CCIN=0000 CC=0000 -rclw A=82345679 B=00000006 R=82349e4a CCIN=0000 CC=0001 -rclb A=82345679 B=00000006 R=8234564f CCIN=0000 CC=0000 -rcll A=82345679 B=00000006 R=8d159e70 CCIN=0001 CC=0000 -rclw A=82345679 B=00000006 R=82349e6a CCIN=0001 CC=0001 -rclb A=82345679 B=00000006 R=8234566f CCIN=0001 CC=0000 -rcll A=82345679 B=00000007 R=1a2b3ca0 CCIN=0000 CC=0001 -rclw A=82345679 B=00000007 R=82343c95 CCIN=0000 CC=0001 -rclb A=82345679 B=00000007 R=8234569e CCIN=0000 CC=0000 -rcll A=82345679 B=00000007 R=1a2b3ce0 CCIN=0001 CC=0001 -rclw A=82345679 B=00000007 R=82343cd5 CCIN=0001 CC=0001 -rclb A=82345679 B=00000007 R=823456de CCIN=0001 CC=0000 -rcll A=82345679 B=00000008 R=34567941 CCIN=0000 CC=0000 -rclw A=82345679 B=00000008 R=8234792b CCIN=0000 CC=0000 -rclb A=82345679 B=00000008 R=8234563c CCIN=0000 CC=0001 -rcll A=82345679 B=00000008 R=345679c1 CCIN=0001 CC=0000 -rclw A=82345679 B=00000008 R=823479ab CCIN=0001 CC=0000 -rclb A=82345679 B=00000008 R=823456bc CCIN=0001 CC=0001 -rcll A=82345679 B=00000009 R=68acf282 CCIN=0000 CC=0000 -rclw A=82345679 B=00000009 R=8234f256 CCIN=0000 CC=0000 -rclb A=82345679 B=00000009 R=82345679 CCIN=0000 CC=0000 -rcll A=82345679 B=00000009 R=68acf382 CCIN=0001 CC=0000 -rclw A=82345679 B=00000009 R=8234f356 CCIN=0001 CC=0000 -rclb A=82345679 B=00000009 R=82345679 CCIN=0001 CC=0001 -rcll A=82345679 B=0000000a R=d159e504 CCIN=0000 CC=0000 -rclw A=82345679 B=0000000a R=8234e4ac CCIN=0000 CC=0001 -rclb A=82345679 B=0000000a R=823456f2 CCIN=0000 CC=0000 -rcll A=82345679 B=0000000a R=d159e704 CCIN=0001 CC=0000 -rclw A=82345679 B=0000000a R=8234e6ac CCIN=0001 CC=0001 -rclb A=82345679 B=0000000a R=823456f3 CCIN=0001 CC=0000 -rcll A=82345679 B=0000000b R=a2b3ca08 CCIN=0000 CC=0001 -rclw A=82345679 B=0000000b R=8234c959 CCIN=0000 CC=0001 -rclb A=82345679 B=0000000b R=823456e4 CCIN=0000 CC=0001 -rcll A=82345679 B=0000000b R=a2b3ce08 CCIN=0001 CC=0001 -rclw A=82345679 B=0000000b R=8234cd59 CCIN=0001 CC=0001 -rclb A=82345679 B=0000000b R=823456e6 CCIN=0001 CC=0001 -rcll A=82345679 B=0000000c R=45679411 CCIN=0000 CC=0001 -rclw A=82345679 B=0000000c R=823492b3 CCIN=0000 CC=0001 -rclb A=82345679 B=0000000c R=823456c9 CCIN=0000 CC=0001 -rcll A=82345679 B=0000000c R=45679c11 CCIN=0001 CC=0001 -rclw A=82345679 B=0000000c R=82349ab3 CCIN=0001 CC=0001 -rclb A=82345679 B=0000000c R=823456cd CCIN=0001 CC=0001 -rcll A=82345679 B=0000000d R=8acf2823 CCIN=0000 CC=0000 -rclw A=82345679 B=0000000d R=82342567 CCIN=0000 CC=0001 -rclb A=82345679 B=0000000d R=82345693 CCIN=0000 CC=0001 -rcll A=82345679 B=0000000d R=8acf3823 CCIN=0001 CC=0000 -rclw A=82345679 B=0000000d R=82343567 CCIN=0001 CC=0001 -rclb A=82345679 B=0000000d R=8234569b CCIN=0001 CC=0001 -rcll A=82345679 B=0000000e R=159e5046 CCIN=0000 CC=0001 -rclw A=82345679 B=0000000e R=82344acf CCIN=0000 CC=0000 -rclb A=82345679 B=0000000e R=82345627 CCIN=0000 CC=0001 -rcll A=82345679 B=0000000e R=159e7046 CCIN=0001 CC=0001 -rclw A=82345679 B=0000000e R=82346acf CCIN=0001 CC=0000 -rclb A=82345679 B=0000000e R=82345637 CCIN=0001 CC=0001 -rcll A=82345679 B=0000000f R=2b3ca08d CCIN=0000 CC=0000 -rclw A=82345679 B=0000000f R=8234959e CCIN=0000 CC=0000 -rclb A=82345679 B=0000000f R=8234564f CCIN=0000 CC=0000 -rcll A=82345679 B=0000000f R=2b3ce08d CCIN=0001 CC=0000 -rclw A=82345679 B=0000000f R=8234d59e CCIN=0001 CC=0000 -rclb A=82345679 B=0000000f R=8234566f CCIN=0001 CC=0000 -rcll A=82345679 B=00000010 R=5679411a CCIN=0000 CC=0000 -rclw A=82345679 B=00000010 R=82342b3c CCIN=0000 CC=0001 -rclb A=82345679 B=00000010 R=8234569e CCIN=0000 CC=0000 -rcll A=82345679 B=00000010 R=5679c11a CCIN=0001 CC=0000 -rclw A=82345679 B=00000010 R=8234ab3c CCIN=0001 CC=0001 -rclb A=82345679 B=00000010 R=823456de CCIN=0001 CC=0000 -rcll A=82345679 B=00000011 R=acf28234 CCIN=0000 CC=0000 -rclw A=82345679 B=00000011 R=82345679 CCIN=0000 CC=0000 -rclb A=82345679 B=00000011 R=8234563c CCIN=0000 CC=0001 -rcll A=82345679 B=00000011 R=acf38234 CCIN=0001 CC=0000 -rclw A=82345679 B=00000011 R=82345679 CCIN=0001 CC=0001 -rclb A=82345679 B=00000011 R=823456bc CCIN=0001 CC=0001 -rcll A=82345679 B=00000012 R=59e50468 CCIN=0000 CC=0001 -rclw A=82345679 B=00000012 R=8234acf2 CCIN=0000 CC=0000 -rclb A=82345679 B=00000012 R=82345679 CCIN=0000 CC=0000 -rcll A=82345679 B=00000012 R=59e70468 CCIN=0001 CC=0001 -rclw A=82345679 B=00000012 R=8234acf3 CCIN=0001 CC=0000 -rclb A=82345679 B=00000012 R=82345679 CCIN=0001 CC=0001 -rcll A=82345679 B=00000013 R=b3ca08d1 CCIN=0000 CC=0000 -rclw A=82345679 B=00000013 R=823459e4 CCIN=0000 CC=0001 -rclb A=82345679 B=00000013 R=823456f2 CCIN=0000 CC=0000 -rcll A=82345679 B=00000013 R=b3ce08d1 CCIN=0001 CC=0000 -rclw A=82345679 B=00000013 R=823459e6 CCIN=0001 CC=0001 -rclb A=82345679 B=00000013 R=823456f3 CCIN=0001 CC=0000 -rcll A=82345679 B=00000014 R=679411a2 CCIN=0000 CC=0001 -rclw A=82345679 B=00000014 R=8234b3c9 CCIN=0000 CC=0000 -rclb A=82345679 B=00000014 R=823456e4 CCIN=0000 CC=0001 -rcll A=82345679 B=00000014 R=679c11a2 CCIN=0001 CC=0001 -rclw A=82345679 B=00000014 R=8234b3cd CCIN=0001 CC=0000 -rclb A=82345679 B=00000014 R=823456e6 CCIN=0001 CC=0001 -rcll A=82345679 B=00000015 R=cf282345 CCIN=0000 CC=0000 -rclw A=82345679 B=00000015 R=82346792 CCIN=0000 CC=0001 -rclb A=82345679 B=00000015 R=823456c9 CCIN=0000 CC=0001 -rcll A=82345679 B=00000015 R=cf382345 CCIN=0001 CC=0000 -rclw A=82345679 B=00000015 R=8234679a CCIN=0001 CC=0001 -rclb A=82345679 B=00000015 R=823456cd CCIN=0001 CC=0001 -rcll A=82345679 B=00000016 R=9e50468a CCIN=0000 CC=0001 -rclw A=82345679 B=00000016 R=8234cf25 CCIN=0000 CC=0000 -rclb A=82345679 B=00000016 R=82345693 CCIN=0000 CC=0001 -rcll A=82345679 B=00000016 R=9e70468a CCIN=0001 CC=0001 -rclw A=82345679 B=00000016 R=8234cf35 CCIN=0001 CC=0000 -rclb A=82345679 B=00000016 R=8234569b CCIN=0001 CC=0001 -rcll A=82345679 B=00000017 R=3ca08d15 CCIN=0000 CC=0001 -rclw A=82345679 B=00000017 R=82349e4a CCIN=0000 CC=0001 -rclb A=82345679 B=00000017 R=82345627 CCIN=0000 CC=0001 -rcll A=82345679 B=00000017 R=3ce08d15 CCIN=0001 CC=0001 -rclw A=82345679 B=00000017 R=82349e6a CCIN=0001 CC=0001 -rclb A=82345679 B=00000017 R=82345637 CCIN=0001 CC=0001 -rcll A=82345679 B=00000018 R=79411a2b CCIN=0000 CC=0000 -rclw A=82345679 B=00000018 R=82343c95 CCIN=0000 CC=0001 -rclb A=82345679 B=00000018 R=8234564f CCIN=0000 CC=0000 -rcll A=82345679 B=00000018 R=79c11a2b CCIN=0001 CC=0000 -rclw A=82345679 B=00000018 R=82343cd5 CCIN=0001 CC=0001 -rclb A=82345679 B=00000018 R=8234566f CCIN=0001 CC=0000 -rcll A=82345679 B=00000019 R=f2823456 CCIN=0000 CC=0000 -rclw A=82345679 B=00000019 R=8234792b CCIN=0000 CC=0000 -rclb A=82345679 B=00000019 R=8234569e CCIN=0000 CC=0000 -rcll A=82345679 B=00000019 R=f3823456 CCIN=0001 CC=0000 -rclw A=82345679 B=00000019 R=823479ab CCIN=0001 CC=0000 -rclb A=82345679 B=00000019 R=823456de CCIN=0001 CC=0000 -rcll A=82345679 B=0000001a R=e50468ac CCIN=0000 CC=0001 -rclw A=82345679 B=0000001a R=8234f256 CCIN=0000 CC=0000 -rclb A=82345679 B=0000001a R=8234563c CCIN=0000 CC=0001 -rcll A=82345679 B=0000001a R=e70468ac CCIN=0001 CC=0001 -rclw A=82345679 B=0000001a R=8234f356 CCIN=0001 CC=0000 -rclb A=82345679 B=0000001a R=823456bc CCIN=0001 CC=0001 -rcll A=82345679 B=0000001b R=ca08d159 CCIN=0000 CC=0001 -rclw A=82345679 B=0000001b R=8234e4ac CCIN=0000 CC=0001 -rclb A=82345679 B=0000001b R=82345679 CCIN=0000 CC=0000 -rcll A=82345679 B=0000001b R=ce08d159 CCIN=0001 CC=0001 -rclw A=82345679 B=0000001b R=8234e6ac CCIN=0001 CC=0001 -rclb A=82345679 B=0000001b R=82345679 CCIN=0001 CC=0001 -rcll A=82345679 B=0000001c R=9411a2b3 CCIN=0000 CC=0001 -rclw A=82345679 B=0000001c R=8234c959 CCIN=0000 CC=0001 -rclb A=82345679 B=0000001c R=823456f2 CCIN=0000 CC=0000 -rcll A=82345679 B=0000001c R=9c11a2b3 CCIN=0001 CC=0001 -rclw A=82345679 B=0000001c R=8234cd59 CCIN=0001 CC=0001 -rclb A=82345679 B=0000001c R=823456f3 CCIN=0001 CC=0000 -rcll A=82345679 B=0000001d R=28234567 CCIN=0000 CC=0001 -rclw A=82345679 B=0000001d R=823492b3 CCIN=0000 CC=0001 -rclb A=82345679 B=0000001d R=823456e4 CCIN=0000 CC=0001 -rcll A=82345679 B=0000001d R=38234567 CCIN=0001 CC=0001 -rclw A=82345679 B=0000001d R=82349ab3 CCIN=0001 CC=0001 -rclb A=82345679 B=0000001d R=823456e6 CCIN=0001 CC=0001 -rcll A=82345679 B=0000001e R=50468acf CCIN=0000 CC=0000 -rclw A=82345679 B=0000001e R=82342567 CCIN=0000 CC=0001 -rclb A=82345679 B=0000001e R=823456c9 CCIN=0000 CC=0001 -rcll A=82345679 B=0000001e R=70468acf CCIN=0001 CC=0000 -rclw A=82345679 B=0000001e R=82343567 CCIN=0001 CC=0001 -rclb A=82345679 B=0000001e R=823456cd CCIN=0001 CC=0001 -rcll A=82345679 B=0000001f R=a08d159e CCIN=0000 CC=0000 -rclw A=82345679 B=0000001f R=82344acf CCIN=0000 CC=0000 -rclb A=82345679 B=0000001f R=82345693 CCIN=0000 CC=0001 -rcll A=82345679 B=0000001f R=e08d159e CCIN=0001 CC=0000 -rclw A=82345679 B=0000001f R=82346acf CCIN=0001 CC=0000 -rclb A=82345679 B=0000001f R=8234569b CCIN=0001 CC=0001 -shldl A=12345678 B=21ad3d34 C=00000000 R=12345678 CCIN=0000 CC=0000 -shldw A=12345678 B=21ad3d34 C=00000000 R=12345678 CCIN=0000 CC=0000 -shldl A=12345678 B=21ad3d34 C=00000001 R=2468acf0 CCIN=0000 CC=0004 -shldw A=12345678 B=21ad3d34 C=00000001 R=1234acf0 CCIN=0000 CC=0884 -shldl A=12345678 B=21ad3d34 C=00000002 R=48d159e0 CCIN=0000 CC=0000 -shldw A=12345678 B=21ad3d34 C=00000002 R=123459e0 CCIN=0000 CC=0001 -shldl A=12345678 B=21ad3d34 C=00000003 R=91a2b3c1 CCIN=0000 CC=0080 -shldw A=12345678 B=21ad3d34 C=00000003 R=1234b3c1 CCIN=0000 CC=0080 -shldl A=12345678 B=21ad3d34 C=00000004 R=23456782 CCIN=0000 CC=0005 -shldw A=12345678 B=21ad3d34 C=00000004 R=12346783 CCIN=0000 CC=0001 -shldl A=12345678 B=21ad3d34 C=00000005 R=468acf04 CCIN=0000 CC=0000 -shldw A=12345678 B=21ad3d34 C=00000005 R=1234cf07 CCIN=0000 CC=0080 -shldl A=12345678 B=21ad3d34 C=00000006 R=8d159e08 CCIN=0000 CC=0080 -shldw A=12345678 B=21ad3d34 C=00000006 R=12349e0f CCIN=0000 CC=0085 -shldl A=12345678 B=21ad3d34 C=00000007 R=1a2b3c10 CCIN=0000 CC=0001 -shldw A=12345678 B=21ad3d34 C=00000007 R=12343c1e CCIN=0000 CC=0005 -shldl A=12345678 B=21ad3d34 C=00000008 R=34567821 CCIN=0000 CC=0004 -shldw A=12345678 B=21ad3d34 C=00000008 R=1234783d CCIN=0000 CC=0000 -shldl A=12345678 B=21ad3d34 C=00000009 R=68acf043 CCIN=0000 CC=0000 -shldw A=12345678 B=21ad3d34 C=00000009 R=1234f07a CCIN=0000 CC=0080 -shldl A=12345678 B=21ad3d34 C=0000000a R=d159e086 CCIN=0000 CC=0080 -shldw A=12345678 B=21ad3d34 C=0000000a R=1234e0f4 CCIN=0000 CC=0081 -shldl A=12345678 B=21ad3d34 C=0000000b R=a2b3c10d CCIN=0000 CC=0081 -shldw A=12345678 B=21ad3d34 C=0000000b R=1234c1e9 CCIN=0000 CC=0081 -shldl A=12345678 B=21ad3d34 C=0000000c R=4567821a CCIN=0000 CC=0001 -shldw A=12345678 B=21ad3d34 C=0000000c R=123483d3 CCIN=0000 CC=0081 -shldl A=12345678 B=21ad3d34 C=0000000d R=8acf0435 CCIN=0000 CC=0084 -shldw A=12345678 B=21ad3d34 C=0000000d R=123407a6 CCIN=0000 CC=0005 -shldl A=12345678 B=21ad3d34 C=0000000e R=159e086b CCIN=0000 CC=0001 -shldw A=12345678 B=21ad3d34 C=0000000e R=12340f4d CCIN=0000 CC=0004 -shldl A=12345678 B=21ad3d34 C=0000000f R=2b3c10d6 CCIN=0000 CC=0000 -shldw A=12345678 B=21ad3d34 C=0000000f R=12341e9a CCIN=0000 CC=0004 -shldl A=12345678 B=21ad3d34 C=00000010 R=567821ad CCIN=0000 CC=0000 -shldw A=12345678 B=21ad3d34 C=00000010 R=12343d34 CCIN=0000 CC=0000 -shldl A=12345678 B=21ad3d34 C=00000011 R=acf0435a CCIN=0000 CC=0084 -shldl A=12345678 B=21ad3d34 C=00000012 R=59e086b4 CCIN=0000 CC=0005 -shldl A=12345678 B=21ad3d34 C=00000013 R=b3c10d69 CCIN=0000 CC=0084 -shldl A=12345678 B=21ad3d34 C=00000014 R=67821ad3 CCIN=0000 CC=0001 -shldl A=12345678 B=21ad3d34 C=00000015 R=cf0435a7 CCIN=0000 CC=0080 -shldl A=12345678 B=21ad3d34 C=00000016 R=9e086b4f CCIN=0000 CC=0081 -shldl A=12345678 B=21ad3d34 C=00000017 R=3c10d69e CCIN=0000 CC=0001 -shldl A=12345678 B=21ad3d34 C=00000018 R=7821ad3d CCIN=0000 CC=0000 -shldl A=12345678 B=21ad3d34 C=00000019 R=f0435a7a CCIN=0000 CC=0080 -shldl A=12345678 B=21ad3d34 C=0000001a R=e086b4f4 CCIN=0000 CC=0081 -shldl A=12345678 B=21ad3d34 C=0000001b R=c10d69e9 CCIN=0000 CC=0081 -shldl A=12345678 B=21ad3d34 C=0000001c R=821ad3d3 CCIN=0000 CC=0081 -shldl A=12345678 B=21ad3d34 C=0000001d R=0435a7a6 CCIN=0000 CC=0005 -shldl A=12345678 B=21ad3d34 C=0000001e R=086b4f4d CCIN=0000 CC=0004 -shldl A=12345678 B=21ad3d34 C=0000001f R=10d69e9a CCIN=0000 CC=0004 -shldl A=82345679 B=813f3421 C=00000000 R=82345679 CCIN=0000 CC=0000 -shldw A=82345679 B=813f3421 C=00000000 R=82345679 CCIN=0000 CC=0000 -shldl A=82345679 B=813f3421 C=00000001 R=0468acf3 CCIN=0000 CC=0805 -shldw A=82345679 B=813f3421 C=00000001 R=8234acf2 CCIN=0000 CC=0880 -shldl A=82345679 B=813f3421 C=00000002 R=08d159e6 CCIN=0000 CC=0000 -shldw A=82345679 B=813f3421 C=00000002 R=823459e4 CCIN=0000 CC=0005 -shldl A=82345679 B=813f3421 C=00000003 R=11a2b3cc CCIN=0000 CC=0004 -shldw A=82345679 B=813f3421 C=00000003 R=8234b3c9 CCIN=0000 CC=0084 -shldl A=82345679 B=813f3421 C=00000004 R=23456798 CCIN=0000 CC=0000 -shldw A=82345679 B=813f3421 C=00000004 R=82346793 CCIN=0000 CC=0005 -shldl A=82345679 B=813f3421 C=00000005 R=468acf30 CCIN=0000 CC=0004 -shldw A=82345679 B=813f3421 C=00000005 R=8234cf26 CCIN=0000 CC=0080 -shldl A=82345679 B=813f3421 C=00000006 R=8d159e60 CCIN=0000 CC=0084 -shldw A=82345679 B=813f3421 C=00000006 R=82349e4d CCIN=0000 CC=0085 -shldl A=82345679 B=813f3421 C=00000007 R=1a2b3cc0 CCIN=0000 CC=0005 -shldw A=82345679 B=813f3421 C=00000007 R=82343c9a CCIN=0000 CC=0005 -shldl A=82345679 B=813f3421 C=00000008 R=34567981 CCIN=0000 CC=0004 -shldw A=82345679 B=813f3421 C=00000008 R=82347934 CCIN=0000 CC=0000 -shldl A=82345679 B=813f3421 C=00000009 R=68acf302 CCIN=0000 CC=0000 -shldw A=82345679 B=813f3421 C=00000009 R=8234f268 CCIN=0000 CC=0080 -shldl A=82345679 B=813f3421 C=0000000a R=d159e604 CCIN=0000 CC=0080 -shldw A=82345679 B=813f3421 C=0000000a R=8234e4d0 CCIN=0000 CC=0081 -shldl A=82345679 B=813f3421 C=0000000b R=a2b3cc09 CCIN=0000 CC=0085 -shldw A=82345679 B=813f3421 C=0000000b R=8234c9a1 CCIN=0000 CC=0081 -shldl A=82345679 B=813f3421 C=0000000c R=45679813 CCIN=0000 CC=0001 -shldw A=82345679 B=813f3421 C=0000000c R=82349342 CCIN=0000 CC=0085 -shldl A=82345679 B=813f3421 C=0000000d R=8acf3027 CCIN=0000 CC=0084 -shldw A=82345679 B=813f3421 C=0000000d R=82342684 CCIN=0000 CC=0005 -shldl A=82345679 B=813f3421 C=0000000e R=159e604f CCIN=0000 CC=0001 -shldw A=82345679 B=813f3421 C=0000000e R=82344d08 CCIN=0000 CC=0000 -shldl A=82345679 B=813f3421 C=0000000f R=2b3cc09f CCIN=0000 CC=0004 -shldw A=82345679 B=813f3421 C=0000000f R=82349a10 CCIN=0000 CC=0080 -shldl A=82345679 B=813f3421 C=00000010 R=5679813f CCIN=0000 CC=0004 -shldw A=82345679 B=813f3421 C=00000010 R=82343421 CCIN=0000 CC=0005 -shldl A=82345679 B=813f3421 C=00000011 R=acf3027e CCIN=0000 CC=0084 -shldl A=82345679 B=813f3421 C=00000012 R=59e604fc CCIN=0000 CC=0005 -shldl A=82345679 B=813f3421 C=00000013 R=b3cc09f9 CCIN=0000 CC=0084 -shldl A=82345679 B=813f3421 C=00000014 R=679813f3 CCIN=0000 CC=0005 -shldl A=82345679 B=813f3421 C=00000015 R=cf3027e6 CCIN=0000 CC=0080 -shldl A=82345679 B=813f3421 C=00000016 R=9e604fcd CCIN=0000 CC=0081 -shldl A=82345679 B=813f3421 C=00000017 R=3cc09f9a CCIN=0000 CC=0005 -shldl A=82345679 B=813f3421 C=00000018 R=79813f34 CCIN=0000 CC=0000 -shldl A=82345679 B=813f3421 C=00000019 R=f3027e68 CCIN=0000 CC=0080 -shldl A=82345679 B=813f3421 C=0000001a R=e604fcd0 CCIN=0000 CC=0081 -shldl A=82345679 B=813f3421 C=0000001b R=cc09f9a1 CCIN=0000 CC=0081 -shldl A=82345679 B=813f3421 C=0000001c R=9813f342 CCIN=0000 CC=0085 -shldl A=82345679 B=813f3421 C=0000001d R=3027e684 CCIN=0000 CC=0005 -shldl A=82345679 B=813f3421 C=0000001e R=604fcd08 CCIN=0000 CC=0000 -shldl A=82345679 B=813f3421 C=0000001f R=c09f9a10 CCIN=0000 CC=0080 -shrdl A=12345678 B=21ad3d34 C=00000000 R=12345678 CCIN=0000 CC=0000 -shrdw A=12345678 B=21ad3d34 C=00000000 R=12345678 CCIN=0000 CC=0000 -shrdl A=12345678 B=21ad3d34 C=00000001 R=091a2b3c CCIN=0000 CC=0004 -shrdw A=12345678 B=21ad3d34 C=00000001 R=12342b3c CCIN=0000 CC=0004 -shrdl A=12345678 B=21ad3d34 C=00000002 R=048d159e CCIN=0000 CC=0000 -shrdw A=12345678 B=21ad3d34 C=00000002 R=1234159e CCIN=0000 CC=0000 -shrdl A=12345678 B=21ad3d34 C=00000003 R=82468acf CCIN=0000 CC=0084 -shrdw A=12345678 B=21ad3d34 C=00000003 R=12348acf CCIN=0000 CC=0084 -shrdl A=12345678 B=21ad3d34 C=00000004 R=41234567 CCIN=0000 CC=0001 -shrdw A=12345678 B=21ad3d34 C=00000004 R=12344567 CCIN=0000 CC=0001 -shrdl A=12345678 B=21ad3d34 C=00000005 R=a091a2b3 CCIN=0000 CC=0081 -shrdw A=12345678 B=21ad3d34 C=00000005 R=1234a2b3 CCIN=0000 CC=0081 -shrdl A=12345678 B=21ad3d34 C=00000006 R=d048d159 CCIN=0000 CC=0085 -shrdw A=12345678 B=21ad3d34 C=00000006 R=1234d159 CCIN=0000 CC=0085 -shrdl A=12345678 B=21ad3d34 C=00000007 R=682468ac CCIN=0000 CC=0005 -shrdw A=12345678 B=21ad3d34 C=00000007 R=123468ac CCIN=0000 CC=0005 -shrdl A=12345678 B=21ad3d34 C=00000008 R=34123456 CCIN=0000 CC=0004 -shrdw A=12345678 B=21ad3d34 C=00000008 R=12343456 CCIN=0000 CC=0004 -shrdl A=12345678 B=21ad3d34 C=00000009 R=9a091a2b CCIN=0000 CC=0084 -shrdw A=12345678 B=21ad3d34 C=00000009 R=12349a2b CCIN=0000 CC=0084 -shrdl A=12345678 B=21ad3d34 C=0000000a R=4d048d15 CCIN=0000 CC=0001 -shrdw A=12345678 B=21ad3d34 C=0000000a R=12344d15 CCIN=0000 CC=0001 -shrdl A=12345678 B=21ad3d34 C=0000000b R=a682468a CCIN=0000 CC=0081 -shrdw A=12345678 B=21ad3d34 C=0000000b R=1234a68a CCIN=0000 CC=0081 -shrdl A=12345678 B=21ad3d34 C=0000000c R=d3412345 CCIN=0000 CC=0080 -shrdw A=12345678 B=21ad3d34 C=0000000c R=1234d345 CCIN=0000 CC=0080 -shrdl A=12345678 B=21ad3d34 C=0000000d R=e9a091a2 CCIN=0000 CC=0081 -shrdw A=12345678 B=21ad3d34 C=0000000d R=1234e9a2 CCIN=0000 CC=0081 -shrdl A=12345678 B=21ad3d34 C=0000000e R=f4d048d1 CCIN=0000 CC=0084 -shrdw A=12345678 B=21ad3d34 C=0000000e R=1234f4d1 CCIN=0000 CC=0084 -shrdl A=12345678 B=21ad3d34 C=0000000f R=7a682468 CCIN=0000 CC=0001 -shrdw A=12345678 B=21ad3d34 C=0000000f R=12347a68 CCIN=0000 CC=0001 -shrdl A=12345678 B=21ad3d34 C=00000010 R=3d341234 CCIN=0000 CC=0000 -shrdw A=12345678 B=21ad3d34 C=00000010 R=12343d34 CCIN=0000 CC=0000 -shrdl A=12345678 B=21ad3d34 C=00000011 R=9e9a091a CCIN=0000 CC=0080 -shrdl A=12345678 B=21ad3d34 C=00000012 R=4f4d048d CCIN=0000 CC=0004 -shrdl A=12345678 B=21ad3d34 C=00000013 R=a7a68246 CCIN=0000 CC=0081 -shrdl A=12345678 B=21ad3d34 C=00000014 R=d3d34123 CCIN=0000 CC=0080 -shrdl A=12345678 B=21ad3d34 C=00000015 R=69e9a091 CCIN=0000 CC=0001 -shrdl A=12345678 B=21ad3d34 C=00000016 R=b4f4d048 CCIN=0000 CC=0085 -shrdl A=12345678 B=21ad3d34 C=00000017 R=5a7a6824 CCIN=0000 CC=0004 -shrdl A=12345678 B=21ad3d34 C=00000018 R=ad3d3412 CCIN=0000 CC=0084 -shrdl A=12345678 B=21ad3d34 C=00000019 R=d69e9a09 CCIN=0000 CC=0084 -shrdl A=12345678 B=21ad3d34 C=0000001a R=6b4f4d04 CCIN=0000 CC=0001 -shrdl A=12345678 B=21ad3d34 C=0000001b R=35a7a682 CCIN=0000 CC=0004 -shrdl A=12345678 B=21ad3d34 C=0000001c R=1ad3d341 CCIN=0000 CC=0004 -shrdl A=12345678 B=21ad3d34 C=0000001d R=0d69e9a0 CCIN=0000 CC=0005 -shrdl A=12345678 B=21ad3d34 C=0000001e R=86b4f4d0 CCIN=0000 CC=0080 -shrdl A=12345678 B=21ad3d34 C=0000001f R=435a7a68 CCIN=0000 CC=0000 -shrdl A=82345679 B=813f3421 C=00000000 R=82345679 CCIN=0000 CC=0000 -shrdw A=82345679 B=813f3421 C=00000000 R=82345679 CCIN=0000 CC=0000 -shrdl A=82345679 B=813f3421 C=00000001 R=c11a2b3c CCIN=0000 CC=0085 -shrdw A=82345679 B=813f3421 C=00000001 R=8234ab3c CCIN=0000 CC=0885 -shrdl A=82345679 B=813f3421 C=00000002 R=608d159e CCIN=0000 CC=0000 -shrdw A=82345679 B=813f3421 C=00000002 R=8234559e CCIN=0000 CC=0000 -shrdl A=82345679 B=813f3421 C=00000003 R=30468acf CCIN=0000 CC=0004 -shrdw A=82345679 B=813f3421 C=00000003 R=82342acf CCIN=0000 CC=0004 -shrdl A=82345679 B=813f3421 C=00000004 R=18234567 CCIN=0000 CC=0001 -shrdw A=82345679 B=813f3421 C=00000004 R=82341567 CCIN=0000 CC=0001 -shrdl A=82345679 B=813f3421 C=00000005 R=0c11a2b3 CCIN=0000 CC=0001 -shrdw A=82345679 B=813f3421 C=00000005 R=82340ab3 CCIN=0000 CC=0001 -shrdl A=82345679 B=813f3421 C=00000006 R=8608d159 CCIN=0000 CC=0085 -shrdw A=82345679 B=813f3421 C=00000006 R=82348559 CCIN=0000 CC=0085 -shrdl A=82345679 B=813f3421 C=00000007 R=430468ac CCIN=0000 CC=0005 -shrdw A=82345679 B=813f3421 C=00000007 R=823442ac CCIN=0000 CC=0005 -shrdl A=82345679 B=813f3421 C=00000008 R=21823456 CCIN=0000 CC=0004 -shrdw A=82345679 B=813f3421 C=00000008 R=82342156 CCIN=0000 CC=0004 -shrdl A=82345679 B=813f3421 C=00000009 R=10c11a2b CCIN=0000 CC=0004 -shrdw A=82345679 B=813f3421 C=00000009 R=823410ab CCIN=0000 CC=0000 -shrdl A=82345679 B=813f3421 C=0000000a R=08608d15 CCIN=0000 CC=0001 -shrdw A=82345679 B=813f3421 C=0000000a R=82340855 CCIN=0000 CC=0005 -shrdl A=82345679 B=813f3421 C=0000000b R=8430468a CCIN=0000 CC=0081 -shrdw A=82345679 B=813f3421 C=0000000b R=8234842a CCIN=0000 CC=0081 -shrdl A=82345679 B=813f3421 C=0000000c R=42182345 CCIN=0000 CC=0000 -shrdw A=82345679 B=813f3421 C=0000000c R=82344215 CCIN=0000 CC=0000 -shrdl A=82345679 B=813f3421 C=0000000d R=a10c11a2 CCIN=0000 CC=0081 -shrdw A=82345679 B=813f3421 C=0000000d R=8234a10a CCIN=0000 CC=0085 -shrdl A=82345679 B=813f3421 C=0000000e R=d08608d1 CCIN=0000 CC=0084 -shrdw A=82345679 B=813f3421 C=0000000e R=8234d085 CCIN=0000 CC=0080 -shrdl A=82345679 B=813f3421 C=0000000f R=68430468 CCIN=0000 CC=0001 -shrdw A=82345679 B=813f3421 C=0000000f R=82346842 CCIN=0000 CC=0005 -shrdl A=82345679 B=813f3421 C=00000010 R=34218234 CCIN=0000 CC=0000 -shrdw A=82345679 B=813f3421 C=00000010 R=82343421 CCIN=0000 CC=0004 -shrdl A=82345679 B=813f3421 C=00000011 R=9a10c11a CCIN=0000 CC=0080 -shrdl A=82345679 B=813f3421 C=00000012 R=cd08608d CCIN=0000 CC=0084 -shrdl A=82345679 B=813f3421 C=00000013 R=e6843046 CCIN=0000 CC=0081 -shrdl A=82345679 B=813f3421 C=00000014 R=f3421823 CCIN=0000 CC=0080 -shrdl A=82345679 B=813f3421 C=00000015 R=f9a10c11 CCIN=0000 CC=0085 -shrdl A=82345679 B=813f3421 C=00000016 R=fcd08608 CCIN=0000 CC=0081 -shrdl A=82345679 B=813f3421 C=00000017 R=7e684304 CCIN=0000 CC=0000 -shrdl A=82345679 B=813f3421 C=00000018 R=3f342182 CCIN=0000 CC=0004 -shrdl A=82345679 B=813f3421 C=00000019 R=9f9a10c1 CCIN=0000 CC=0080 -shrdl A=82345679 B=813f3421 C=0000001a R=4fcd0860 CCIN=0000 CC=0005 -shrdl A=82345679 B=813f3421 C=0000001b R=27e68430 CCIN=0000 CC=0004 -shrdl A=82345679 B=813f3421 C=0000001c R=13f34218 CCIN=0000 CC=0004 -shrdl A=82345679 B=813f3421 C=0000001d R=09f9a10c CCIN=0000 CC=0004 -shrdl A=82345679 B=813f3421 C=0000001e R=04fcd086 CCIN=0000 CC=0000 -shrdl A=82345679 B=813f3421 C=0000001f R=027e6843 CCIN=0000 CC=0000 -btl A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000001 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000001 R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000002 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000002 R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000003 R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=00000003 R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=00000004 R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=00000004 R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=00000005 R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=00000005 R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=00000006 R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=00000006 R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=00000007 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000007 R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000008 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000008 R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000009 R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=00000009 R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=0000000a R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=0000000a R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=0000000b R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=0000000b R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=0000000c R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=0000000c R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=0000000d R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=0000000d R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=0000000e R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=0000000e R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=0000000f R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=0000000f R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000010 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000010 R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000011 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000011 R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000012 R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=00000012 R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000013 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000013 R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=00000014 R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=00000014 R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=00000015 R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=00000015 R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=00000016 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000016 R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=00000017 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000017 R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000018 R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=00000018 R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=00000019 R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=00000019 R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=0000001a R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=0000001a R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=0000001b R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=0000001b R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=0000001c R=12345678 CCIN=0000 CC=0001 -btw A=12345678 B=0000001c R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=0000001d R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=0000001d R=12345678 CCIN=0000 CC=0000 -btl A=12345678 B=0000001e R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=0000001e R=12345678 CCIN=0000 CC=0001 -btl A=12345678 B=0000001f R=12345678 CCIN=0000 CC=0000 -btw A=12345678 B=0000001f R=12345678 CCIN=0000 CC=0000 -btl A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=00000001 R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=00000001 R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=00000002 R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=00000002 R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=00000003 R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=00000003 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=00000004 R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=00000004 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=00000005 R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=00000005 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=00000006 R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=00000006 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=00000007 R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=00000007 R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=00000008 R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=00000008 R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=00000009 R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=00000009 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=0000000a R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=0000000a R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=0000000b R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=0000000b R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=0000000c R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=0000000c R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=0000000d R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=0000000d R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=0000000e R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=0000000e R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=0000000f R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=0000000f R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=00000010 R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=00000010 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=00000011 R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=00000011 R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=00000012 R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=00000012 R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=00000013 R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=00000013 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=00000014 R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=00000014 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=00000015 R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=00000015 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=00000016 R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=00000016 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=00000017 R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=00000017 R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=00000018 R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=00000018 R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=00000019 R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=00000019 R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=0000001a R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=0000001a R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=0000001b R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=0000001b R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=0000001c R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=0000001c R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=0000001d R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=0000001d R=82345679 CCIN=0000 CC=0000 -btl A=82345679 B=0000001e R=82345679 CCIN=0000 CC=0000 -btw A=82345679 B=0000001e R=82345679 CCIN=0000 CC=0001 -btl A=82345679 B=0000001f R=82345679 CCIN=0000 CC=0001 -btw A=82345679 B=0000001f R=82345679 CCIN=0000 CC=0000 -btsl A=12345678 B=00000000 R=12345679 CCIN=0000 CC=0000 -btsw A=12345678 B=00000000 R=12345679 CCIN=0000 CC=0000 -btsl A=12345678 B=00000001 R=1234567a CCIN=0000 CC=0000 -btsw A=12345678 B=00000001 R=1234567a CCIN=0000 CC=0000 -btsl A=12345678 B=00000002 R=1234567c CCIN=0000 CC=0000 -btsw A=12345678 B=00000002 R=1234567c CCIN=0000 CC=0000 -btsl A=12345678 B=00000003 R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=00000003 R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=00000004 R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=00000004 R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=00000005 R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=00000005 R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=00000006 R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=00000006 R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=00000007 R=123456f8 CCIN=0000 CC=0000 -btsw A=12345678 B=00000007 R=123456f8 CCIN=0000 CC=0000 -btsl A=12345678 B=00000008 R=12345778 CCIN=0000 CC=0000 -btsw A=12345678 B=00000008 R=12345778 CCIN=0000 CC=0000 -btsl A=12345678 B=00000009 R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=00000009 R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=0000000a R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=0000000a R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=0000000b R=12345e78 CCIN=0000 CC=0000 -btsw A=12345678 B=0000000b R=12345e78 CCIN=0000 CC=0000 -btsl A=12345678 B=0000000c R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=0000000c R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=0000000d R=12347678 CCIN=0000 CC=0000 -btsw A=12345678 B=0000000d R=12347678 CCIN=0000 CC=0000 -btsl A=12345678 B=0000000e R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=0000000e R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=0000000f R=1234d678 CCIN=0000 CC=0000 -btsw A=12345678 B=0000000f R=1234d678 CCIN=0000 CC=0000 -btsl A=12345678 B=00000010 R=12355678 CCIN=0000 CC=0000 -btsw A=12345678 B=00000010 R=12345679 CCIN=0000 CC=0000 -btsl A=12345678 B=00000011 R=12365678 CCIN=0000 CC=0000 -btsw A=12345678 B=00000011 R=1234567a CCIN=0000 CC=0000 -btsl A=12345678 B=00000012 R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=00000012 R=1234567c CCIN=0000 CC=0000 -btsl A=12345678 B=00000013 R=123c5678 CCIN=0000 CC=0000 -btsw A=12345678 B=00000013 R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=00000014 R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=00000014 R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=00000015 R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=00000015 R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=00000016 R=12745678 CCIN=0000 CC=0000 -btsw A=12345678 B=00000016 R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=00000017 R=12b45678 CCIN=0000 CC=0000 -btsw A=12345678 B=00000017 R=123456f8 CCIN=0000 CC=0000 -btsl A=12345678 B=00000018 R=13345678 CCIN=0000 CC=0000 -btsw A=12345678 B=00000018 R=12345778 CCIN=0000 CC=0000 -btsl A=12345678 B=00000019 R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=00000019 R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=0000001a R=16345678 CCIN=0000 CC=0000 -btsw A=12345678 B=0000001a R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=0000001b R=1a345678 CCIN=0000 CC=0000 -btsw A=12345678 B=0000001b R=12345e78 CCIN=0000 CC=0000 -btsl A=12345678 B=0000001c R=12345678 CCIN=0000 CC=0001 -btsw A=12345678 B=0000001c R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=0000001d R=32345678 CCIN=0000 CC=0000 -btsw A=12345678 B=0000001d R=12347678 CCIN=0000 CC=0000 -btsl A=12345678 B=0000001e R=52345678 CCIN=0000 CC=0000 -btsw A=12345678 B=0000001e R=12345678 CCIN=0000 CC=0001 -btsl A=12345678 B=0000001f R=92345678 CCIN=0000 CC=0000 -btsw A=12345678 B=0000001f R=1234d678 CCIN=0000 CC=0000 -btsl A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=00000000 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=00000001 R=8234567b CCIN=0000 CC=0000 -btsw A=82345679 B=00000001 R=8234567b CCIN=0000 CC=0000 -btsl A=82345679 B=00000002 R=8234567d CCIN=0000 CC=0000 -btsw A=82345679 B=00000002 R=8234567d CCIN=0000 CC=0000 -btsl A=82345679 B=00000003 R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=00000003 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=00000004 R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=00000004 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=00000005 R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=00000005 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=00000006 R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=00000006 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=00000007 R=823456f9 CCIN=0000 CC=0000 -btsw A=82345679 B=00000007 R=823456f9 CCIN=0000 CC=0000 -btsl A=82345679 B=00000008 R=82345779 CCIN=0000 CC=0000 -btsw A=82345679 B=00000008 R=82345779 CCIN=0000 CC=0000 -btsl A=82345679 B=00000009 R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=00000009 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=0000000a R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=0000000a R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=0000000b R=82345e79 CCIN=0000 CC=0000 -btsw A=82345679 B=0000000b R=82345e79 CCIN=0000 CC=0000 -btsl A=82345679 B=0000000c R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=0000000c R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=0000000d R=82347679 CCIN=0000 CC=0000 -btsw A=82345679 B=0000000d R=82347679 CCIN=0000 CC=0000 -btsl A=82345679 B=0000000e R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=0000000e R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=0000000f R=8234d679 CCIN=0000 CC=0000 -btsw A=82345679 B=0000000f R=8234d679 CCIN=0000 CC=0000 -btsl A=82345679 B=00000010 R=82355679 CCIN=0000 CC=0000 -btsw A=82345679 B=00000010 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=00000011 R=82365679 CCIN=0000 CC=0000 -btsw A=82345679 B=00000011 R=8234567b CCIN=0000 CC=0000 -btsl A=82345679 B=00000012 R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=00000012 R=8234567d CCIN=0000 CC=0000 -btsl A=82345679 B=00000013 R=823c5679 CCIN=0000 CC=0000 -btsw A=82345679 B=00000013 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=00000014 R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=00000014 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=00000015 R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=00000015 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=00000016 R=82745679 CCIN=0000 CC=0000 -btsw A=82345679 B=00000016 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=00000017 R=82b45679 CCIN=0000 CC=0000 -btsw A=82345679 B=00000017 R=823456f9 CCIN=0000 CC=0000 -btsl A=82345679 B=00000018 R=83345679 CCIN=0000 CC=0000 -btsw A=82345679 B=00000018 R=82345779 CCIN=0000 CC=0000 -btsl A=82345679 B=00000019 R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=00000019 R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=0000001a R=86345679 CCIN=0000 CC=0000 -btsw A=82345679 B=0000001a R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=0000001b R=8a345679 CCIN=0000 CC=0000 -btsw A=82345679 B=0000001b R=82345e79 CCIN=0000 CC=0000 -btsl A=82345679 B=0000001c R=92345679 CCIN=0000 CC=0000 -btsw A=82345679 B=0000001c R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=0000001d R=a2345679 CCIN=0000 CC=0000 -btsw A=82345679 B=0000001d R=82347679 CCIN=0000 CC=0000 -btsl A=82345679 B=0000001e R=c2345679 CCIN=0000 CC=0000 -btsw A=82345679 B=0000001e R=82345679 CCIN=0000 CC=0001 -btsl A=82345679 B=0000001f R=82345679 CCIN=0000 CC=0001 -btsw A=82345679 B=0000001f R=8234d679 CCIN=0000 CC=0000 -btrl A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000000 R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000001 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000001 R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000002 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000002 R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000003 R=12345670 CCIN=0000 CC=0001 -btrw A=12345678 B=00000003 R=12345670 CCIN=0000 CC=0001 -btrl A=12345678 B=00000004 R=12345668 CCIN=0000 CC=0001 -btrw A=12345678 B=00000004 R=12345668 CCIN=0000 CC=0001 -btrl A=12345678 B=00000005 R=12345658 CCIN=0000 CC=0001 -btrw A=12345678 B=00000005 R=12345658 CCIN=0000 CC=0001 -btrl A=12345678 B=00000006 R=12345638 CCIN=0000 CC=0001 -btrw A=12345678 B=00000006 R=12345638 CCIN=0000 CC=0001 -btrl A=12345678 B=00000007 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000007 R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000008 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000008 R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000009 R=12345478 CCIN=0000 CC=0001 -btrw A=12345678 B=00000009 R=12345478 CCIN=0000 CC=0001 -btrl A=12345678 B=0000000a R=12345278 CCIN=0000 CC=0001 -btrw A=12345678 B=0000000a R=12345278 CCIN=0000 CC=0001 -btrl A=12345678 B=0000000b R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=0000000b R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=0000000c R=12344678 CCIN=0000 CC=0001 -btrw A=12345678 B=0000000c R=12344678 CCIN=0000 CC=0001 -btrl A=12345678 B=0000000d R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=0000000d R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=0000000e R=12341678 CCIN=0000 CC=0001 -btrw A=12345678 B=0000000e R=12341678 CCIN=0000 CC=0001 -btrl A=12345678 B=0000000f R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=0000000f R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000010 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000010 R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000011 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000011 R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000012 R=12305678 CCIN=0000 CC=0001 -btrw A=12345678 B=00000012 R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000013 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000013 R=12345670 CCIN=0000 CC=0001 -btrl A=12345678 B=00000014 R=12245678 CCIN=0000 CC=0001 -btrw A=12345678 B=00000014 R=12345668 CCIN=0000 CC=0001 -btrl A=12345678 B=00000015 R=12145678 CCIN=0000 CC=0001 -btrw A=12345678 B=00000015 R=12345658 CCIN=0000 CC=0001 -btrl A=12345678 B=00000016 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000016 R=12345638 CCIN=0000 CC=0001 -btrl A=12345678 B=00000017 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000017 R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000018 R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=00000018 R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=00000019 R=10345678 CCIN=0000 CC=0001 -btrw A=12345678 B=00000019 R=12345478 CCIN=0000 CC=0001 -btrl A=12345678 B=0000001a R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=0000001a R=12345278 CCIN=0000 CC=0001 -btrl A=12345678 B=0000001b R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=0000001b R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=0000001c R=02345678 CCIN=0000 CC=0001 -btrw A=12345678 B=0000001c R=12344678 CCIN=0000 CC=0001 -btrl A=12345678 B=0000001d R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=0000001d R=12345678 CCIN=0000 CC=0000 -btrl A=12345678 B=0000001e R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=0000001e R=12341678 CCIN=0000 CC=0001 -btrl A=12345678 B=0000001f R=12345678 CCIN=0000 CC=0000 -btrw A=12345678 B=0000001f R=12345678 CCIN=0000 CC=0000 -btrl A=82345679 B=00000000 R=82345678 CCIN=0000 CC=0001 -btrw A=82345679 B=00000000 R=82345678 CCIN=0000 CC=0001 -btrl A=82345679 B=00000001 R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=00000001 R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=00000002 R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=00000002 R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=00000003 R=82345671 CCIN=0000 CC=0001 -btrw A=82345679 B=00000003 R=82345671 CCIN=0000 CC=0001 -btrl A=82345679 B=00000004 R=82345669 CCIN=0000 CC=0001 -btrw A=82345679 B=00000004 R=82345669 CCIN=0000 CC=0001 -btrl A=82345679 B=00000005 R=82345659 CCIN=0000 CC=0001 -btrw A=82345679 B=00000005 R=82345659 CCIN=0000 CC=0001 -btrl A=82345679 B=00000006 R=82345639 CCIN=0000 CC=0001 -btrw A=82345679 B=00000006 R=82345639 CCIN=0000 CC=0001 -btrl A=82345679 B=00000007 R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=00000007 R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=00000008 R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=00000008 R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=00000009 R=82345479 CCIN=0000 CC=0001 -btrw A=82345679 B=00000009 R=82345479 CCIN=0000 CC=0001 -btrl A=82345679 B=0000000a R=82345279 CCIN=0000 CC=0001 -btrw A=82345679 B=0000000a R=82345279 CCIN=0000 CC=0001 -btrl A=82345679 B=0000000b R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=0000000b R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=0000000c R=82344679 CCIN=0000 CC=0001 -btrw A=82345679 B=0000000c R=82344679 CCIN=0000 CC=0001 -btrl A=82345679 B=0000000d R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=0000000d R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=0000000e R=82341679 CCIN=0000 CC=0001 -btrw A=82345679 B=0000000e R=82341679 CCIN=0000 CC=0001 -btrl A=82345679 B=0000000f R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=0000000f R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=00000010 R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=00000010 R=82345678 CCIN=0000 CC=0001 -btrl A=82345679 B=00000011 R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=00000011 R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=00000012 R=82305679 CCIN=0000 CC=0001 -btrw A=82345679 B=00000012 R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=00000013 R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=00000013 R=82345671 CCIN=0000 CC=0001 -btrl A=82345679 B=00000014 R=82245679 CCIN=0000 CC=0001 -btrw A=82345679 B=00000014 R=82345669 CCIN=0000 CC=0001 -btrl A=82345679 B=00000015 R=82145679 CCIN=0000 CC=0001 -btrw A=82345679 B=00000015 R=82345659 CCIN=0000 CC=0001 -btrl A=82345679 B=00000016 R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=00000016 R=82345639 CCIN=0000 CC=0001 -btrl A=82345679 B=00000017 R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=00000017 R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=00000018 R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=00000018 R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=00000019 R=80345679 CCIN=0000 CC=0001 -btrw A=82345679 B=00000019 R=82345479 CCIN=0000 CC=0001 -btrl A=82345679 B=0000001a R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=0000001a R=82345279 CCIN=0000 CC=0001 -btrl A=82345679 B=0000001b R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=0000001b R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=0000001c R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=0000001c R=82344679 CCIN=0000 CC=0001 -btrl A=82345679 B=0000001d R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=0000001d R=82345679 CCIN=0000 CC=0000 -btrl A=82345679 B=0000001e R=82345679 CCIN=0000 CC=0000 -btrw A=82345679 B=0000001e R=82341679 CCIN=0000 CC=0001 -btrl A=82345679 B=0000001f R=02345679 CCIN=0000 CC=0001 -btrw A=82345679 B=0000001f R=82345679 CCIN=0000 CC=0000 -btcl A=12345678 B=00000000 R=12345679 CCIN=0000 CC=0000 -btcw A=12345678 B=00000000 R=12345679 CCIN=0000 CC=0000 -btcl A=12345678 B=00000001 R=1234567a CCIN=0000 CC=0000 -btcw A=12345678 B=00000001 R=1234567a CCIN=0000 CC=0000 -btcl A=12345678 B=00000002 R=1234567c CCIN=0000 CC=0000 -btcw A=12345678 B=00000002 R=1234567c CCIN=0000 CC=0000 -btcl A=12345678 B=00000003 R=12345670 CCIN=0000 CC=0001 -btcw A=12345678 B=00000003 R=12345670 CCIN=0000 CC=0001 -btcl A=12345678 B=00000004 R=12345668 CCIN=0000 CC=0001 -btcw A=12345678 B=00000004 R=12345668 CCIN=0000 CC=0001 -btcl A=12345678 B=00000005 R=12345658 CCIN=0000 CC=0001 -btcw A=12345678 B=00000005 R=12345658 CCIN=0000 CC=0001 -btcl A=12345678 B=00000006 R=12345638 CCIN=0000 CC=0001 -btcw A=12345678 B=00000006 R=12345638 CCIN=0000 CC=0001 -btcl A=12345678 B=00000007 R=123456f8 CCIN=0000 CC=0000 -btcw A=12345678 B=00000007 R=123456f8 CCIN=0000 CC=0000 -btcl A=12345678 B=00000008 R=12345778 CCIN=0000 CC=0000 -btcw A=12345678 B=00000008 R=12345778 CCIN=0000 CC=0000 -btcl A=12345678 B=00000009 R=12345478 CCIN=0000 CC=0001 -btcw A=12345678 B=00000009 R=12345478 CCIN=0000 CC=0001 -btcl A=12345678 B=0000000a R=12345278 CCIN=0000 CC=0001 -btcw A=12345678 B=0000000a R=12345278 CCIN=0000 CC=0001 -btcl A=12345678 B=0000000b R=12345e78 CCIN=0000 CC=0000 -btcw A=12345678 B=0000000b R=12345e78 CCIN=0000 CC=0000 -btcl A=12345678 B=0000000c R=12344678 CCIN=0000 CC=0001 -btcw A=12345678 B=0000000c R=12344678 CCIN=0000 CC=0001 -btcl A=12345678 B=0000000d R=12347678 CCIN=0000 CC=0000 -btcw A=12345678 B=0000000d R=12347678 CCIN=0000 CC=0000 -btcl A=12345678 B=0000000e R=12341678 CCIN=0000 CC=0001 -btcw A=12345678 B=0000000e R=12341678 CCIN=0000 CC=0001 -btcl A=12345678 B=0000000f R=1234d678 CCIN=0000 CC=0000 -btcw A=12345678 B=0000000f R=1234d678 CCIN=0000 CC=0000 -btcl A=12345678 B=00000010 R=12355678 CCIN=0000 CC=0000 -btcw A=12345678 B=00000010 R=12345679 CCIN=0000 CC=0000 -btcl A=12345678 B=00000011 R=12365678 CCIN=0000 CC=0000 -btcw A=12345678 B=00000011 R=1234567a CCIN=0000 CC=0000 -btcl A=12345678 B=00000012 R=12305678 CCIN=0000 CC=0001 -btcw A=12345678 B=00000012 R=1234567c CCIN=0000 CC=0000 -btcl A=12345678 B=00000013 R=123c5678 CCIN=0000 CC=0000 -btcw A=12345678 B=00000013 R=12345670 CCIN=0000 CC=0001 -btcl A=12345678 B=00000014 R=12245678 CCIN=0000 CC=0001 -btcw A=12345678 B=00000014 R=12345668 CCIN=0000 CC=0001 -btcl A=12345678 B=00000015 R=12145678 CCIN=0000 CC=0001 -btcw A=12345678 B=00000015 R=12345658 CCIN=0000 CC=0001 -btcl A=12345678 B=00000016 R=12745678 CCIN=0000 CC=0000 -btcw A=12345678 B=00000016 R=12345638 CCIN=0000 CC=0001 -btcl A=12345678 B=00000017 R=12b45678 CCIN=0000 CC=0000 -btcw A=12345678 B=00000017 R=123456f8 CCIN=0000 CC=0000 -btcl A=12345678 B=00000018 R=13345678 CCIN=0000 CC=0000 -btcw A=12345678 B=00000018 R=12345778 CCIN=0000 CC=0000 -btcl A=12345678 B=00000019 R=10345678 CCIN=0000 CC=0001 -btcw A=12345678 B=00000019 R=12345478 CCIN=0000 CC=0001 -btcl A=12345678 B=0000001a R=16345678 CCIN=0000 CC=0000 -btcw A=12345678 B=0000001a R=12345278 CCIN=0000 CC=0001 -btcl A=12345678 B=0000001b R=1a345678 CCIN=0000 CC=0000 -btcw A=12345678 B=0000001b R=12345e78 CCIN=0000 CC=0000 -btcl A=12345678 B=0000001c R=02345678 CCIN=0000 CC=0001 -btcw A=12345678 B=0000001c R=12344678 CCIN=0000 CC=0001 -btcl A=12345678 B=0000001d R=32345678 CCIN=0000 CC=0000 -btcw A=12345678 B=0000001d R=12347678 CCIN=0000 CC=0000 -btcl A=12345678 B=0000001e R=52345678 CCIN=0000 CC=0000 -btcw A=12345678 B=0000001e R=12341678 CCIN=0000 CC=0001 -btcl A=12345678 B=0000001f R=92345678 CCIN=0000 CC=0000 -btcw A=12345678 B=0000001f R=1234d678 CCIN=0000 CC=0000 -btcl A=82345679 B=00000000 R=82345678 CCIN=0000 CC=0001 -btcw A=82345679 B=00000000 R=82345678 CCIN=0000 CC=0001 -btcl A=82345679 B=00000001 R=8234567b CCIN=0000 CC=0000 -btcw A=82345679 B=00000001 R=8234567b CCIN=0000 CC=0000 -btcl A=82345679 B=00000002 R=8234567d CCIN=0000 CC=0000 -btcw A=82345679 B=00000002 R=8234567d CCIN=0000 CC=0000 -btcl A=82345679 B=00000003 R=82345671 CCIN=0000 CC=0001 -btcw A=82345679 B=00000003 R=82345671 CCIN=0000 CC=0001 -btcl A=82345679 B=00000004 R=82345669 CCIN=0000 CC=0001 -btcw A=82345679 B=00000004 R=82345669 CCIN=0000 CC=0001 -btcl A=82345679 B=00000005 R=82345659 CCIN=0000 CC=0001 -btcw A=82345679 B=00000005 R=82345659 CCIN=0000 CC=0001 -btcl A=82345679 B=00000006 R=82345639 CCIN=0000 CC=0001 -btcw A=82345679 B=00000006 R=82345639 CCIN=0000 CC=0001 -btcl A=82345679 B=00000007 R=823456f9 CCIN=0000 CC=0000 -btcw A=82345679 B=00000007 R=823456f9 CCIN=0000 CC=0000 -btcl A=82345679 B=00000008 R=82345779 CCIN=0000 CC=0000 -btcw A=82345679 B=00000008 R=82345779 CCIN=0000 CC=0000 -btcl A=82345679 B=00000009 R=82345479 CCIN=0000 CC=0001 -btcw A=82345679 B=00000009 R=82345479 CCIN=0000 CC=0001 -btcl A=82345679 B=0000000a R=82345279 CCIN=0000 CC=0001 -btcw A=82345679 B=0000000a R=82345279 CCIN=0000 CC=0001 -btcl A=82345679 B=0000000b R=82345e79 CCIN=0000 CC=0000 -btcw A=82345679 B=0000000b R=82345e79 CCIN=0000 CC=0000 -btcl A=82345679 B=0000000c R=82344679 CCIN=0000 CC=0001 -btcw A=82345679 B=0000000c R=82344679 CCIN=0000 CC=0001 -btcl A=82345679 B=0000000d R=82347679 CCIN=0000 CC=0000 -btcw A=82345679 B=0000000d R=82347679 CCIN=0000 CC=0000 -btcl A=82345679 B=0000000e R=82341679 CCIN=0000 CC=0001 -btcw A=82345679 B=0000000e R=82341679 CCIN=0000 CC=0001 -btcl A=82345679 B=0000000f R=8234d679 CCIN=0000 CC=0000 -btcw A=82345679 B=0000000f R=8234d679 CCIN=0000 CC=0000 -btcl A=82345679 B=00000010 R=82355679 CCIN=0000 CC=0000 -btcw A=82345679 B=00000010 R=82345678 CCIN=0000 CC=0001 -btcl A=82345679 B=00000011 R=82365679 CCIN=0000 CC=0000 -btcw A=82345679 B=00000011 R=8234567b CCIN=0000 CC=0000 -btcl A=82345679 B=00000012 R=82305679 CCIN=0000 CC=0001 -btcw A=82345679 B=00000012 R=8234567d CCIN=0000 CC=0000 -btcl A=82345679 B=00000013 R=823c5679 CCIN=0000 CC=0000 -btcw A=82345679 B=00000013 R=82345671 CCIN=0000 CC=0001 -btcl A=82345679 B=00000014 R=82245679 CCIN=0000 CC=0001 -btcw A=82345679 B=00000014 R=82345669 CCIN=0000 CC=0001 -btcl A=82345679 B=00000015 R=82145679 CCIN=0000 CC=0001 -btcw A=82345679 B=00000015 R=82345659 CCIN=0000 CC=0001 -btcl A=82345679 B=00000016 R=82745679 CCIN=0000 CC=0000 -btcw A=82345679 B=00000016 R=82345639 CCIN=0000 CC=0001 -btcl A=82345679 B=00000017 R=82b45679 CCIN=0000 CC=0000 -btcw A=82345679 B=00000017 R=823456f9 CCIN=0000 CC=0000 -btcl A=82345679 B=00000018 R=83345679 CCIN=0000 CC=0000 -btcw A=82345679 B=00000018 R=82345779 CCIN=0000 CC=0000 -btcl A=82345679 B=00000019 R=80345679 CCIN=0000 CC=0001 -btcw A=82345679 B=00000019 R=82345479 CCIN=0000 CC=0001 -btcl A=82345679 B=0000001a R=86345679 CCIN=0000 CC=0000 -btcw A=82345679 B=0000001a R=82345279 CCIN=0000 CC=0001 -btcl A=82345679 B=0000001b R=8a345679 CCIN=0000 CC=0000 -btcw A=82345679 B=0000001b R=82345e79 CCIN=0000 CC=0000 -btcl A=82345679 B=0000001c R=92345679 CCIN=0000 CC=0000 -btcw A=82345679 B=0000001c R=82344679 CCIN=0000 CC=0001 -btcl A=82345679 B=0000001d R=a2345679 CCIN=0000 CC=0000 -btcw A=82345679 B=0000001d R=82347679 CCIN=0000 CC=0000 -btcl A=82345679 B=0000001e R=c2345679 CCIN=0000 CC=0000 -btcw A=82345679 B=0000001e R=82341679 CCIN=0000 CC=0001 -btcl A=82345679 B=0000001f R=02345679 CCIN=0000 CC=0001 -btcw A=82345679 B=0000001f R=8234d679 CCIN=0000 CC=0000 -bsrw A=00000000 R=12345678 1 -bsrw A=12340128 R=12340008 0 -bsfw A=00000000 R=12345678 1 -bsfw A=12340128 R=12340003 0 -bsrl A=00000000 R=12345678 1 -bsrl A=00340128 R=00000015 0 -bsfl A=00000000 R=12345678 1 -bsfl A=00340128 R=00000003 0 -imulb A=1234561d B=00000004 R=12340074 CC=0000 -imulb A=00000003 B=fffffffc R=0000fff4 CC=0000 -imulb A=00000080 B=00000080 R=00004000 CC=0801 -imulb A=00000010 B=00000010 R=00000100 CC=0801 -imulw AH=00000000 AL=1234001d B=0000002d RH=00000000 RL=12340519 CC=0000 -imulw AH=00000000 AL=00000017 B=ffffffd3 RH=0000ffff RL=0000fbf5 CC=0000 -imulw AH=00000000 AL=00008000 B=00008000 RH=00004000 RL=00000000 CC=0801 -imulw AH=00000000 AL=00000100 B=00000100 RH=00000001 RL=00000000 CC=0801 -imull AH=00000000 AL=1234001d B=0000002d RH=00000003 RL=33240519 CC=0801 -imull AH=00000000 AL=00000017 B=ffffffd3 RH=ffffffff RL=fffffbf5 CC=0000 -imull AH=00000000 AL=80000000 B=80000000 RH=40000000 RL=00000000 CC=0801 -imull AH=00000000 AL=00010000 B=00010000 RH=00000001 RL=00000000 CC=0801 -mulb A=1234561d B=00000004 R=12340074 CC=0000 -mulb A=00000003 B=fffffffc R=000002f4 CC=0801 -mulb A=00000080 B=00000080 R=00004000 CC=0801 -mulb A=00000010 B=00000010 R=00000100 CC=0801 -mulw AH=00000000 AL=1234001d B=0000002d RH=00000000 RL=12340519 CC=0000 -mulw AH=00000000 AL=00000017 B=ffffffd3 RH=00000016 RL=0000fbf5 CC=0801 -mulw AH=00000000 AL=00008000 B=00008000 RH=00004000 RL=00000000 CC=0801 -mulw AH=00000000 AL=00000100 B=00000100 RH=00000001 RL=00000000 CC=0801 -mull AH=00000000 AL=1234001d B=0000002d RH=00000003 RL=33240519 CC=0801 -mull AH=00000000 AL=00000017 B=ffffffd3 RH=00000016 RL=fffffbf5 CC=0801 -mull AH=00000000 AL=80000000 B=80000000 RH=40000000 RL=00000000 CC=0801 -mull AH=00000000 AL=00010000 B=00010000 RH=00000001 RL=00000000 CC=0801 -imulw A=1234001d B=0000002d R=12340519 CC=0000 -imulw A=00000017 B=ffffffd3 R=0000fbf5 CC=0000 -imulw A=00008000 B=00008000 R=00000000 CC=0801 -imulw A=00000100 B=00000100 R=00000000 CC=0801 -imull A=1234001d B=0000002d R=33240519 CC=0801 -imull A=00000017 B=ffffffd3 R=fffffbf5 CC=0000 -imull A=80000000 B=80000000 R=00000000 CC=0801 -imull A=00010000 B=00010000 R=00000000 CC=0801 -imulw im A=0000002d B=00001234 R=00003324 CC=0000 -imulw im A=ffffffd3 B=00000017 R=0000fbf5 CC=0000 -imulw im A=00008000 B=80000000 R=00000000 CC=0000 -imulw im A=00007fff B=00001000 R=0000f000 CC=0000 -imull im A=0000002d B=00001234 R=00033324 CC=0000 -imull im A=ffffffd3 B=00000017 R=fffffbf5 CC=0000 -imull im A=00008000 B=80000000 R=00000000 CC=0000 -imull im A=00007fff B=00001000 R=07fff000 CC=0000 -idivb A=12341678 B=0000127e R=1234522d CC=0000 -idivb A=43210123 B=fffffffb R=432101c6 CC=0000 -idivb A=12340004 B=ffffffff R=123400fc CC=0000 -idivw AH=00000000 AL=12345678 B=0000303b RH=0000263d RL=12340001 CC=0000 -idivw AH=00000000 AL=ffffa549 B=ffffffd3 RH=0000000d RL=fffffc54 CC=0000 -idivw AH=00000000 AL=12348000 B=ffffffff RH=00000000 RL=12348000 CC=0000 -idivw AH=00012343 AL=12345678 B=81238567 RH=000120a6 RL=1234b65e CC=0000 -idivl AH=00000000 AL=12345678 B=0000303b RH=00001198 RL=000060a0 CC=0000 -idivl AH=00000000 AL=fffc70f9 B=ffffffd3 RH=0000002b RL=fa4fb93a CC=0000 -idivl AH=00000000 AL=80000000 B=ffffffff RH=00000000 RL=80000000 CC=0000 -idivl AH=00012343 AL=12345678 B=81234567 RH=4ba84b51 RL=fffdb441 CC=0000 -divb A=12341678 B=0000127e R=1234522d CC=0000 -divb A=43210123 B=fffffffb R=43212801 CC=0000 -divb A=12340004 B=ffffffff R=12340400 CC=0000 -divw AH=00000000 AL=12345678 B=0000303b RH=0000263d RL=12340001 CC=0000 -divw AH=00000000 AL=ffffa549 B=ffffffd3 RH=0000a549 RL=ffff0000 CC=0000 -divw AH=00000000 AL=12348000 B=ffffffff RH=00008000 RL=12340000 CC=0000 -divw AH=00012343 AL=12345678 B=81238567 RH=000145ab RL=123443ab CC=0000 -divl AH=00000000 AL=12345678 B=0000303b RH=00001198 RL=000060a0 CC=0000 -divl AH=00000000 AL=fffc70f9 B=ffffffd3 RH=fffc70f9 RL=00000000 CC=0000 -divl AH=00000000 AL=80000000 B=ffffffff RH=80000000 RL=00000000 CC=0000 -divl AH=00012343 AL=12345678 B=81234567 RH=2100133c RL=00024164 CC=0000 -jne 0 -setne 0 -jne 1 -setne 1 -je 1 -sete 1 -je 0 -sete 0 -jl 0 -setl 0 -jl 0 -setl 0 -jl 0 -setl 0 -jle 1 -setle 1 -jle 0 -setle 0 -jle 0 -setle 0 -jge 1 -setge 1 -jge 1 -setge 1 -jge 0 -setge 0 -jg 0 -setg 0 -jg 1 -setg 1 -jg 1 -setg 1 -jb 0 -setb 0 -jb 0 -setb 0 -jb 1 -setb 1 -jbe 1 -setbe 1 -jbe 0 -setbe 0 -jbe 1 -setbe 1 -jae 1 -setae 1 -jae 1 -setae 1 -jae 0 -setae 0 -ja 0 -seta 0 -ja 1 -seta 1 -ja 0 -seta 0 -jp 1 -setp 1 -jp 0 -setp 0 -jnp 0 -setnp 0 -jnp 1 -setnp 1 -jo 0 -seto 0 -jo 1 -seto 1 -jno 1 -setno 1 -jno 0 -setno 0 -js 1 -sets 1 -js 0 -sets 0 -js 0 -sets 0 -jns 0 -setns 0 -jns 1 -setns 1 -jns 1 -setns 1 -jcxz ECX=00000000 ZF=0 r=1 -jcxz ECX=00000000 ZF=1 r=1 -jcxz ECX=00000001 ZF=0 r=0 -jcxz ECX=00000001 ZF=1 r=0 -jcxz ECX=00010000 ZF=0 r=1 -jcxz ECX=00010000 ZF=1 r=1 -jcxz ECX=00010001 ZF=0 r=0 -jcxz ECX=00010001 ZF=1 r=0 -loopw ECX=00000000 ZF=0 r=1 -loopw ECX=00000000 ZF=1 r=1 -loopw ECX=00000001 ZF=0 r=0 -loopw ECX=00000001 ZF=1 r=0 -loopw ECX=00010000 ZF=0 r=1 -loopw ECX=00010000 ZF=1 r=1 -loopw ECX=00010001 ZF=0 r=0 -loopw ECX=00010001 ZF=1 r=0 -loopzw ECX=00000000 ZF=0 r=0 -loopzw ECX=00000000 ZF=1 r=1 -loopzw ECX=00000001 ZF=0 r=0 -loopzw ECX=00000001 ZF=1 r=0 -loopzw ECX=00010000 ZF=0 r=0 -loopzw ECX=00010000 ZF=1 r=1 -loopzw ECX=00010001 ZF=0 r=0 -loopzw ECX=00010001 ZF=1 r=0 -loopnzw ECX=00000000 ZF=0 r=1 -loopnzw ECX=00000000 ZF=1 r=0 -loopnzw ECX=00000001 ZF=0 r=0 -loopnzw ECX=00000001 ZF=1 r=0 -loopnzw ECX=00010000 ZF=0 r=1 -loopnzw ECX=00010000 ZF=1 r=0 -loopnzw ECX=00010001 ZF=0 r=0 -loopnzw ECX=00010001 ZF=1 r=0 -jecxz ECX=00000000 ZF=0 r=1 -jecxz ECX=00000000 ZF=1 r=1 -jecxz ECX=00000001 ZF=0 r=0 -jecxz ECX=00000001 ZF=1 r=0 -jecxz ECX=00010000 ZF=0 r=0 -jecxz ECX=00010000 ZF=1 r=0 -jecxz ECX=00010001 ZF=0 r=0 -jecxz ECX=00010001 ZF=1 r=0 -loopl ECX=00000000 ZF=0 r=1 -loopl ECX=00000000 ZF=1 r=1 -loopl ECX=00000001 ZF=0 r=0 -loopl ECX=00000001 ZF=1 r=0 -loopl ECX=00010000 ZF=0 r=1 -loopl ECX=00010000 ZF=1 r=1 -loopl ECX=00010001 ZF=0 r=1 -loopl ECX=00010001 ZF=1 r=1 -loopzl ECX=00000000 ZF=0 r=0 -loopzl ECX=00000000 ZF=1 r=1 -loopzl ECX=00000001 ZF=0 r=0 -loopzl ECX=00000001 ZF=1 r=0 -loopzl ECX=00010000 ZF=0 r=0 -loopzl ECX=00010000 ZF=1 r=1 -loopzl ECX=00010001 ZF=0 r=0 -loopzl ECX=00010001 ZF=1 r=1 -loopnzl ECX=00000000 ZF=0 r=1 -loopnzl ECX=00000000 ZF=1 r=0 -loopnzl ECX=00000001 ZF=0 r=0 -loopnzl ECX=00000001 ZF=1 r=0 -loopnzl ECX=00010000 ZF=0 r=1 -loopnzl ECX=00010000 ZF=1 r=0 -loopnzl ECX=00010001 ZF=0 r=1 -loopnzl ECX=00010001 ZF=1 r=0 -a=2.000000 b=3.000000 a+b=5.000000 -a=2.000000 b=3.000000 a-b=-1.000000 -a=2.000000 b=3.000000 a*b=6.000000 -a=2.000000 b=3.000000 a/b=0.666667 -a=2.000000 b=3.000000 fmod(a, b)=2.000000 -a=2.000000 sqrt(a)=1.414214 -a=2.000000 sin(a)=0.909297 -a=2.000000 cos(a)=-0.416147 -a=2.000000 tan(a)=-2.185040 -a=2.000000 log(a)=0.693147 -a=2.000000 exp(a)=7.389056 -a=2.000000 b=3.000000 atan2(a, b)=0.588003 -a=2.000000 asin(sin(a))=1.141593 -a=2.000000 acos(cos(a))=2.000000 -a=2.000000 atan(tan(a))=-1.141593 -a=1.400000 b=-5.000000 a+b=-3.600000 -a=1.400000 b=-5.000000 a-b=6.400000 -a=1.400000 b=-5.000000 a*b=-7.000000 -a=1.400000 b=-5.000000 a/b=-0.280000 -a=1.400000 b=-5.000000 fmod(a, b)=1.400000 -a=1.400000 sqrt(a)=1.183216 -a=1.400000 sin(a)=0.985450 -a=1.400000 cos(a)=0.169967 -a=1.400000 tan(a)=5.797884 -a=1.400000 log(a)=0.336472 -a=1.400000 exp(a)=4.055200 -a=1.400000 b=-5.000000 atan2(a, b)=2.868584 -a=1.400000 asin(sin(a))=1.400000 -a=1.400000 acos(cos(a))=1.400000 -a=1.400000 atan(tan(a))=1.400000 -fcom(2.000000 -1.000000)=0000 -fucom(2.000000 -1.000000)=0000 -fxam(2.000000)=0400 -fcom(2.000000 2.000000)=4000 -fucom(2.000000 2.000000)=4000 -fxam(2.000000)=0400 -fcom(2.000000 3.000000)=0100 -fucom(2.000000 3.000000)=0100 -fxam(2.000000)=0400 -fcom(2.000000 -nan)=4500 -fucom(2.000000 -nan)=4500 -fxam(2.000000)=0400 -fcom(-nan -1.000000)=4500 -fucom(-nan -1.000000)=4500 -fxam(-nan)=0300 -fcom(-inf -1.000000)=0100 -fucom(-inf -1.000000)=0100 -fxam(-inf)=0700 -fcom(inf -1.000000)=0000 -fucom(inf -1.000000)=0000 -fxam(inf)=0500 -(float)5.000000000000000e-01 = 5.0000000e-01 -(long double)0.500000 = 0.500000 -a=3fe0000000000000 -la=8000000000000000 3ffe -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = 0.000000 -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = 0.000000 -(short)a = 1 -(int)a = 1 -(int64_t)a = 0000000000000001 -rint(a) = 1.000000 -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = 0.000000 -(float)-5.000000000000000e-01 = -5.0000000e-01 -(long double)-0.500000 = -0.500000 -a=bfe0000000000000 -la=8000000000000000 bffe -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = -0.000000 -(short)a = -1 -(int)a = -1 -(int64_t)a = ffffffffffffffff -rint(a) = -1.000000 -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = -0.000000 -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = -0.000000 -(float)1.428571428571428e-01 = 1.4285715e-01 -(long double)0.142857 = 0.142857 -a=3fc2492492492492 -la=9249249249249000 3ffc -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = 0.000000 -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = 0.000000 -(short)a = 1 -(int)a = 1 -(int64_t)a = 0000000000000001 -rint(a) = 1.000000 -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = 0.000000 -(float)-1.111111111111111e-01 = -1.1111111e-01 -(long double)-0.111111 = -0.111111 -a=bfbc71c71c71c71c -la=e38e38e38e38e000 bffb -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = -0.000000 -(short)a = -1 -(int)a = -1 -(int64_t)a = ffffffffffffffff -rint(a) = -1.000000 -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = -0.000000 -(short)a = 0 -(int)a = 0 -(int64_t)a = 0000000000000000 -rint(a) = -0.000000 -(float)3.276800000000000e+04 = 3.2768000e+04 -(long double)32768.000000 = 32768.000000 -a=40e0000000000000 -la=8000000000000000 400e -(short)a = -32768 -(int)a = 32768 -(int64_t)a = 0000000000008000 -rint(a) = 32768.000000 -(short)a = -32768 -(int)a = 32768 -(int64_t)a = 0000000000008000 -rint(a) = 32768.000000 -(short)a = -32768 -(int)a = 32768 -(int64_t)a = 0000000000008000 -rint(a) = 32768.000000 -(short)a = -32768 -(int)a = 32768 -(int64_t)a = 0000000000008000 -rint(a) = 32768.000000 -(float)-1.000000000000000e+20 = -1.0000000e+20 -(long double)-100000000000000000000.000000 = -100000000000000000000.000000 -a=c415af1d78b58c40 -la=ad78ebc5ac620000 c041 -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -100000000000000000000.000000 -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -100000000000000000000.000000 -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -100000000000000000000.000000 -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -100000000000000000000.000000 -(float)-inf = -inf -(long double)-inf = -inf -a=fff0000000000000 -la=8000000000000000 ffff -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -inf -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -inf -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -inf -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -inf -(float)inf = inf -(long double)inf = inf -a=7ff0000000000000 -la=8000000000000000 7fff -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = inf -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = inf -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = inf -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = inf -(float)-nan = -nan -(long double)-nan = -nan -a=fff8000000000000 -la=c000000000000000 ffff -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -nan -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -nan -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -nan -(short)a = -32768 -(int)a = -2147483648 -(int64_t)a = 8000000000000000 -rint(a) = -nan -fld1= 1.000000 -fldl2t= 3.321928 -fldl2e= 1.442695 -fldpi= 3.141593 -fldlg2= 0.301030 -fldln2= 0.693147 -fldz= 0.000000 -a=1234567890123456.000000 bcd=00001234567890123456 b=1234567890123456.000000 -a=-123451234567890.000000 bcd=80000123451234567890 b=-123451234567890.000000 -res[0]=5.000000 -res[1]=4.000000 -res[2]=3.000000 -res[3]=2.000000 -res[4]=1.000000 -fpuc=037f fpus=1800 fptag=003f -res[0]=5.000000 -res[1]=4.000000 -res[2]=3.000000 -res[3]=2.000000 -res[4]=1.000000 -fpuc=037f fpus=1800 fptag=003f -res[0]=5.000000 -res[1]=4.000000 -res[2]=3.000000 -res[3]=2.000000 -res[4]=1.000000 -fpuc=037f fpus=1800 fptag=003f -res[0]=5.000000 -res[1]=4.000000 -res[2]=3.000000 -res[3]=2.000000 -res[4]=1.000000 -fpuc=037f fpus=1800 fptag=003f -fptag=0c3f -xchgl A=fbca7654 B=12345678 -xchgw A=12347654 B=fbca5678 -xchgb A=12345654 B=fbca7678 -xchgl A=fbca7654 B=12345678 -xchgw A=12347654 B=fbca5678 -xchgb A=12345654 B=fbca7678 -xaddl A=fbca7654 B=0dfecccc -xaddw A=12347654 B=fbcacccc -xaddb A=12345654 B=fbca76cc -xaddl same res=2468acf0 -xaddl A=fbca7654 B=0dfecccc -xaddw A=12347654 B=fbcacccc -xaddb A=12345654 B=fbca76cc -cmpxchgl EAX=fbca7654 A=12345678 C=12345678 -cmpxchgw EAX=fbca7654 A=12345678 C=fbca5678 -cmpxchgb EAX=fbca7654 A=12345678 C=fbca7678 -cmpxchgl EAX=fffefdfc A=12345678 C=fbca7654 -cmpxchgw EAX=fffefdfc A=12345678 C=fbca7654 -cmpxchgb EAX=fffefdfc A=12345678 C=fbca7654 -cmpxchgl EAX=fbca7654 A=12345678 C=12345678 -cmpxchgw EAX=fbca7654 A=12345678 C=fbca5678 -cmpxchgb EAX=fbca7654 A=12345678 C=fbca7678 -cmpxchgl EAX=fffefdfc A=12345678 C=fbca7654 -cmpxchgw EAX=fffefdfc A=12345678 C=fbca7654 -cmpxchgb EAX=fffefdfc A=12345678 C=fbca7654 -cmpxchg8b: eax=65423456 edx=000fbca7 op1=000fbca765423456 CC=00 -cmpxchg8b: eax=6789abcd edx=00012345 op1=0006532432432434 CC=40 -stosb ESI= +0 EDI= +1 EAX=12345678 ECX=00000011 EFL=0000 -stosw ESI= +0 EDI= +2 EAX=12345678 ECX=00000011 EFL=0000 -stosl ESI= +0 EDI= +4 EAX=12345678 ECX=00000011 EFL=0000 -stosb ESI= +0 EDI= -1 EAX=12345678 ECX=00000011 EFL=0000 -stosw ESI= +0 EDI= -2 EAX=12345678 ECX=00000011 EFL=0000 -stosl ESI= +0 EDI= -4 EAX=12345678 ECX=00000011 EFL=0000 -rep stosb ESI= +0 EDI=+17 EAX=12345678 ECX=00000000 EFL=0000 -rep stosw ESI= +0 EDI=+34 EAX=12345678 ECX=00000000 EFL=0000 -rep stosl ESI= +0 EDI=+68 EAX=12345678 ECX=00000000 EFL=0000 -rep stosb ESI= +0 EDI=-17 EAX=12345678 ECX=00000000 EFL=0000 -rep stosw ESI= +0 EDI=-34 EAX=12345678 ECX=00000000 EFL=0000 -rep stosl ESI= +0 EDI=-68 EAX=12345678 ECX=00000000 EFL=0000 -lodsb ESI= +1 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -lodsw ESI= +2 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -lodsl ESI= +4 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -lodsb ESI= -1 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -lodsw ESI= -2 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -lodsl ESI= -4 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -rep lodsb ESI=+17 EDI= +0 EAX=12345678 ECX=00000000 EFL=0000 -rep lodsw ESI=+34 EDI= +0 EAX=12345678 ECX=00000000 EFL=0000 -rep lodsl ESI=+68 EDI= +0 EAX=12345678 ECX=00000000 EFL=0000 -rep lodsb ESI=-17 EDI= +0 EAX=12345678 ECX=00000000 EFL=0000 -rep lodsw ESI=-34 EDI= +0 EAX=12345678 ECX=00000000 EFL=0000 -rep lodsl ESI=-68 EDI= +0 EAX=19181716 ECX=00000000 EFL=0000 -movsb ESI= +1 EDI= +1 EAX=12345678 ECX=00000011 EFL=0000 -movsw ESI= +2 EDI= +2 EAX=12345678 ECX=00000011 EFL=0000 -movsl ESI= +4 EDI= +4 EAX=12345678 ECX=00000011 EFL=0000 -movsb ESI= -1 EDI= -1 EAX=12345678 ECX=00000011 EFL=0000 -movsw ESI= -2 EDI= -2 EAX=12345678 ECX=00000011 EFL=0000 -movsl ESI= -4 EDI= -4 EAX=12345678 ECX=00000011 EFL=0000 -rep movsb ESI=+17 EDI=+17 EAX=12345678 ECX=00000000 EFL=0000 -rep movsw ESI=+34 EDI=+34 EAX=12345678 ECX=00000000 EFL=0000 -rep movsl ESI=+68 EDI=+68 EAX=12345678 ECX=00000000 EFL=0000 -rep movsb ESI=-17 EDI=-17 EAX=12345678 ECX=00000000 EFL=0000 -rep movsw ESI=-34 EDI=-34 EAX=12345678 ECX=00000000 EFL=0000 -rep movsl ESI=-68 EDI=-68 EAX=12345678 ECX=00000000 EFL=0000 -lodsb ESI= +1 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -lodsw ESI= +2 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -lodsl ESI= +4 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -lodsb ESI= -1 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -lodsw ESI= -2 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -lodsl ESI= -4 EDI= +0 EAX=12345678 ECX=00000011 EFL=0000 -scasb ESI= +0 EDI= +1 EAX=12345678 ECX=00000011 EFL=0044 -scasw ESI= +0 EDI= +2 EAX=12345678 ECX=00000011 EFL=0044 -scasl ESI= +0 EDI= +4 EAX=12345678 ECX=00000011 EFL=0044 -scasb ESI= +0 EDI= -1 EAX=12345678 ECX=00000011 EFL=0044 -scasw ESI= +0 EDI= -2 EAX=12345678 ECX=00000011 EFL=0044 -scasl ESI= +0 EDI= -4 EAX=12345678 ECX=00000011 EFL=0044 -repz scasb ESI= +0 EDI= +2 EAX=12345678 ECX=0000000f EFL=0004 -repz scasw ESI= +0 EDI= +4 EAX=12345678 ECX=0000000f EFL=0004 -repz scasl ESI= +0 EDI=+68 EAX=12345678 ECX=00000000 EFL=0044 -repz scasb ESI= +0 EDI= -2 EAX=12345678 ECX=0000000f EFL=0004 -repz scasw ESI= +0 EDI= -4 EAX=12345678 ECX=0000000f EFL=0004 -repz scasl ESI= +0 EDI=-56 EAX=12345678 ECX=00000003 EFL=0085 -repnz scasb ESI= +0 EDI= +1 EAX=12345678 ECX=00000010 EFL=0044 -repnz scasw ESI= +0 EDI= +2 EAX=12345678 ECX=00000010 EFL=0044 -repnz scasl ESI= +0 EDI= +4 EAX=12345678 ECX=00000010 EFL=0044 -repnz scasb ESI= +0 EDI= -1 EAX=12345678 ECX=00000010 EFL=0044 -repnz scasw ESI= +0 EDI= -2 EAX=12345678 ECX=00000010 EFL=0044 -repnz scasl ESI= +0 EDI= -4 EAX=12345678 ECX=00000010 EFL=0044 -cmpsb ESI= +1 EDI= +1 EAX=12345678 ECX=00000011 EFL=0044 -cmpsw ESI= +2 EDI= +2 EAX=12345678 ECX=00000011 EFL=0044 -cmpsl ESI= +4 EDI= +4 EAX=12345678 ECX=00000011 EFL=0044 -cmpsb ESI= -1 EDI= -1 EAX=12345678 ECX=00000011 EFL=0044 -cmpsw ESI= -2 EDI= -2 EAX=12345678 ECX=00000011 EFL=0044 -cmpsl ESI= -4 EDI= -4 EAX=12345678 ECX=00000011 EFL=0044 -repz cmpsb ESI=+17 EDI=+17 EAX=12345678 ECX=00000000 EFL=0044 -repz cmpsw ESI=+34 EDI=+34 EAX=12345678 ECX=00000000 EFL=0044 -repz cmpsl ESI=+68 EDI=+68 EAX=12345678 ECX=00000000 EFL=0044 -repz cmpsb ESI=-17 EDI=-17 EAX=12345678 ECX=00000000 EFL=0044 -repz cmpsw ESI=-34 EDI=-34 EAX=12345678 ECX=00000000 EFL=0044 -repz cmpsl ESI=-40 EDI=-40 EAX=12345678 ECX=00000007 EFL=0014 -repnz cmpsb ESI= +1 EDI= +1 EAX=12345678 ECX=00000010 EFL=0044 -repnz cmpsw ESI= +2 EDI= +2 EAX=12345678 ECX=00000010 EFL=0044 -repnz cmpsl ESI= +4 EDI= +4 EAX=12345678 ECX=00000010 EFL=0044 -repnz cmpsb ESI= -1 EDI= -1 EAX=12345678 ECX=00000010 EFL=0044 -repnz cmpsw ESI= -2 EDI= -2 EAX=12345678 ECX=00000010 EFL=0044 -repnz cmpsl ESI= -4 EDI= -4 EAX=12345678 ECX=00000010 EFL=0044 -xlat: EAX=12345688 -func_lret=87654321 -func_iret=abcd4321 -popl esp=09abcdef -popw esp=00bc6058 -lea 0x4000 = 00004000 -lea (%%eax) = 00000001 -lea (%%ebx) = 00000002 -lea (%%ecx) = 00000004 -lea (%%edx) = 00000008 -lea (%%esi) = 00000010 -lea (%%edi) = 00000020 -lea 0x40(%%eax) = 00000041 -lea 0x40(%%ebx) = 00000042 -lea 0x40(%%ecx) = 00000044 -lea 0x40(%%edx) = 00000048 -lea 0x40(%%esi) = 00000050 -lea 0x40(%%edi) = 00000060 -lea 0x4000(%%eax) = 00004001 -lea 0x4000(%%ebx) = 00004002 -lea 0x4000(%%ecx) = 00004004 -lea 0x4000(%%edx) = 00004008 -lea 0x4000(%%esi) = 00004010 -lea 0x4000(%%edi) = 00004020 -lea (%%eax, %%ecx) = 00000005 -lea (%%ebx, %%edx) = 0000000a -lea (%%ecx, %%ecx) = 00000008 -lea (%%edx, %%ecx) = 0000000c -lea (%%esi, %%ecx) = 00000014 -lea (%%edi, %%ecx) = 00000024 -lea 0x40(%%eax, %%ecx) = 00000045 -lea 0x4000(%%ebx, %%edx) = 0000400a -lea (%%ecx, %%ecx, 2) = 0000000c -lea (%%edx, %%ecx, 4) = 00000018 -lea (%%esi, %%ecx, 8) = 00000030 -lea (,%%eax, 2) = 00000002 -lea (,%%ebx, 4) = 00000008 -lea (,%%ecx, 8) = 00000020 -lea 0x40(,%%eax, 2) = 00000042 -lea 0x40(,%%ebx, 4) = 00000048 -lea 0x40(,%%ecx, 8) = 00000060 -lea -10(%%ecx, %%ecx, 2) = 00000002 -lea -10(%%edx, %%ecx, 4) = 0000000e -lea -10(%%esi, %%ecx, 8) = 00000026 -lea 0x4000(%%ecx, %%ecx, 2) = 0000400c -lea 0x4000(%%edx, %%ecx, 4) = 00004018 -lea 0x4000(%%esi, %%ecx, 8) = 00004030 -lea 0x4000 = 00004000 -lea (%%bx) = 00000002 -lea (%%si) = 00000010 -lea (%%di) = 00000020 -lea 0x40(%%bx) = 00000042 -lea 0x40(%%si) = 00000050 -lea 0x40(%%di) = 00000060 -lea 0x4000(%%bx) = 00004002 -lea 0x4000(%%si) = 00004010 -lea (%%bx,%%si) = 00000012 -lea (%%bx,%%di) = 00000022 -lea 0x40(%%bx,%%si) = 00000052 -lea 0x40(%%bx,%%di) = 00000062 -lea 0x4000(%%bx,%%si) = 00004012 -lea 0x4000(%%bx,%%di) = 00004022 -cbw A=8234a6f8 R=8234fff8 -cwde A=8234a6f8 R=ffffa6f8 -cwd A=8234a6f8 R=8234a6f8:8345ffff -cdq A=8234a6f8 R=8234a6f8:ffffffff -bswapl : A=12345678 R=78563412 -daa A=12340503 R=12340509 CCIN=0010 CC=0014 -daa A=12340506 R=1234050c CCIN=0010 CC=0014 -daa A=12340507 R=1234050d CCIN=0010 CC=0010 -daa A=12340559 R=1234055f CCIN=0010 CC=0014 -daa A=12340560 R=12340566 CCIN=0010 CC=0014 -daa A=1234059f R=12340505 CCIN=0010 CC=0015 -daa A=123405a0 R=12340506 CCIN=0010 CC=0015 -daa A=12340503 R=12340503 CCIN=0000 CC=0004 -daa A=12340506 R=12340506 CCIN=0000 CC=0004 -daa A=12340503 R=12340563 CCIN=0001 CC=0005 -daa A=12340506 R=12340566 CCIN=0001 CC=0005 -daa A=12340503 R=12340569 CCIN=0011 CC=0015 -daa A=12340506 R=1234056c CCIN=0011 CC=0015 -das A=12340503 R=123405fd CCIN=0010 CC=0091 -das A=12340506 R=12340500 CCIN=0010 CC=0054 -das A=12340507 R=12340501 CCIN=0010 CC=0010 -das A=12340559 R=12340553 CCIN=0010 CC=0014 -das A=12340560 R=1234055a CCIN=0010 CC=0014 -das A=1234059f R=12340539 CCIN=0010 CC=0015 -das A=123405a0 R=1234053a CCIN=0010 CC=0015 -das A=12340503 R=12340503 CCIN=0000 CC=0004 -das A=12340506 R=12340506 CCIN=0000 CC=0004 -das A=12340503 R=123405a3 CCIN=0001 CC=0085 -das A=12340506 R=123405a6 CCIN=0001 CC=0085 -das A=12340503 R=1234059d CCIN=0011 CC=0091 -das A=12340506 R=123405a0 CCIN=0011 CC=0095 -aaa A=12340205 R=1234030b CCIN=0010 CC=0011 -aaa A=12340306 R=1234040c CCIN=0010 CC=0011 -aaa A=1234040a R=12340500 CCIN=0010 CC=0011 -aaa A=123405fa R=12340700 CCIN=0010 CC=0011 -aaa A=12340205 R=12340205 CCIN=0000 CC=0000 -aaa A=12340306 R=12340306 CCIN=0000 CC=0000 -aaa A=1234040a R=12340500 CCIN=0000 CC=0011 -aaa A=123405fa R=12340700 CCIN=0000 CC=0011 -aas A=12340205 R=1234000f CCIN=0010 CC=0011 -aas A=12340306 R=12340200 CCIN=0010 CC=0011 -aas A=1234040a R=12340304 CCIN=0010 CC=0011 -aas A=123405fa R=12340404 CCIN=0010 CC=0011 -aas A=12340205 R=12340205 CCIN=0000 CC=0000 -aas A=12340306 R=12340306 CCIN=0000 CC=0000 -aas A=1234040a R=12340304 CCIN=0000 CC=0011 -aas A=123405fa R=12340404 CCIN=0000 CC=0011 -aam A=12340547 R=12340701 CCIN=0010 CC=0000 -aad A=12340407 R=1234002f CCIN=0010 CC=0000 -self modifying code: -func1 = 0x1 -func2 = 0x2 -func3 = 0x3 -func4 = 0x4 -smc_code2(2) = 2 -smc_code2(3) = 3 -smc_code2(4) = 4 diff --git a/test/cpu/test-i386-code16.S b/test/cpu/test-i386-code16.S index a5e458a..05394d1 100644 --- a/test/cpu/test-i386-code16.S +++ b/test/cpu/test-i386-code16.S @@ -77,7 +77,3 @@ myfunc2: code16_end: - -#ifdef __ELF__ -.section .note.GNU-stack,"",%progbits -#endif diff --git a/test/cpu/test-i386-shift.h b/test/cpu/test-i386-shift.h index 2fe2eaf..6cbe537 100644 --- a/test/cpu/test-i386-shift.h +++ b/test/cpu/test-i386-shift.h @@ -1,3 +1,4 @@ + #define exec_op glue(exec_, OP) #define exec_opq glue(glue(exec_, OP), q) #define exec_opl glue(glue(exec_, OP), l) @@ -57,10 +58,6 @@ void exec_opl(long s2, long s0, long s1, long iflags) void exec_opw(long s2, long s0, long s1, long iflags) { long res, flags; - - if ((strcmp(stringify(OP), "shld") == 0 || - strcmp(stringify(OP), "shrd") == 0) && s1 > 16) - return; res = s0; flags = iflags; EXECSHIFT("w", "w", res, s1, s2, flags); @@ -112,10 +109,6 @@ void exec_opl(long s2, long s0, long s1, long iflags) void exec_opw(long s2, long s0, long s1, long iflags) { long res, flags; - - if ((strcmp(stringify(OP), "shld") == 0 || - strcmp(stringify(OP), "shrd") == 0) && s1 > 16) - return; res = s0; flags = iflags; EXECSHIFT("w", "w", res, s1, s2, flags); @@ -151,7 +144,11 @@ void exec_op(long s2, long s0, long s1) exec_opq(s2, s0, s1, 0); #endif exec_opl(s2, s0, s1, 0); +#ifdef OP_SHIFTD exec_opw(s2, s0, s1, 0); +#else + exec_opw(s2, s0, s1, 0); +#endif #ifndef OP_NOBYTE exec_opb(s0, s1, 0); #endif diff --git a/test/cpu/test-i386-vm86.S b/test/cpu/test-i386-vm86.S index b9947e8..040059c 100644 --- a/test/cpu/test-i386-vm86.S +++ b/test/cpu/test-i386-vm86.S @@ -105,7 +105,3 @@ IF_msg1: .string "If you see a diff here, your Linux kernel is buggy, please update to 2.4.20 kernel\n$" vm86_code_end: - -#ifdef __ELF__ -.section .note.GNU-stack,"",%progbits -#endif diff --git a/test/cpu/test-i386.c b/test/cpu/test-i386.c index ef98882..9a94a81 100644 --- a/test/cpu/test-i386.c +++ b/test/cpu/test-i386.c @@ -2416,8 +2416,8 @@ static void test_enter(void) #ifdef TEST_SSE -typedef int __m64 __attribute__ ((vector_size (8))); -typedef float __m128 __attribute__ ((vector_size (16))); +typedef int __m64 __attribute__ ((__mode__ (__V2SI__))); +typedef float __m128 __attribute__ ((__mode__(__V4SF__))); typedef union { double d[2]; @@ -2591,7 +2591,7 @@ void test_sse_comi(double a1, double b1) } /* Force %xmm0 usage to avoid the case where both register index are 0 - to test instruction decoding more extensively */ + to test intruction decoding more extensively */ #define CVT_OP_XMM2MMX(op)\ {\ asm volatile (#op " %1, %0" : "=y" (r.q[0]) : "x" (a.dq) \ @@ -3084,7 +3084,7 @@ int main(int argc, char **argv) if (argc >= 2 && strcmp(argv[1], "--common-tests") == 0) return 0; -// tests that will probably never produce the same output on different platforms +// tests that will probabaly never produce the same output on different platforms test_exceptions(); test_enter(); diff --git a/test/dosemu_tap_interface.sh b/test/dosemu_tap_interface.sh deleted file mode 100755 index 6303ded..0000000 --- a/test/dosemu_tap_interface.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -# Notes: -# 1/ this file needs to be installed in the well known location by root -# cp test/dosemu_tap_interface.sh /bin/. -# chmod 755 /bin/dosemu_tap_interface.sh -# chown root.root /bin/dosemu_tap_interface.sh -# -# 2/ sudo needs to be configured by root for the test user to run it -# without passwd -# echo 'ajb ALL=(ALL) NOPASSWD: /bin/dosemu_tap_interface.sh' > /etc/sudoers.d/dosemu -# chmod 0440 /etc/sudoers.d/dosemu - -if [ "$1" = "setup" ] ; then - ip tuntap add mode tap user ${SUDO_UID} tap0 - brctl addif virbr0 tap0 - ifconfig tap0 promisc up - -elif [ "$1" = "teardown" ] ; then - ifconfig tap0 down - brctl delif virbr0 tap0 - ip tuntap del mode tap tap0 - -else - echo "${0}: incorrect args" - exit 1 -fi diff --git a/test/ecm/dpmitest/Makefile b/test/ecm/dpmitest/Makefile index 0568a46..9afb07f 100644 --- a/test/ecm/dpmitest/Makefile +++ b/test/ecm/dpmitest/Makefile @@ -1,5 +1,5 @@ -all: dpmialoc.com dpmimini.com dpmims.com dpmipsp.com +all: dpmialoc.com dpmimini.com dpmims.com dpmipsp.com %.com: %.asm nasm -f bin -I../lmacros/ -o $@ $< diff --git a/test/func_cpu_trap_flag.py b/test/func_cpu_trap_flag.py index 0c2148d..5ff2758 100644 --- a/test/func_cpu_trap_flag.py +++ b/test/func_cpu_trap_flag.py @@ -1,5 +1,3 @@ -import re - from cpuinfo import get_cpu_info from os import access, R_OK, W_OK @@ -9,7 +7,7 @@ def cpu_trap_flag(self, cpu_vm): raise ValueError('invalid argument') if cpu_vm == "kvm" and not access("/dev/kvm", W_OK|R_OK): - self.skipTest("requires KVM") + self.skipTest("No KVM available") config = """ $_hdimage = "dXXXXs/c:hdtype1 +1" @@ -23,80 +21,57 @@ rem end """, newline="\r\n") # compile sources - self.mkcom_with_nasm("cputrapf", r""" + self.mkcom_with_gas("cputrapf", r""" +.text +.code16 -bits 16 -cpu 386 + .globl _start16 +_start16: -org 100h + push %cs + pop %ds -section .text - - push cs - pop ds - - mov ax, 2501h - mov dx, int1 - int 21h - - mov ax, 14h - mov bx, 1 - int 0xe6 - - push 3003h - push 3303h - popf - popf + movw $0x2501, %ax + movw $int1, %dx + int $0x21 + pushw $0x3003 + pushw $0x3303 + popfw + popfw nop - mov ax, 14h - mov bx, 0 - int 0xe6 - - mov ah, 9 ; print string - mov dx, result - int 21h + movb $0x9, %ah # print string + movw $result, %dx + int $0x21 exit: - mov ax, 4c00h - int 21h + movw $0x4c00, %ax + int $0x21 ret int1: - inc byte [cs:result.cnt] + incb %cs:cnt iret -section .data - result: - db "Result is (" -.cnt: - db '0' - db ')',13,10,'$' + .ascii "Result is (" +cnt: + .byte '0' + .ascii ")\r\n$" + """) results = self.runDosemu("testit.bat", config=config) - # Extract the result value - r1 = re.compile(r'Result is \((\d+)\)') - self.assertRegex(results, r1) - t = r1.search(results) - rval = int(t.group(1), 10) - - # Some unknown error in the test - self.assertNotEqual(rval, 0, results) + self.assertIn("Result is (1)", results) if cpu_vm != 'kvm': - self.assertEqual(rval, 1, results) return # check for fixup - fixupmsg = "KVM: not applying TF fixup" + fixupmsg = "KVM: applying TF fixup" knownbad = ( 'AMD FX(tm)-8350 Eight-Core Processor', - 'AMD A10-7870K Radeon R7, 12 Compute Cores 4C+8G', - 'AMD Ryzen 5 5600U with Radeon Graphics', - 'AMD EPYC 7763 64-Core Processor', ) # get log content @@ -113,11 +88,11 @@ result: except KeyError: name = str(cpu) - if rval == 1: - if name in knownbad: - self.fail("Unexpected success with cpu '%s'" % name) - elif rval > 1 or fixupmsg in results or fixupmsg in logcontents: - if name in knownbad: + if name in knownbad: + if fixupmsg in results or fixupmsg in logcontents: self.setMessage("known bad cpu '%s'" % name) else: + self.fail("Unexpected success with cpu '%s'" % name) + else: + if fixupmsg in results or fixupmsg in logcontents: self.fail("Fail with unknown cpu '%s'" % name) diff --git a/test/func_ds2_file_seek_read.py b/test/func_ds2_file_seek_read.py index 6297292..b810eba 100644 --- a/test/func_ds2_file_seek_read.py +++ b/test/func_ds2_file_seek_read.py @@ -30,169 +30,166 @@ rem end """ % ename, newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds - - mov ax, 3c00h ; create file - mov cx, 0 - mov dx, fname - int 21h + movw $0x3c00, %%ax # create file + movw $0, %%cx + movw $fname, %%dx + int $0x21 jc prfailcreate - mov word [fhndl], ax + movw %%ax, fhndl - mov ax, 4000h ; write testdata - mov bx, word [fhndl] - mov cx, fdatalen - mov dx, fdata - int 21h + movw $0x4000, %%ax # write testdata + movw fhndl, %%bx + movw $fdatalen, %%cx + movw $fdata, %%dx + int $0x21 jc prfailwrite - cmp ax, fdatalen + cmpw $fdatalen, %%ax jne prnumwrite - mov ax, 3e00h ; close file - mov bx, word [fhndl] - int 21h + movw $0x3e00, %%ax # close file + movw fhndl, %%bx + int $0x21 - mov ax, 3d00h ; open file readonly - mov dx, fname - int 21h + movw $0x3d00, %%ax # open file readonly + movw $fname, %%dx + int $0x21 jc prfailopen - mov word [fhndl], ax + movw %%ax, fhndl - mov ax, 3f00h ; read from file to middle - mov bx, word [fhndl] - mov cx, 16 - mov dx, ftemp - int 21h + movw $0x3f00, %%ax # read from file to middle + movw fhndl, %%bx + movw $16, %%cx + movw $ftemp, %%dx + int $0x21 jc prfailread - cmp ax, 16 + cmpw $16, %%ax jne prnumread - mov ax, %xh ; seek from whence to somewhere - mov bx, word [fhndl] - mov si, seekval - mov cx, [ds:si + 2] - mov dx, [ds:si] - int 21h + movw $0x%x, %%ax # seek from whence to somewhere + movw fhndl, %%bx + movw $seekval, %%si + movw %%ds:2(%%si), %%cx + movw %%ds:0(%%si), %%dx + int $0x21 jc prcarryset - mov ax, 3f00h ; read 4 chars from new position - mov bx, word [fhndl] - mov cx, 4 - mov dx, fdata2 - int 21h + movw $0x3f00, %%ax # read 4 chars from new position + movw fhndl, %%bx + movw $4, %%cx + movw $fdata2, %%dx + int $0x21 jc prfailread2 - cmp ax, 4 + cmpw $4, %%ax jne prnumread2 jmp prsucc prfailcreate: - mov dx, failcreate - jmp @1 + movw $failcreate, %%dx + jmp 1f prfailwrite: - mov dx, failwrite - jmp @2 + movw $failwrite, %%dx + jmp 2f prnumwrite: - mov dx, numwrite - jmp @2 + movw $numwrite, %%dx + jmp 2f prfailopen: - mov dx, failopen - jmp @1 + movw $failopen, %%dx + jmp 1f prfailread: - mov dx, failread - jmp @2 + movw $failread, %%dx + jmp 2f prnumread: - mov dx, numread - jmp @2 + movw $numread, %%dx + jmp 2f prcarryset: - mov dx, carryset - jmp @2 + movw $carryset, %%dx + jmp 2f prfailread2: - mov dx, failread2 - jmp @2 + movw $failread2, %%dx + jmp 2f prnumread2: - mov dx, numread2 - jmp @2 + movw $numread2, %%dx + jmp 2f prsucc: - mov byte [fdata2 + 4], ')' - mov byte [fdata2 + 5], 13 - mov byte [fdata2 + 6], 10 - mov byte [fdata2 + 7], '$' - mov dx, success - jmp @2 + movb $')', (fdata2 + 4) + movb $'\r', (fdata2 + 5) + movb $'\n', (fdata2 + 6) + movb $'$', (fdata2 + 7) + movw $success, %%dx + jmp 2f -@2: - mov ax, 3e00h ; close file - mov bx, word [fhndl] - int 21h +2: + movw $0x3e00, %%ax # close file + movw fhndl, %%bx + int $0x21 -@1: - mov ah, 9 ; print string - int 21h +1: + movb $0x9, %%ah # print string + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 seekval: - dd %d + .long %d fname: - db "%s", 0 + .asciz "%s" fhndl: - dw 0 + .word 0 fdata: - db "%s" -fdatalen equ $ - fdata + .ascii "%s" +fdatalen = (. - fdata) success: - db "Operation Success(" + .ascii "Operation Success(" fdata2: - times 64 db 0 + .space 64 ftemp: - times 64 db 0 + .space 64 failcreate: - db "Create Operation Failed",13,10,'$' + .ascii "Create Operation Failed\r\n$" failwrite: - db "Write Operation Failed",13,10,'$' + .ascii "Write Operation Failed\r\n$" numwrite: - db "Write Incorrect Length",13,10,'$' + .ascii "Write Incorrect Length\r\n$" failopen: - db "Open Operation Failed",13,10,'$' + .ascii "Open Operation Failed\r\n$" failread: - db "Read Operation Failed",13,10,'$' + .ascii "Read Operation Failed\r\n$" numread: - db "Read Not 16 Chars",13,10,'$' + .ascii "Read Not 16 Chars\r\n$" carryset: - db "Seek Carry Set",13,10,'$' + .ascii "Seek Carry Set\r\n$" failread2: - db "Read2 Operation Failed",13,10,'$' + .ascii "Read2 Operation Failed\r\n$" numread2: - db "Read2 Not 4 Chars",13,10,'$' + .ascii "Read2 Not 4 Chars\r\n$" """ % (dosfunc, seekval, "test.fil", testdata)) diff --git a/test/func_ds2_file_seek_tell.py b/test/func_ds2_file_seek_tell.py index 79f5fd0..0caafd2 100644 --- a/test/func_ds2_file_seek_tell.py +++ b/test/func_ds2_file_seek_tell.py @@ -29,138 +29,135 @@ rem end }[testfunc] # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds - - mov ax, 3c00h ; create file - mov cx, 0 - mov dx, fname - int 21h + movw $0x3c00, %%ax # create file + movw $0, %%cx + movw $fname, %%dx + int $0x21 jc prfailcreate - mov word [fhndl], ax + movw %%ax, fhndl - mov cx, 1000h ; number of 512 byte chunks + movw $0x1000, %%cx # number of 512 byte chunks -@1: - push cx - mov ax, 4000h ; write testdata - mov bx, word [fhndl] - mov cx, fdatalen - mov dx, fdata - int 21h - pop cx +1: + pushw %%cx + movw $0x4000, %%ax # write testdata + movw fhndl, %%bx + movw $fdatalen, %%cx + movw $fdata, %%dx + int $0x21 + popw %%cx jc prfailwrite - cmp ax, fdatalen + cmpw $fdatalen, %%ax jne prnumwrite - loop @1 + loop 1b - mov ax, %xh ; seek from whence to somewhere - mov bx, word [fhndl] - mov si, seekval - mov cx, word [ds:si + 2] - mov dx, word [ds:si] - int 21h + movw $0x%x, %%ax # seek from whence to somewhere + movw fhndl, %%bx + movw $seekval, %%si + movw %%ds:2(%%si), %%cx + movw %%ds:0(%%si), %%dx + int $0x21 jc prcarryset - shl edx, 16 ; compare the resultant position - mov dx, ax - mov ecx, long [expected] - cmp ecx, edx + shll $16, %%edx # compare the resultant position + movw %%ax, %%dx + movl expected, %%ecx + cmpl %%edx, %%ecx jne prfailcompare jmp prsucc prfailcreate: - mov dx, failcreate - jmp @3 + movw $failcreate, %%dx + jmp 1f prfailwrite: - mov dx, failwrite - jmp @2 + movw $failwrite, %%dx + jmp 2f prnumwrite: - mov dx, numwrite - jmp @2 + movw $numwrite, %%dx + jmp 2f prcarryset: - mov dx, carryset - jmp @2 + movw $carryset, %%dx + jmp 2f prfailcompare: - mov dx, failcompare - jmp @2 + movw $failcompare, %%dx + jmp 2f prsucc: - mov dx, success - jmp @2 + movw $success, %%dx + jmp 2f -@2: - mov ax, 3e00h ; close file - mov bx, word [fhndl] - int 21h +2: + movw $0x3e00, %%ax # close file + movw fhndl, %%bx + int $0x21 -@3: - mov ah, 9 ; print string - int 21h +1: + movb $0x9, %%ah # print string + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 seekval: - dd %d + .long %d expected: - dd %d + .long %d fname: - db "test.fil", 0 + .asciz "test.fil" fhndl: - dw 0 + .word 0 fdata: - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" - db "0123456789abcdefFEDCBA9876543210" -fdatalen equ $ - fdata + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" + .ascii "0123456789abcdefFEDCBA9876543210" +fdatalen = (. - fdata) success: - db "Operation Success",13,10,'$' + .ascii "Operation Success\r\n$" failcreate: - db "Create Operation Failed",13,10,'$' + .ascii "Create Operation Failed\r\n$" failwrite: - db "Write Operation Failed",13,10,'$' + .ascii "Write Operation Failed\r\n$" numwrite: - db "Write Incorrect Length",13,10,'$' + .ascii "Write Incorrect Length\r\n$" carryset: - db "Seek Carry Set",13,10,'$' + .ascii "Seek Carry Set\r\n$" failcompare: - db "File Position Incorrect",13,10,'$' + .ascii "File Position Incorrect\r\n$" """ % (dosfunc, seekval, expected)) diff --git a/test/func_ds3_file_access.py b/test/func_ds3_file_access.py index c7ede2e..6b902bc 100644 --- a/test/func_ds3_file_access.py +++ b/test/func_ds3_file_access.py @@ -31,7 +31,7 @@ void __far __interrupt (*oldint24)(void); volatile uint16_t int24_ax; -void __far __interrupt __attribute__ ((near_section)) myint24(void); /* Prototype */ +void __far __interrupt myint24(void); /* Prototype */ __asm ( "myint24:\n" " pushw %bp\n" diff --git a/test/func_ds3_lock_two_handles.py b/test/func_ds3_lock_two_handles.py index b0b6cbf..725daf4 100644 --- a/test/func_ds3_lock_two_handles.py +++ b/test/func_ds3_lock_two_handles.py @@ -21,7 +21,7 @@ rem end #include #define FNAME "FOO.DAT" -#define FDATA "0123456789abcdefghij" +#define FDATA "0123456789abc" #define FDAT2 " 567 " int main(int argc, char *argv[]) { @@ -29,7 +29,6 @@ int main(int argc, char *argv[]) { int ret, rc; unsigned int attr; char buf[80]; - int read_allowed = 0; if (_dos_creatnew(FNAME, 0, &hnd1) != 0) { printf("FAIL: File '%s' not created\n", FNAME); @@ -91,9 +90,12 @@ int main(int argc, char *argv[]) { ret = _dos_lock(hnd2, 5, 3); // try the same lock handle 2 if (ret == 0) { - // extension, multiple read locks are allowed, make sure also read() works - printf("OKAY: Managed to lock again on file '%s' via different handle\n", FNAME); - read_allowed = 1; + printf("FAIL: Managed to lock again on file '%s' via different handle\n", FNAME); + _dos_unlock(hnd2, 5, 3); + _dos_close(hnd2); + _dos_unlock(hnd1, 5, 3); + _dos_close(hnd1); + return -1; } else if (ret != 33) { // Should be lock violation printf("FAIL: Refused second lock on file '%s' but return (err=%d != 33)\n", FNAME, ret); _dos_close(hnd2); @@ -104,31 +106,9 @@ int main(int argc, char *argv[]) { printf("OKAY: Refused second lock on file '%s', err=%d\n", FNAME, ret); } - /* lock adjacent region, should succeed */ - ret = _dos_lock(hnd2, 8, 3); - if (ret == 0) { - printf("OKAY: Locked adjacent on file '%s' via different handle\n", FNAME); - } else { - printf("FAIL: Refused adjacent lock on file '%s' but return (err=%d != 33)\n", FNAME, ret); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - - /* lock another region, should succeed */ - ret = _dos_lock(hnd2, 14, 3); - if (ret == 0) { - printf("OKAY: Locked another reg on file '%s' via different handle\n", FNAME); - } else { - printf("FAIL: Refused another lock on file '%s' but return (err=%d != 33)\n", FNAME, ret); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - + // try to read the locked region via the second handle (should succeed) memset(buf, ' ', strlen(FDATA)); - // try to read the locked region via the second handle if (llseek(hnd2, 5, SEEK_SET) != 5) { printf("FAIL: File '%s' seek failed\n", FNAME); _dos_close(hnd2); @@ -138,148 +118,13 @@ int main(int argc, char *argv[]) { } ret = _dos_read(hnd2, buf + 5, 3, &rc); // exact match conflict if (ret == 0) { - if (!read_allowed) { - printf("FAIL: Read other's-locked data from file '%s' via second descriptor, cnt=%d\n", FNAME, rc); - _dos_close(hnd2); - _dos_unlock(hnd1, 5, 3); - _dos_close(hnd1); - return -1; - } else { - printf("OKAY: Read other's-locked data from file '%s' via second descriptor, cnt=%d\n", FNAME, rc); - } - } else { - if (!read_allowed) { - printf("OKAY: Refused to read others-locked data from file '%s' via second descriptor, err = %d\n", FNAME, ret); - } else { - printf("FAIL: Refused to read other's-locked data from file '%s' via second descriptor, err = %d\n", FNAME, ret); - _dos_close(hnd2); - _dos_unlock(hnd1, 5, 3); - _dos_close(hnd1); - return -1; - } - } - // try to read the locked region in the middle - if (llseek(hnd2, 6, SEEK_SET) != 6) { - printf("FAIL: File '%s' seek failed\n", FNAME); + printf("FAIL: Read locked data from file '%s' via second descriptor, cnt=%d\n", FNAME, rc); _dos_close(hnd2); _dos_unlock(hnd1, 5, 3); _dos_close(hnd1); return -1; - } - ret = _dos_read(hnd2, buf + 6, 1, &rc); - if (ret == 0) { - if (!read_allowed) { - printf("FAIL: Read within other's-locked data from file '%s' via second descriptor, cnt=%d\n", FNAME, rc); - _dos_close(hnd2); - _dos_unlock(hnd1, 5, 3); - _dos_close(hnd1); - return -1; - } else { - printf("OKAY: Read within other's-locked data from file '%s' via second descriptor, cnt=%d\n", FNAME, rc); - } } else { - if (!read_allowed) { - printf("OKAY: Refused to read within other's-locked data from file '%s' via second descriptor, err = %d\n", FNAME, ret); - } else { - printf("FAIL: Refused to read within other's-locked data from file '%s' via second descriptor, err = %d\n", FNAME, ret); - _dos_close(hnd2); - _dos_unlock(hnd1, 5, 3); - _dos_close(hnd1); - return -1; - } - } - - /* read multiple locked regions */ - if (llseek(hnd2, 0, SEEK_SET) != 0) { - printf("FAIL: File '%s' seek failed\n", FNAME); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - ret = _dos_read(hnd2, buf, 20, &rc); - if (ret == 0) { - if (read_allowed) { - printf("OKAY: Read multiple locked data from file '%s' via second descriptor, cnt=%d\n", FNAME, rc); - } else { - printf("FAIL: Managed to read multiple locked regs from file '%s' via second descriptor, len = %d\n", FNAME, rc); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - } else { - if (read_allowed) { - printf("FAIL: Refused to read multiple locked regs from file '%s' via second descriptor, err = %d\n", FNAME, ret); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } else { - printf("OKAY: Refused to read multiple locked regs from file '%s' via second descriptor, err = %d\n", FNAME, ret); - } - } - - /* read multiple own-locked regions */ - if (llseek(hnd2, 8, SEEK_SET) != 8) { - printf("FAIL: File '%s' seek failed\n", FNAME); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - ret = _dos_read(hnd2, buf + 8, 12, &rc); - if (ret == 0) { - printf("OKAY: Read multiple own-locked data from file '%s' via second descriptor, cnt=%d\n", FNAME, rc); - } else { - printf("FAIL: Refused to read multiple own-locked regs from file '%s' via second descriptor, err = %d\n", FNAME, ret); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - /* read from the middle of region */ - if (llseek(hnd2, 9, SEEK_SET) != 9) { - printf("FAIL: File '%s' seek failed\n", FNAME); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - ret = _dos_read(hnd2, buf + 9, 11, &rc); - if (ret == 0) { - printf("OKAY: Read from middle own-locked reg from file '%s' via second descriptor, cnt=%d\n", FNAME, rc); - } else { - printf("FAIL: Refused to read from middle own-locked reg from file '%s' via second descriptor, err = %d\n", FNAME, ret); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - /* read from unlocked space and span the region */ - if (llseek(hnd2, 13, SEEK_SET) != 13) { - printf("FAIL: File '%s' seek failed\n", FNAME); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - ret = _dos_read(hnd2, buf + 13, 7, &rc); - if (ret == 0) { - printf("OKAY: Read span own-locked reg from file '%s' via second descriptor, cnt=%d\n", FNAME, rc); - } else { - printf("FAIL: Refused to read span own-locked reg from file '%s' via second descriptor, err = %d\n", FNAME, ret); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - /* read within the locked region */ - if (llseek(hnd2, 15, SEEK_SET) != 15) { - printf("FAIL: File '%s' seek failed\n", FNAME); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; - } - ret = _dos_read(hnd2, buf + 15, 1, &rc); - if (ret == 0) { - printf("OKAY: Read within own-locked reg from file '%s' via second descriptor, cnt=%d\n", FNAME, rc); - } else { - printf("FAIL: Refused to read within own-locked reg from file '%s' via second descriptor, err = %d\n", FNAME, ret); - _dos_close(hnd2); - _dos_close(hnd1); - return -1; + printf("OKAY: Refused to read locked data from file '%s' via second descriptor, err = %d\n", FNAME, ret); } printf("PASS: all tests okay on file '%s'\n", FNAME); diff --git a/test/func_ds3_share_open_access.py b/test/func_ds3_share_open_access.py index e2b2f9b..cea61c2 100644 --- a/test/func_ds3_share_open_access.py +++ b/test/func_ds3_share_open_access.py @@ -1,7 +1,7 @@ import re -def _run_all(self, numprocs, fstype, tests, testtype): +def _run_all(self, fstype, tests, testtype): testdir = self.mkworkdir('d') share = "rem Internal share" if self.version == "FDPP kernel" else "c:\\share" @@ -9,10 +9,7 @@ def _run_all(self, numprocs, fstype, tests, testtype): tfile = "set LFN=n\r\n" + "d:\r\n" + share + "\r\n" for t in tests: args = t + (testtype,) - if numprocs == "ONE": - tfile += ("c:\\shardlrn single %s %s %s %s\r\n" % args) - else: - tfile += ("c:\\shardlrn primary %s %s %s %s\r\n" % args) + tfile += ("c:\\shardlrn primary %s %s %s %s\r\n" % args) tfile += "rem tests complete\r\n" tfile += "rem end\r\n" @@ -69,13 +66,8 @@ unsigned short openmode(const char *s) { int main(int argc, char *argv[]) { int handle; int ret; - enum { - PRIMARY, - SECONDARY, - SINGLE, - } ptype; - - unsigned short smode, omode; + int primary = -1; + unsigned short prismode, priomode; enum { DELFCB, RENFCB, @@ -85,29 +77,27 @@ int main(int argc, char *argv[]) { } testmode; if (argc < 6) { - printf("FAIL: Missing arguments (primary|secondary|single) sharemode openmode expected (DELFCB|RENFCB|DELPTH|RENPTH|SETATT)\n"); + printf("FAIL: Missing arguments (primary|secondary) prismode priomode expected (DELFCB|RENFCB|DELPTH|RENPTH|SETATT)\n"); return -2; } if (strcmp(argv[1], "primary") == 0) - ptype = PRIMARY; - else if (strcmp(argv[1], "secondary") == 0) - ptype = SECONDARY; - else if (strcmp(argv[1], "single") == 0) - ptype = SINGLE; - else { - printf("FAIL: Invalid argument (primary|secondary|single)\n"); + primary = 1; + if (strcmp(argv[1], "secondary") == 0) + primary = 0; + if (primary < 0) { + printf("FAIL: Invalid argument (primary|secondary)\n"); return -2; } - smode = sharemode(argv[2]); - if (smode == 0xff) { - printf("FAIL: Invalid argument sharemode '%s'\n", argv[2]); + prismode = sharemode(argv[2]); + if (prismode == 0xff) { + printf("FAIL: Invalid argument prismode '%s'\n", argv[2]); return -2; } - omode = openmode(argv[3]); - if (omode == 0xff) { - printf("FAIL: Invalid argument openmode '%s'\n", argv[3]); + priomode = openmode(argv[3]); + if (priomode == 0xff) { + printf("FAIL: Invalid argument priomode '%s'\n", argv[3]); return -2; } @@ -131,8 +121,8 @@ int main(int argc, char *argv[]) { // Print results in consistent format // FAIL:("SH_DENYNO", "RW", "ALLOW")[secondary denied] - if (ptype == PRIMARY || ptype == SINGLE) { - unsigned short mode = smode | omode; + if (primary) { + unsigned short mode = prismode | priomode; // remove the source file so we can create it anew unlink(FN1 "." FE1); @@ -156,19 +146,12 @@ int main(int argc, char *argv[]) { } // printf("INFO: primary: File was opened with mode 0x%04x\n", mode); - } - - if (ptype == PRIMARY) { - // Now start second copy spawnlp(P_WAIT, argv[0], argv[0], "secondary", argv[2], argv[3], argv[4], argv[5], NULL); _dos_close(handle); - return 0; - } - - if (ptype == SECONDARY || ptype == SINGLE) { + } else { // secondary switch(testmode) { case DELFCB: { @@ -347,7 +330,7 @@ int main(int argc, char *argv[]) { break; } - } // switch + } if (ret != 0) { if (strcmp(argv[4], "DENY") == 0) { @@ -368,10 +351,6 @@ int main(int argc, char *argv[]) { } } - if (ptype == SINGLE) { - _dos_close(handle); - } - return 0; } """) @@ -385,29 +364,7 @@ int main(int argc, char *argv[]) { return self.runDosemu("testit.bat", config=config, timeout=60) -TESTS_ONE_PROCESS = ( - ("SH_COMPAT", "R" , "ALLOW"), - ("SH_COMPAT", "W" , "ALLOW"), - ("SH_COMPAT", "RW", "ALLOW"), - - ("SH_DENYRW", "R" , "DENY"), - ("SH_DENYRW", "W" , "DENY"), - ("SH_DENYRW", "RW", "DENY"), - - ("SH_DENYWR", "R" , "DENY"), - ("SH_DENYWR", "W" , "DENY"), - ("SH_DENYWR", "RW", "DENY"), - - ("SH_DENYRD", "R" , "DENY"), - ("SH_DENYRD", "W" , "DENY"), - ("SH_DENYRD", "RW", "DENY"), - - ("SH_DENYNO", "R" , "DENY"), - ("SH_DENYNO", "W" , "DENY"), - ("SH_DENYNO", "RW", "DENY"), -) - -TESTS_TWO_PROCESS_FAT = ( +DELRENTESTS = ( ("SH_COMPAT", "R" , "DENY"), ("SH_COMPAT", "W" , "DENY"), ("SH_COMPAT", "RW", "DENY"), @@ -429,27 +386,14 @@ TESTS_TWO_PROCESS_FAT = ( ("SH_DENYNO", "RW", "DENY"), ) -# SH_COMPAT makes no sense on network drive, see -# https://github.com/dosemu2/dosemu2/pull/1623#issuecomment-1108776612 -TESTS_TWO_PROCESS_MFS = tuple(TESTS_TWO_PROCESS_FAT)[3:] - - def _check_single_result(self, results, t): m = re.search("FAIL:\('%s', '%s', '%s'\)\[.*\]" % t, results) if m: self.fail(msg=m.group(0)) -def ds3_share_open_access(self, numprocs, fstype, testtype): - if numprocs == "ONE": - tests = TESTS_ONE_PROCESS - else: # TWO - if fstype == "MFS": - tests = TESTS_TWO_PROCESS_MFS - else: # FAT - tests = TESTS_TWO_PROCESS_FAT - - results = _run_all(self, numprocs, fstype, tests, testtype) - for t in tests: +def ds3_share_open_access(self, fstype, testtype): + results = _run_all(self, fstype, DELRENTESTS, testtype) + for t in DELRENTESTS: with self.subTest(t=t): _check_single_result(self, results, t) self.assertIn("rem tests complete", results) diff --git a/test/func_ds3_share_open_twice.py b/test/func_ds3_share_open_twice.py index 2cf883d..e930c13 100644 --- a/test/func_ds3_share_open_twice.py +++ b/test/func_ds3_share_open_twice.py @@ -187,7 +187,7 @@ int main(int argc, char *argv[]) { # 1 = open succeeds if file read-only, else fails with error code. # 2 = open succeeds if file read-only, else fails with INT 24 -OPEN_622 = ( +OPENTESTS = ( # Compat R |Y Y Y N N N 1 N N N N N 1 N N. ("SH_COMPAT", "R" , "SH_COMPAT", "R" , "ALLOW"), ("SH_COMPAT", "R" , "SH_COMPAT", "W" , "ALLOW"), @@ -444,277 +444,14 @@ OPEN_622 = ( ("SH_DENYNO", "RW", "SH_DENYNO", "RW", "ALLOW"), ) -OPEN_HYBRID = ( -# Compat R |Y Y Y N N N 1 N N N N N 1 N N. - ("SH_COMPAT", "R" , "SH_COMPAT", "R" , "ALLOW"), - ("SH_COMPAT", "R" , "SH_COMPAT", "W" , "ALLOW"), - ("SH_COMPAT", "R" , "SH_COMPAT", "RW", "ALLOW"), - ("SH_COMPAT", "R" , "SH_DENYRW", "R" , "DENY"), - ("SH_COMPAT", "R" , "SH_DENYRW", "W" , "DENY"), - ("SH_COMPAT", "R" , "SH_DENYRW", "RW", "DENY"), - ("SH_COMPAT", "R" , "SH_DENYWR", "R" , "ALLOW"), # File RO success, W fails. For MS-DOS-7: always success. - ("SH_COMPAT", "R" , "SH_DENYWR", "W" , "DENY"), - ("SH_COMPAT", "R" , "SH_DENYWR", "RW", "DENY"), - ("SH_COMPAT", "R" , "SH_DENYRD", "R" , "DENY"), - ("SH_COMPAT", "R" , "SH_DENYRD", "W" , "DENY"), - ("SH_COMPAT", "R" , "SH_DENYRD", "RW", "DENY"), - ("SH_COMPAT", "R" , "SH_DENYNO", "R" , "ALLOW"), # File RO success, W fails. For MS-DOS-7: always success. - ("SH_COMPAT", "R" , "SH_DENYNO", "W" , "DENY"), - ("SH_COMPAT", "R" , "SH_DENYNO", "RW", "DENY"), - -# W |Y Y Y N N N N N N N N N N N N. - ("SH_COMPAT", "W" , "SH_COMPAT", "R" , "ALLOW"), - ("SH_COMPAT", "W" , "SH_COMPAT", "W" , "ALLOW"), - ("SH_COMPAT", "W" , "SH_COMPAT", "RW", "ALLOW"), - ("SH_COMPAT", "W" , "SH_DENYRW", "R" , "DENY"), - ("SH_COMPAT", "W" , "SH_DENYRW", "W" , "DENY"), - ("SH_COMPAT", "W" , "SH_DENYRW", "RW", "DENY"), - ("SH_COMPAT", "W" , "SH_DENYWR", "R" , "DENY"), - ("SH_COMPAT", "W" , "SH_DENYWR", "W" , "DENY"), - ("SH_COMPAT", "W" , "SH_DENYWR", "RW", "DENY"), - ("SH_COMPAT", "W" , "SH_DENYRD", "R" , "DENY"), - ("SH_COMPAT", "W" , "SH_DENYRD", "W" , "DENY"), - ("SH_COMPAT", "W" , "SH_DENYRD", "RW", "DENY"), - ("SH_COMPAT", "W" , "SH_DENYNO", "R" , "DENY"), - ("SH_COMPAT", "W" , "SH_DENYNO", "W" , "DENY"), - ("SH_COMPAT", "W" , "SH_DENYNO", "RW", "DENY"), - -# RW|Y Y Y N N N N N N N N N N N N - ("SH_COMPAT", "RW", "SH_COMPAT", "R" , "ALLOW"), - ("SH_COMPAT", "RW", "SH_COMPAT", "W" , "ALLOW"), - ("SH_COMPAT", "RW", "SH_COMPAT", "RW", "ALLOW"), - ("SH_COMPAT", "RW", "SH_DENYRW", "R" , "DENY"), - ("SH_COMPAT", "RW", "SH_DENYRW", "W" , "DENY"), - ("SH_COMPAT", "RW", "SH_DENYRW", "RW", "DENY"), - ("SH_COMPAT", "RW", "SH_DENYWR", "R" , "DENY"), - ("SH_COMPAT", "RW", "SH_DENYWR", "W" , "DENY"), - ("SH_COMPAT", "RW", "SH_DENYWR", "RW", "DENY"), - ("SH_COMPAT", "RW", "SH_DENYRD", "R" , "DENY"), - ("SH_COMPAT", "RW", "SH_DENYRD", "W" , "DENY"), - ("SH_COMPAT", "RW", "SH_DENYRD", "RW", "DENY"), - ("SH_COMPAT", "RW", "SH_DENYNO", "R" , "DENY"), - ("SH_COMPAT", "RW", "SH_DENYNO", "W" , "DENY"), - ("SH_COMPAT", "RW", "SH_DENYNO", "RW", "DENY"), - -# Deny R |C C C N N N N N N N N N N N N - ("SH_DENYRW", "R" , "SH_COMPAT", "R" , "INT24"), - ("SH_DENYRW", "R" , "SH_COMPAT", "W" , "INT24"), - ("SH_DENYRW", "R" , "SH_COMPAT", "RW", "INT24"), - ("SH_DENYRW", "R" , "SH_DENYRW", "R" , "DENY"), - ("SH_DENYRW", "R" , "SH_DENYRW", "W" , "DENY"), - ("SH_DENYRW", "R" , "SH_DENYRW", "RW", "DENY"), - ("SH_DENYRW", "R" , "SH_DENYWR", "R" , "DENY"), - ("SH_DENYRW", "R" , "SH_DENYWR", "W" , "DENY"), - ("SH_DENYRW", "R" , "SH_DENYWR", "RW", "DENY"), - ("SH_DENYRW", "R" , "SH_DENYRD", "R" , "DENY"), - ("SH_DENYRW", "R" , "SH_DENYRD", "W" , "DENY"), - ("SH_DENYRW", "R" , "SH_DENYRD", "RW", "DENY"), - ("SH_DENYRW", "R" , "SH_DENYNO", "R" , "DENY"), - ("SH_DENYRW", "R" , "SH_DENYNO", "W" , "DENY"), - ("SH_DENYRW", "R" , "SH_DENYNO", "RW", "DENY"), - -# All W |C C C N N N N N N N N N N N N. - ("SH_DENYRW", "W" , "SH_COMPAT", "R" , "INT24"), - ("SH_DENYRW", "W" , "SH_COMPAT", "W" , "INT24"), - ("SH_DENYRW", "W" , "SH_COMPAT", "RW", "INT24"), - ("SH_DENYRW", "W" , "SH_DENYRW", "R" , "DENY"), - ("SH_DENYRW", "W" , "SH_DENYRW", "W" , "DENY"), - ("SH_DENYRW", "W" , "SH_DENYRW", "RW", "DENY"), - ("SH_DENYRW", "W" , "SH_DENYWR", "R" , "DENY"), - ("SH_DENYRW", "W" , "SH_DENYWR", "W" , "DENY"), - ("SH_DENYRW", "W" , "SH_DENYWR", "RW", "DENY"), - ("SH_DENYRW", "W" , "SH_DENYRD", "R" , "DENY"), - ("SH_DENYRW", "W" , "SH_DENYRD", "W" , "DENY"), - ("SH_DENYRW", "W" , "SH_DENYRD", "RW", "DENY"), - ("SH_DENYRW", "W" , "SH_DENYNO", "R" , "DENY"), - ("SH_DENYRW", "W" , "SH_DENYNO", "W" , "DENY"), - ("SH_DENYRW", "W" , "SH_DENYNO", "RW", "DENY"), - -# RW|C C C N N N N N N N N N N N N - ("SH_DENYRW", "RW", "SH_COMPAT", "R" , "INT24"), - ("SH_DENYRW", "RW", "SH_COMPAT", "W" , "INT24"), - ("SH_DENYRW", "RW", "SH_COMPAT", "RW", "INT24"), - ("SH_DENYRW", "RW", "SH_DENYRW", "R" , "DENY"), - ("SH_DENYRW", "RW", "SH_DENYRW", "W" , "DENY"), - ("SH_DENYRW", "RW", "SH_DENYRW", "RW", "DENY"), - ("SH_DENYRW", "RW", "SH_DENYWR", "R" , "DENY"), - ("SH_DENYRW", "RW", "SH_DENYWR", "W" , "DENY"), - ("SH_DENYRW", "RW", "SH_DENYWR", "RW", "DENY"), - ("SH_DENYRW", "RW", "SH_DENYRD", "R" , "DENY"), - ("SH_DENYRW", "RW", "SH_DENYRD", "W" , "DENY"), - ("SH_DENYRW", "RW", "SH_DENYRD", "RW", "DENY"), - ("SH_DENYRW", "RW", "SH_DENYNO", "R" , "DENY"), - ("SH_DENYRW", "RW", "SH_DENYNO", "W" , "DENY"), - ("SH_DENYRW", "RW", "SH_DENYNO", "RW", "DENY"), - -# Deny R |2 C C N N N Y N N N N N Y N N - ("SH_DENYWR", "R" , "SH_COMPAT", "R" , "ALLOW"), # File RO success, W fails INT24. For MS-DOS-7: always success. - ("SH_DENYWR", "R" , "SH_COMPAT", "W" , "INT24"), - ("SH_DENYWR", "R" , "SH_COMPAT", "RW", "INT24"), - ("SH_DENYWR", "R" , "SH_DENYRW", "R" , "DENY"), - ("SH_DENYWR", "R" , "SH_DENYRW", "W" , "DENY"), - ("SH_DENYWR", "R" , "SH_DENYRW", "RW", "DENY"), - ("SH_DENYWR", "R" , "SH_DENYWR", "R" , "ALLOW"), - ("SH_DENYWR", "R" , "SH_DENYWR", "W" , "DENY"), - ("SH_DENYWR", "R" , "SH_DENYWR", "RW", "DENY"), - ("SH_DENYWR", "R" , "SH_DENYRD", "R" , "DENY"), - ("SH_DENYWR", "R" , "SH_DENYRD", "W" , "DENY"), - ("SH_DENYWR", "R" , "SH_DENYRD", "RW", "DENY"), - ("SH_DENYWR", "R" , "SH_DENYNO", "R" , "ALLOW"), - ("SH_DENYWR", "R" , "SH_DENYNO", "W" , "DENY"), - ("SH_DENYWR", "R" , "SH_DENYNO", "RW", "DENY"), - -# Write W |C C C N N N N N N Y N N Y N N. - ("SH_DENYWR", "W" , "SH_COMPAT", "R" , "INT24"), - ("SH_DENYWR", "W" , "SH_COMPAT", "W" , "INT24"), - ("SH_DENYWR", "W" , "SH_COMPAT", "RW", "INT24"), - ("SH_DENYWR", "W" , "SH_DENYRW", "R" , "DENY"), - ("SH_DENYWR", "W" , "SH_DENYRW", "W" , "DENY"), - ("SH_DENYWR", "W" , "SH_DENYRW", "RW", "DENY"), - ("SH_DENYWR", "W" , "SH_DENYWR", "R" , "DENY"), - ("SH_DENYWR", "W" , "SH_DENYWR", "W" , "DENY"), - ("SH_DENYWR", "W" , "SH_DENYWR", "RW", "DENY"), - ("SH_DENYWR", "W" , "SH_DENYRD", "R" , "ALLOW"), - ("SH_DENYWR", "W" , "SH_DENYRD", "W" , "DENY"), - ("SH_DENYWR", "W" , "SH_DENYRD", "RW", "DENY"), - ("SH_DENYWR", "W" , "SH_DENYNO", "R" , "ALLOW"), - ("SH_DENYWR", "W" , "SH_DENYNO", "W" , "DENY"), - ("SH_DENYWR", "W" , "SH_DENYNO", "RW", "DENY"), - -# RW|C C C N N N N N N N N N Y N N - ("SH_DENYWR", "RW", "SH_COMPAT", "R" , "INT24"), - ("SH_DENYWR", "RW", "SH_COMPAT", "W" , "INT24"), - ("SH_DENYWR", "RW", "SH_COMPAT", "RW", "INT24"), - ("SH_DENYWR", "RW", "SH_DENYRW", "R" , "DENY"), - ("SH_DENYWR", "RW", "SH_DENYRW", "W" , "DENY"), - ("SH_DENYWR", "RW", "SH_DENYRW", "RW", "DENY"), - ("SH_DENYWR", "RW", "SH_DENYWR", "R" , "DENY"), - ("SH_DENYWR", "RW", "SH_DENYWR", "W" , "DENY"), - ("SH_DENYWR", "RW", "SH_DENYWR", "RW", "DENY"), - ("SH_DENYWR", "RW", "SH_DENYRD", "R" , "DENY"), - ("SH_DENYWR", "RW", "SH_DENYRD", "W" , "DENY"), - ("SH_DENYWR", "RW", "SH_DENYRD", "RW", "DENY"), - ("SH_DENYWR", "RW", "SH_DENYNO", "R" , "ALLOW"), - ("SH_DENYWR", "RW", "SH_DENYNO", "W" , "DENY"), - ("SH_DENYWR", "RW", "SH_DENYNO", "RW", "DENY"), - -# Deny R |C C C N N N N Y N N N N N Y N - ("SH_DENYRD", "R" , "SH_COMPAT", "R" , "INT24"), - ("SH_DENYRD", "R" , "SH_COMPAT", "W" , "INT24"), - ("SH_DENYRD", "R" , "SH_COMPAT", "RW", "INT24"), - ("SH_DENYRD", "R" , "SH_DENYRW", "R" , "DENY"), - ("SH_DENYRD", "R" , "SH_DENYRW", "W" , "DENY"), - ("SH_DENYRD", "R" , "SH_DENYRW", "RW", "DENY"), - ("SH_DENYRD", "R" , "SH_DENYWR", "R" , "DENY"), - ("SH_DENYRD", "R" , "SH_DENYWR", "W" , "ALLOW"), - ("SH_DENYRD", "R" , "SH_DENYWR", "RW", "DENY"), - ("SH_DENYRD", "R" , "SH_DENYRD", "R" , "DENY"), - ("SH_DENYRD", "R" , "SH_DENYRD", "W" , "DENY"), - ("SH_DENYRD", "R" , "SH_DENYRD", "RW", "DENY"), - ("SH_DENYRD", "R" , "SH_DENYNO", "R" , "DENY"), - ("SH_DENYRD", "R" , "SH_DENYNO", "W" , "ALLOW"), - ("SH_DENYRD", "R" , "SH_DENYNO", "RW", "DENY"), - -# Read W |C C C N N N N N N N Y N N Y N. - ("SH_DENYRD", "W" , "SH_COMPAT", "R" , "INT24"), - ("SH_DENYRD", "W" , "SH_COMPAT", "W" , "INT24"), - ("SH_DENYRD", "W" , "SH_COMPAT", "RW", "INT24"), - ("SH_DENYRD", "W" , "SH_DENYRW", "R" , "DENY"), - ("SH_DENYRD", "W" , "SH_DENYRW", "W" , "DENY"), - ("SH_DENYRD", "W" , "SH_DENYRW", "RW", "DENY"), - ("SH_DENYRD", "W" , "SH_DENYWR", "R" , "DENY"), - ("SH_DENYRD", "W" , "SH_DENYWR", "W" , "DENY"), - ("SH_DENYRD", "W" , "SH_DENYWR", "RW", "DENY"), - ("SH_DENYRD", "W" , "SH_DENYRD", "R" , "DENY"), - ("SH_DENYRD", "W" , "SH_DENYRD", "W" , "ALLOW"), - ("SH_DENYRD", "W" , "SH_DENYRD", "RW", "DENY"), - ("SH_DENYRD", "W" , "SH_DENYNO", "R" , "DENY"), - ("SH_DENYRD", "W" , "SH_DENYNO", "W" , "ALLOW"), - ("SH_DENYRD", "W" , "SH_DENYNO", "RW", "DENY"), - -# RW|C C C N N N N N N N N N N Y N - ("SH_DENYRD", "RW", "SH_COMPAT", "R" , "INT24"), - ("SH_DENYRD", "RW", "SH_COMPAT", "W" , "INT24"), - ("SH_DENYRD", "RW", "SH_COMPAT", "RW", "INT24"), - ("SH_DENYRD", "RW", "SH_DENYRW", "R" , "DENY"), - ("SH_DENYRD", "RW", "SH_DENYRW", "W" , "DENY"), - ("SH_DENYRD", "RW", "SH_DENYRW", "RW", "DENY"), - ("SH_DENYRD", "RW", "SH_DENYWR", "R" , "DENY"), - ("SH_DENYRD", "RW", "SH_DENYWR", "W" , "DENY"), - ("SH_DENYRD", "RW", "SH_DENYWR", "RW", "DENY"), - ("SH_DENYRD", "RW", "SH_DENYRD", "R" , "DENY"), - ("SH_DENYRD", "RW", "SH_DENYRD", "W" , "DENY"), - ("SH_DENYRD", "RW", "SH_DENYRD", "RW", "DENY"), - ("SH_DENYRD", "RW", "SH_DENYNO", "R" , "DENY"), - ("SH_DENYRD", "RW", "SH_DENYNO", "W" , "ALLOW"), - ("SH_DENYRD", "RW", "SH_DENYNO", "RW", "DENY"), - -# Deny R |2 C C N N N Y Y Y N N N Y Y Y - ("SH_DENYNO", "R" , "SH_COMPAT", "R" , "ALLOW"), # File RO success, W fails INT24. For MS-DOS-7: always success. - ("SH_DENYNO", "R" , "SH_COMPAT", "W" , "INT24"), - ("SH_DENYNO", "R" , "SH_COMPAT", "RW", "INT24"), - ("SH_DENYNO", "R" , "SH_DENYRW", "R" , "DENY"), - ("SH_DENYNO", "R" , "SH_DENYRW", "W" , "DENY"), - ("SH_DENYNO", "R" , "SH_DENYRW", "RW", "DENY"), - ("SH_DENYNO", "R" , "SH_DENYWR", "R" , "ALLOW"), - ("SH_DENYNO", "R" , "SH_DENYWR", "W" , "ALLOW"), - ("SH_DENYNO", "R" , "SH_DENYWR", "RW", "ALLOW"), - ("SH_DENYNO", "R" , "SH_DENYRD", "R" , "DENY"), - ("SH_DENYNO", "R" , "SH_DENYRD", "W" , "DENY"), - ("SH_DENYNO", "R" , "SH_DENYRD", "RW", "DENY"), - ("SH_DENYNO", "R" , "SH_DENYNO", "R" , "ALLOW"), - ("SH_DENYNO", "R" , "SH_DENYNO", "W" , "ALLOW"), - ("SH_DENYNO", "R" , "SH_DENYNO", "RW", "ALLOW"), - -# None W |C C C N N N N N N Y Y Y Y Y Y. - ("SH_DENYNO", "W" , "SH_COMPAT", "R" , "INT24"), - ("SH_DENYNO", "W" , "SH_COMPAT", "W" , "INT24"), - ("SH_DENYNO", "W" , "SH_COMPAT", "RW", "INT24"), - ("SH_DENYNO", "W" , "SH_DENYRW", "R" , "DENY"), - ("SH_DENYNO", "W" , "SH_DENYRW", "W" , "DENY"), - ("SH_DENYNO", "W" , "SH_DENYRW", "RW", "DENY"), - ("SH_DENYNO", "W" , "SH_DENYWR", "R" , "DENY"), - ("SH_DENYNO", "W" , "SH_DENYWR", "W" , "DENY"), - ("SH_DENYNO", "W" , "SH_DENYWR", "RW", "DENY"), - ("SH_DENYNO", "W" , "SH_DENYRD", "R" , "ALLOW"), - ("SH_DENYNO", "W" , "SH_DENYRD", "W" , "ALLOW"), - ("SH_DENYNO", "W" , "SH_DENYRD", "RW", "ALLOW"), - ("SH_DENYNO", "W" , "SH_DENYNO", "R" , "ALLOW"), - ("SH_DENYNO", "W" , "SH_DENYNO", "W" , "ALLOW"), - ("SH_DENYNO", "W" , "SH_DENYNO", "RW", "ALLOW"), - -# RW|C C C N N N N N N N N N Y Y Y - ("SH_DENYNO", "RW", "SH_COMPAT", "R" , "INT24"), - ("SH_DENYNO", "RW", "SH_COMPAT", "W" , "INT24"), - ("SH_DENYNO", "RW", "SH_COMPAT", "RW", "INT24"), - ("SH_DENYNO", "RW", "SH_DENYRW", "R" , "DENY"), - ("SH_DENYNO", "RW", "SH_DENYRW", "W" , "DENY"), - ("SH_DENYNO", "RW", "SH_DENYRW", "RW", "DENY"), - ("SH_DENYNO", "RW", "SH_DENYWR", "R" , "DENY"), - ("SH_DENYNO", "RW", "SH_DENYWR", "W" , "DENY"), - ("SH_DENYNO", "RW", "SH_DENYWR", "RW", "DENY"), - ("SH_DENYNO", "RW", "SH_DENYRD", "R" , "DENY"), - ("SH_DENYNO", "RW", "SH_DENYRD", "W" , "DENY"), - ("SH_DENYNO", "RW", "SH_DENYRD", "RW", "DENY"), - ("SH_DENYNO", "RW", "SH_DENYNO", "R" , "ALLOW"), - ("SH_DENYNO", "RW", "SH_DENYNO", "W" , "ALLOW"), - ("SH_DENYNO", "RW", "SH_DENYNO", "RW", "ALLOW"), -) - def _check_single_result(self, results, t): m = re.search("FAIL:\('%s', '%s', '%s', '%s', '%s'\)\[.*\]" % t, results) if m: self.fail(msg=m.group(0)) - def ds3_share_open_twice(self, fstype): - if 'FDPP' in self.version or fstype == 'MFS': - tests = OPEN_HYBRID - else: - tests = OPEN_622 - - results = _run_all(self, fstype, tests) - for t in tests: + results = _run_all(self, fstype, OPENTESTS) + for t in OPENTESTS: with self.subTest(t=t): _check_single_result(self, results, t) self.assertIn("rem tests complete", results) diff --git a/test/func_label_create.py b/test/func_label_create.py deleted file mode 100644 index 27b92b1..0000000 --- a/test/func_label_create.py +++ /dev/null @@ -1,676 +0,0 @@ -# Note label setting is currently disabled on MFS - -from subprocess import check_output, STDOUT - -from common_framework import IMAGEDIR - - -def label_create(self, fstype, itype): - testdir = self.mkworkdir('d') - - name = 'sentinel' - preop = '' - postop = '' - fat = '12' - if itype is None or itype == 'bpb12': - pass - elif itype == 'bpb16': - fat = '16' - elif itype == 'bpb32': - fat = '32' - elif itype == 'prefile': - preop += 'echo a >> %s' % name - elif itype == 'predir': - preop += 'mkdir %s' % name - elif itype == 'postfile': - postop += 'echo a >> %s' % name - elif itype == 'postdir': - postop += 'mkdir %s' % name - else: - raise ValueError - - if fstype == "MFS": - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 dXXXXs/d:hdtype1 +1" -$_floppy_a = "" -""" - else: # FAT - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 %s:partition +1" -$_floppy_a = "" -""" % self.mkimage_vbr(fat, cwd=testdir) - - self.mkfile("testit.bat", """\ -d: -%s -c:\\labcreat -%s -DIR -rem end -""" % (preop, postop), newline="\r\n") - - self.mkcom_with_ia16("labcreat", r""" - -#include -#include -#include - -struct { - uint8_t sig; - uint8_t pad[5]; - uint8_t attr; - struct _fcb x; - /* - char _fcb_drive; - char _fcb_name[8]; - char _fcb_ext[3]; - short _fcb_curblk; - short _fcb_recsize; - long _fcb_filsize; - short _fcb_date; - char _fcb_resv[10]; - char _fcb_currec; - long _fcb_random; - */ -} __attribute__((packed)) xfcb; - - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - - xfcb.sig = 0xff; - xfcb.attr = _A_VOLID; - xfcb.x._fcb_drive = 0; - - memcpy(xfcb.x._fcb_name, "????????", 8); // delete - memcpy(xfcb.x._fcb_ext, "???", 3); - r.x.ax = 0x1300; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - /* don't check result, there might not be anything to delete */ - - memcpy(xfcb.x._fcb_name, "%s", 8); // create - memcpy(xfcb.x._fcb_ext, " ", 3); - r.x.ax = 0x1600; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On creation\n"); - return 1; - } - - r.x.ax = 0x1000; // close - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On close\n"); - return 1; - } - - printf("PASS: Operation success\n"); - return 0; -} - -""" % name) - - results = self.runDosemu("testit.bat", config=config) - - self.assertIn("PASS: Operation success", results) - self.assertRegex(results, "Volume in drive [Dd] is %s" % name.upper()) - - if itype in ['prefile', 'postfile']: - # 2022-09-03 12:59 4 SENTINEL - # SENTINEL 4 09-03-22 1:00p - # SENTINEL 4 9-03-22 1:01p - # SENTINEL 4 9-03-22 11:01 - self.assertRegex(results.upper(), - r"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}\s+4\s+%s" - r"|" - r"%s\s+4\s+\d{1,2}-\d{1,2}-\d{2}\s+\d+:\d+[AaPp]?" % - (name.upper(), name.upper())) - elif itype in ['predir', 'postdir']: - # 2019-06-27 11:29 DOSEMU - # DOSEMU 06-27-19 5:33p - # TESTB 8-17-20 2:03p - # TESTB 8-17-20 12:03 - self.assertRegex(results.upper(), - r"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}\s\s+%s" - r"|" - r"%s\s+\s+\d{1,2}-\d{1,2}-\d{2}\s+\d+:\d+[AaPp]?" % - (name.upper(), name.upper())) - elif itype in ['bpb12', 'bpb16', 'bpb32']: - fat = itype[3:5] - img = self.topdir / IMAGEDIR / ("fat%s.img" % fat) - data = img.read_bytes() - if data[0x26] == 0x29: # v4 BPB - v1 = 0x2b - v2 = v1 + len(name) - self.assertEqual(data[v1:v2], bytes(name.upper(), encoding='ascii')) - elif data[0x42] == 0x29: # v7.1 BPB - v1 = 0x47 - v2 = v1 + len(name) - self.assertEqual(data[v1:v2], bytes(name.upper(), encoding='ascii')) - else: - self.fail("No BPB signature found") - - -def label_create_noduplicate(self, fstype): - testdir = self.mkworkdir('d') - - if fstype == "MFS": - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 dXXXXs/d:hdtype1 +1" -$_floppy_a = "" -""" - else: # FAT - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 %s:partition +1" -$_floppy_a = "" -""" % self.mkimage_vbr("12", cwd=testdir) - - self.mkfile("testit.bat", """\ -d: -c:\\labdupli -DIR -rem end -""", newline="\r\n") - - self.mkcom_with_ia16("labdupli", r""" - -#include -#include -#include - -struct { - uint8_t sig; - uint8_t pad[5]; - uint8_t attr; - struct _fcb x; - /* - char _fcb_drive; - char _fcb_name[8]; - char _fcb_ext[3]; - short _fcb_curblk; - short _fcb_recsize; - long _fcb_filsize; - short _fcb_date; - char _fcb_resv[10]; - char _fcb_currec; - long _fcb_random; - */ -} __attribute__((packed)) xfcb; - - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - - xfcb.sig = 0xff; - xfcb.attr = _A_VOLID; - xfcb.x._fcb_drive = 0; - - memcpy(xfcb.x._fcb_name, "????????", 8); // delete - memcpy(xfcb.x._fcb_ext, "???", 3); - r.x.ax = 0x1300; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - /* don't check result, there might not be anything to delete */ - - memcpy(xfcb.x._fcb_name, "INITIAL ", 8); // create - memcpy(xfcb.x._fcb_ext, " ", 3); - r.x.ax = 0x1600; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On initial creation\n"); - return 1; - } - - r.x.ax = 0x1000; // close - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On initial close\n"); - return 1; - } - - memcpy(xfcb.x._fcb_name, "DUPLICAT", 8); // create duplicate - memcpy(xfcb.x._fcb_ext, " ", 3); - r.x.ax = 0x1600; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al == 0) { - printf("FAIL: Allowed duplicate creation\n"); - r.x.ax = 0x1000; // close - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - /* don't check result, there's nothing we can do about it. */ - return 1; - } else { - printf("INFO: Denied duplicate creation (0x%02x)\n", r.h.al); - } - - printf("PASS: Operation success\n"); - return 0; -} - -""") - - results = self.runDosemu("testit.bat", config=config) - - self.assertIn("PASS: Operation success", results) - self.assertRegex(results, "Volume in drive [Dd] is INITIAL") - self.assertIn("INFO: Denied duplicate creation (0xff)", results) - -def label_create_nonrootdir(self, fstype): - testdir = self.mkworkdir('d') - - if fstype == "MFS": - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 dXXXXs/d:hdtype1 +1" -$_floppy_a = "" -""" - else: # FAT - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 %s:partition +1" -$_floppy_a = "" -""" % self.mkimage_vbr("12", cwd=testdir) - - self.mkfile("testit.bat", """\ -d: -cd \\ -mkdir x -cd x -c:\\labnonrt -DIR -rem end -""", newline="\r\n") - - self.mkcom_with_ia16("labnonrt", r""" - -#include -#include -#include - -struct { - uint8_t sig; - uint8_t pad[5]; - uint8_t attr; - struct _fcb x; - /* - char _fcb_drive; - char _fcb_name[8]; - char _fcb_ext[3]; - short _fcb_curblk; - short _fcb_recsize; - long _fcb_filsize; - short _fcb_date; - char _fcb_resv[10]; - char _fcb_currec; - long _fcb_random; - */ -} __attribute__((packed)) xfcb; - - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - - xfcb.sig = 0xff; - xfcb.attr = _A_VOLID; - xfcb.x._fcb_drive = 0; - - memcpy(xfcb.x._fcb_name, "TEST LAB", 8); // create in non root - memcpy(xfcb.x._fcb_ext, "EL1", 3); - r.x.ax = 0x1600; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al == 0) { - printf("INFO: Allowed non root creation\n"); - r.x.ax = 0x1000; // close - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - /* don't check result, there's nothing we can do about it. */ - } else { - printf("FAIL: Denied non root creation (0x%02x)\n", r.h.al); - return 1; - } - - printf("PASS: Operation success\n"); - return 0; -} - -""") - - results = self.runDosemu("testit.bat", config=config) - - self.assertIn("PASS: Operation success", results) - self.assertRegex(results, "Volume in drive [Dd] is TEST LABEL1") - self.assertNotIn("FAIL: Denied non root creation", results) - - -def label_delete_wildcard(self, fstype): - testdir = self.mkworkdir('d') - - if fstype == "MFS": - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 dXXXXs/d:hdtype1 +1" -$_floppy_a = "" -""" - else: # FAT - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 %s:partition +1" -$_floppy_a = "" -""" % self.mkimage_vbr("12", cwd=testdir) - - self.mkfile("testit.bat", """\ -d: -c:\\labdelw -DIR -rem end -""", newline="\r\n") - - self.mkcom_with_ia16("labdelw", r""" - -#include -#include -#include - -struct { - uint8_t sig; - uint8_t pad[5]; - uint8_t attr; - struct _fcb x; - /* - char _fcb_drive; - char _fcb_name[8]; - char _fcb_ext[3]; - short _fcb_curblk; - short _fcb_recsize; - long _fcb_filsize; - short _fcb_date; - char _fcb_resv[10]; - char _fcb_currec; - long _fcb_random; - */ -} __attribute__((packed)) xfcb; - - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - - xfcb.sig = 0xff; - xfcb.attr = _A_VOLID; - xfcb.x._fcb_drive = 0; - - memcpy(xfcb.x._fcb_name, "????????", 8); // delete - memcpy(xfcb.x._fcb_ext, "???", 3); - r.x.ax = 0x1300; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - /* don't check result, there might not be anything to delete */ - - memcpy(xfcb.x._fcb_name, "INITIAL ", 8); // create - memcpy(xfcb.x._fcb_ext, " ", 3); - r.x.ax = 0x1600; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On initial creation\n"); - return 1; - } - - r.x.ax = 0x1000; // close - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On initial close\n"); - return 1; - } - - memcpy(xfcb.x._fcb_name, "????????", 8); // delete with wildcard - memcpy(xfcb.x._fcb_ext, "???", 3); - r.x.ax = 0x1300; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On delete with wildcard\n"); - return 1; - } - - printf("PASS: Operation success\n"); - return 0; -} - -""") - - results = self.runDosemu("testit.bat", config=config) - - self.assertIn("PASS: Operation success", results) - self.assertRegex(results, "Volume.*(has no|does not have a) label") - self.assertNotIn("FAIL:", results) - - -def label_delete_recreate(self, fstype): - testdir = self.mkworkdir('d') - - if fstype == "MFS": - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 dXXXXs/d:hdtype1 +1" -$_floppy_a = "" -""" - else: # FAT - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 %s:partition +1" -$_floppy_a = "" -""" % self.mkimage_vbr("12", cwd=testdir) - - self.mkfile("testit.bat", """\ -d: -c:\\labdelr -DIR -rem end -""", newline="\r\n") - - self.mkcom_with_ia16("labdelr", r""" - -#include -#include -#include - -struct { - uint8_t sig; - uint8_t pad[5]; - uint8_t attr; - struct _fcb x; - /* - char _fcb_drive; - char _fcb_name[8]; - char _fcb_ext[3]; - short _fcb_curblk; - short _fcb_recsize; - long _fcb_filsize; - short _fcb_date; - char _fcb_resv[10]; - char _fcb_currec; - long _fcb_random; - */ -} __attribute__((packed)) xfcb; - - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - - xfcb.sig = 0xff; - xfcb.attr = _A_VOLID; - xfcb.x._fcb_drive = 0; - - /* it's very important that the disk has never had a label before */ - - memcpy(xfcb.x._fcb_name, "INITIAL ", 8); // create - memcpy(xfcb.x._fcb_ext, " ", 3); - r.x.ax = 0x1600; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On initial creation\n"); - return 1; - } - - r.x.ax = 0x1000; // close - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On initial close\n"); - return 1; - } - - memcpy(xfcb.x._fcb_name, "????????", 8); // delete with wildcard - memcpy(xfcb.x._fcb_ext, "???", 3); - r.x.ax = 0x1300; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On delete with wildcard\n"); - return 1; - } - - memcpy(xfcb.x._fcb_name, "RECREATI", 8); // recreation - memcpy(xfcb.x._fcb_ext, "ON ", 3); - r.x.ax = 0x1600; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On recreation\n"); - return 1; - } - - printf("PASS: Operation success\n"); - return 0; -} - -""") - - results = self.runDosemu("testit.bat", config=config) - - self.assertIn("PASS: Operation success", results) - self.assertRegex(results, "Volume in drive [Dd] is RECREATION") - self.assertNotIn("FAIL:", results) - - -def label_create_on_lfns(self): - testdir = self.mkworkdir('d') - - names = [ - "This Is A Long Filename.tXt", - "simple_but_long_filename.txt", - ] - for n in names: - f2 = testdir / n - f2.write_text("HELLO THERE\n") - n3 = "LFNdirectory" - f3 = testdir / n3 - f3.mkdir() - names += [n3,] - - image = self.mkimage_vbr("12", lfn=True, cwd=testdir) - config = """\ -$_hdimage = "dXXXXs/c:hdtype1 %s:partition +1" -$_floppy_a = "" -""" % image - - self.mkfile("testit.bat", """\ -d: -c:\\labclfns -rem end -""", newline="\r\n") - - self.mkcom_with_ia16("labclfns", r""" - -#include -#include -#include - -struct { - uint8_t sig; - uint8_t pad[5]; - uint8_t attr; - struct _fcb x; - /* - char _fcb_drive; - char _fcb_name[8]; - char _fcb_ext[3]; - short _fcb_curblk; - short _fcb_recsize; - long _fcb_filsize; - short _fcb_date; - char _fcb_resv[10]; - char _fcb_currec; - long _fcb_random; - */ -} __attribute__((packed)) xfcb; - - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - - xfcb.sig = 0xff; - xfcb.attr = _A_VOLID; - xfcb.x._fcb_drive = 0; - - /* It's very important that the disk has no existing label */ - - /* We shouldn't error if the volume has any LFNs */ - memcpy(xfcb.x._fcb_name, "INITIAL ", 8); // create - memcpy(xfcb.x._fcb_ext, " ", 3); - r.x.ax = 0x1600; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On initial creation\n"); - return 1; - } - - r.x.ax = 0x1000; // close - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On initial close\n"); - return 1; - } - - printf("INFO: Label was created successfully\n"); - - /* We should be able to delete the label without affecting the LFNs */ - memcpy(xfcb.x._fcb_name, "????????", 8); // delete with wildcard - memcpy(xfcb.x._fcb_ext, "???", 3); - r.x.ax = 0x1300; - r.x.dx = FP_OFF(&xfcb); - intdos(&r, &r); - if (r.h.al != 0) { - printf("FAIL: On delete with wildcard\n"); - return 1; - } - - printf("INFO: Label was deleted successfully\n"); - - printf("PASS: Operation success\n"); - return 0; -} - -""") - - results = self.runDosemu("testit.bat", config=config) - - self.assertIn("PASS: Operation success", results) - self.assertNotIn("FAIL:", results) - - # Check afterwards with mtools that each lfn still exists - args = ['mdir', '-i', str(self.imagedir / image)] - output = check_output(args, timeout=5, stderr=STDOUT).decode('ASCII') - for n in names: - self.assertIn(n, output) diff --git a/test/func_lfn_voln_info.py b/test/func_lfn_voln_info.py deleted file mode 100644 index 64a5cb8..0000000 --- a/test/func_lfn_voln_info.py +++ /dev/null @@ -1,75 +0,0 @@ - -def lfn_voln_info(self, fstype): - - testdir = self.mkworkdir('d') - self.mkfile("foo.dat", "some content", dname=testdir) - - if fstype == "FAT16": - name = self.mkimage_vbr("16", cwd=testdir) - config = """$_hdimage = "dXXXXs/c:hdtype1 %s +1"\n""" % name - elif fstype == "FAT32": - name = self.mkimage_vbr("32", cwd=testdir) - config = """$_hdimage = "dXXXXs/c:hdtype1 %s +1"\n""" % name - elif fstype == "MFS": - config = """$_hdimage = "dXXXXs/c:hdtype1 dXXXXs/d +1"\n""" - else: - raise ValueError - - self.unTarOrSkip("TEST_DOSLFN.tar", [ - ("doslfn.com", "6fec9451489d81b16253a5340afdb955aa6136fb"), - ("cp437uni.tbl", "4b2c5f7ef008e6826a75035822b65c5bb72e2ffe"), - ("cp858uni.tbl", "4dc79f9b2e8d8f57187e94169eb9b7c79b32bb31"), - ("cp866uni.tbl", "28d4dc1b9197fb03af9382674c3fa3321c0608b5"), - ]) - - self.mkfile("testit.bat", """\ -c:\\doslfn -f- -d: -c:\\lfnvinfo D:\\ -rem end -""", newline="\r\n") - - # compile sources - self.mkexe_with_djgpp("lfnvinfo", r""" -#include -#include -#include -#include -#include -#include - -int main(int argc, char *argv[]) { - int max_file_len, max_path_len; - char fsystype[32]; - unsigned rval; - - if (argc < 1) { - printf("missing volume argument e.g. 'C:\\'\n"); - return 1; - } - - rval = _get_volume_info(argv[1], &max_file_len, &max_path_len, fsystype); - if (rval == 0 && errno) { - printf("ERRNO(%d)\r\n", errno); - return 2; - } - if (rval == _FILESYS_UNKNOWN) { - printf("FILESYS_UNKNOWN(%d)\r\n", errno); - return 3; - } - - printf("FSTYPE(%s), FILELEN(%d), PATHLEN(%d), BITS(0x%04x)\r\n", - fsystype, max_file_len, max_path_len, rval); - - return 0; -} -""") - - results = self.runDosemu("testit.bat", config=config) - - if fstype == "MFS": - self.assertIn("FSTYPE(MFS)", results) - elif fstype == "FAT16": - self.assertIn("FSTYPE(FAT)", results) - elif fstype == "FAT32": - self.assertIn("FSTYPE(FAT32)", results) diff --git a/test/func_lfs_disk_info.py b/test/func_lfs_disk_info.py deleted file mode 100644 index 0a49b60..0000000 --- a/test/func_lfs_disk_info.py +++ /dev/null @@ -1,144 +0,0 @@ -import re - -from os import statvfs -from subprocess import call, DEVNULL - - -def lfs_disk_info(self, fstype): - - testdir = self.mkworkdir('d') - - if fstype == 'MFS': - config="""$_hdimage = "dXXXXs/c:hdtype1 dXXXXs/d +1"\n""" - elif fstype == 'FAT32': - # Make a big file to use some space on the image - bigfile = testdir / 'bigfile.zro' - size = 104857600 - call(["dd", "if=/dev/zero", "of=%s" % bigfile, "bs=%s" % size, "count=1"], stderr=DEVNULL) - name = self.mkimage_vbr("32", cwd=testdir) - config="""$_hdimage = "dXXXXs/c:hdtype1 %s +1"\n""" % name - else: - raise ValueError - - self.mkfile("testit.bat", """\ -d: -c:\\diskinfo D:\\ -rem end -""", newline="\r\n") - - # compile sources - self.mkexe_with_djgpp("diskinfo", r"""\ -#include -#include -#include - -struct dinfo { - uint16_t size; - uint16_t version; // (0000h) - uint32_t spc; - uint32_t bps; - uint32_t avail_clusters; - uint32_t total_clusters; - uint32_t avail_sectors; - uint32_t total_sectors; - uint32_t avail_units; - uint32_t total_units; - char reserved[8]; -}; - -#define MAXPATH 128 - -int main(int argc, char *argv[]) { - struct dinfo df; - uint8_t carry; - uint16_t ax; - int len; - - if (argc < 2) { - printf("path argument missing e.g. 'C:\\'\n"); - return 3; - } - - len = strlen(argv[1]) + 1; - if (len > MAXPATH) { - printf("path argument too long\n"); - return 2; - } - - /* - AX = 7303h - DS:DX -> ASCIZ string for drive ("C:\" or "\\SERVER\Share") - ES:DI -> buffer for extended free space structure (see #01789) - CX = length of buffer for extended free space - - Return: - CF clear if successful - ES:DI buffer filled - CF set on error - AX = error code - */ - - asm volatile("stc\n" - "int $0x21\n" - "setc %0\n" - : "=r"(carry), "=a"(ax) - : "a"(0x7303), "d"(argv[1]), "D"(&df), "c"(sizeof(df)) - : "cc", "memory"); - - if (carry) { - printf("Call failed (CARRY), AX = 0x%04x\n", ax); - return 1; - } - - /* See if we have valid data */ - if (df.size > sizeof(df)) { - printf("Call failed (Struct invalid), size = 0x%04x, version 0x%04x\n", df.size, df.version); - return 1; - } - - printf("size 0x%04x\n", df.size); - printf("version 0x%04x\n", df.version); - printf("spc 0x%08lx\n", df.spc); - printf("bps 0x%08lx\n", df.bps); - printf("avail_clusters 0x%08lx\n", df.avail_clusters); - printf("total_clusters 0x%08lx\n", df.total_clusters); - printf("avail_sectors 0x%08lx\n", df.avail_sectors); - printf("total_sectors 0x%08lx\n", df.total_sectors); - printf("avail_units 0x%08lx\n", df.avail_units); - printf("total_units 0x%08lx\n", df.total_units); - - printf("avail_bytes(%llu)\n", - (unsigned long long)df.spc * (unsigned long long)df.bps * (unsigned long long)df.avail_clusters); - printf("total_bytes(%llu)\n", - (unsigned long long)df.spc * (unsigned long long)df.bps * (unsigned long long)df.total_clusters); - return 0; -} -""") - - results = self.runDosemu("testit.bat", config=config) - - self.assertNotIn("Call failed", results) - - t = re.search(r'total_bytes\((\d+)\)', results) - self.assertIsNotNone(t, "Unable to parse 'total_bytes'") - dfs_total = int(t.group(1)) - a = re.search(r'avail_bytes\((\d+)\)', results) - self.assertIsNotNone(a, "Unable to parse 'avail_bytes'") - dfs_avail = int(a.group(1)) - - if fstype == 'MFS': - fsinfo = statvfs(self.workdir) - lfs_total = fsinfo.f_blocks * fsinfo.f_bsize - lfs_avail = fsinfo.f_bavail * fsinfo.f_bsize - else: # FAT32 - lfs_total = (self.imagedir / name).stat().st_size - lfs_avail = lfs_total - size - - # see if we are within 5% of the values expected - msg = "total dos %d, expected %d" % (dfs_total, lfs_total) - self.assertLessEqual(dfs_total, lfs_total * 1.05, msg) - self.assertGreaterEqual(dfs_total, lfs_total * 0.95, msg) - - msg = "avail dos %d, expected %d" % (dfs_avail, lfs_avail) - self.assertLessEqual(dfs_avail, lfs_avail * 1.05, msg) - self.assertGreaterEqual(dfs_avail, lfs_avail * 0.95, msg) diff --git a/test/func_lfs_file_info.py b/test/func_lfs_file_info.py index e571383..2460a63 100644 --- a/test/func_lfs_file_info.py +++ b/test/func_lfs_file_info.py @@ -131,19 +131,11 @@ $_lredir_paths = "%s" # Check the obvious fields self.assertNotIn("Error: ", results) - r1 = re.compile(r'fsize_hi.*0x([0-9a-f]+)') - self.assertRegex(results, r1) - t = r1.search(results) + t = re.search(r'fsize_hi.*0x([0-9a-f]+)', results) fsize_hi = int(t.group(1), 16) - - r2 = re.compile(r'fsize_lo.*0x([0-9a-f]+)') - self.assertRegex(results, r2) - t = r2.search(results) + t = re.search(r'fsize_lo.*0x([0-9a-f]+)', results) fsize_lo = int(t.group(1), 16) - - r3 = re.compile(r'numlinks.*0x([0-9a-f]+)') - self.assertRegex(results, r3) - t = r3.search(results) + t = re.search(r'numlinks.*0x([0-9a-f]+)', results) numlinks = int(t.group(1), 16) self.assertEqual(fsize_hi, fsize >> 32) diff --git a/test/func_libi86_testsuite.py b/test/func_libi86_testsuite.py deleted file mode 100644 index c381a11..0000000 --- a/test/func_libi86_testsuite.py +++ /dev/null @@ -1,75 +0,0 @@ - -import re - -from shutil import copy -from subprocess import check_call, check_output, CalledProcessError, DEVNULL, TimeoutExpired - - -TESTSUITE = "/usr/ia16-elf/libexec/libi86/tests/testsuite" - - -def libi86_create_items(testcase): - - # Enumerate the tests - tests = [] - try: - listing = check_output([TESTSUITE, '--list']) - except FileNotFoundError: - print('libi86-testsuite-ia16-elf not installed - skipping those\n') - return - for l in listing.split(b'\n'): - # b' 12: bios.h.at:83 _bios_equiplist' - t = re.search(r"\s*(\d+): (.+):\d+\s+([^']+)", str(l)) - if t: - tests += [t.groups(),] - - def create_test(test): - def do_test_libi86(self): - libi86_test_item(self, test[0]) - docstring = """libi86 item % 3s %s""" % (test[0], test[2]) - setattr(do_test_libi86, '__doc__', docstring) - setattr(do_test_libi86, 'libi86test', True) - return do_test_libi86 - - # Insert each test into the testcase - for test in tests: - name = 'test_libi86_item_%03d' % int(test[0]) - setattr(testcase, name, create_test(test)) - - testcase.attrs += ['libi86test',] - - -def libi86_test_item(self, test): - self.mkfile("dosemu.conf", """\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -""", dname=self.imagedir, mode="a") - - build = self.imagedir / "libi86-test" - build.mkdir() - - dosemu = self.topdir / "bin" / "dosemu" - options = '-f {0}/dosemu.conf -n --Fimagedir {0} -o {1}'.format(self.imagedir, self.logfiles['log'][0]) - args = [ - '--x-installcheck', - '--x-test-underlying', - '--x-with-dosemu=%s' % dosemu, - '--x-with-dosemu-options=%s' % options, - ] - - # Do just one - try: - starttime = self.utcnow() - check_call([TESTSUITE, *args, test[0]], cwd=build, timeout=60, stdout=DEVNULL, stderr=DEVNULL) - self.duration = self.utcnow() - starttime - except CalledProcessError: - raise self.failureException("Test error") from None - except TimeoutExpired: - raise self.failureException("Test timeout") from None - finally: - # The libi86 test suite has its own log file called 'testsuite.log', - # so we will present it as our usual expect log - logfile = build / "tests" / "testsuite.log" - if logfile.is_file(): - copy(logfile, self.logfiles['xpt'][0]) - self.logfiles['xpt'][1] = "testsuite.log" diff --git a/test/func_memory_dpmi_dpmi10_ldt.py b/test/func_memory_dpmi_dpmi10_ldt.py deleted file mode 100644 index 2251725..0000000 --- a/test/func_memory_dpmi_dpmi10_ldt.py +++ /dev/null @@ -1,159 +0,0 @@ -BATCHFILE = """\ -c:\\%s -rem end -""" - -CONFIG = """\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -""" - - -def memory_dpmi_dpmi10_ldt(self): - -# Note: Not sure if I need this - if 'FDPP' in self.version: - self.mkfile("userhook.sys", """DOS=HIGH\n""", newline="\r\n") - - self.mkfile("testit.bat", BATCHFILE % 'dpmi1ldt primary', newline="\r\n") - - self.mkexe_with_djgpp("dpmi1ldt", r""" -#include -#include -#include -#include -#include -#include -#include - -int main(int argc, char *argv[]) -{ - int i, err; - uint32_t lim; - int primary = -1; - - if (argc < 2) { - printf("FAIL: Missing argument (primary|secondary)\n"); - return -2; - } - if (strcmp(argv[1], "primary") == 0) - primary = 1; - if (strcmp(argv[1], "secondary") == 0) - primary = 0; - if (primary < 0) { - printf("FAIL: Invalid argument (primary|secondary)\n"); - return -2; - } - - if (primary) { - unsigned short sel; - char selstr[16]; - - for (i = 0; i < 0x10; i++) { - sel = (i << 3) | 7; - err = __dpmi_allocate_specific_ldt_descriptor(sel); - if (err) { - printf("FAIL: %s: cannot allocate specific desc %#x\n", argv[1], i); - return -1; - } - lim = __dpmi_get_segment_limit(sel); - if (lim) { - printf("FAIL: %s: limit of desc %#x is %lx\n", argv[1], i, lim); - return -1; - } - err = __dpmi_set_segment_limit(sel, 0xfff); - if (err) { - printf("FAIL: %s: cannot set limit for %x\n", argv[1], i); - return -1; - } - } - printf("OKAY: %s: Allocated 16 LDT descriptors\n", argv[1]); - - sel = __dpmi_allocate_ldt_descriptors(1); - if (sel == -1) { - printf("FAIL: cannot allocate LDT desc\n"); - return -1; - } - err = __dpmi_set_segment_limit(sel, 0xfff); - if (err) { - printf("FAIL: cannot set segment limit\n"); - return -1; - } - printf("OKAY: %s: Allocated descriptor at %#x\n", argv[1], sel); - sprintf(selstr, "%i", sel); - - // Now start second copy - spawnlp(P_WAIT, argv[0], argv[0], "secondary", selstr, NULL); - - for (i = 0; i < 0x10; i++) { - sel = (i << 3) | 7; - lim = __dpmi_get_segment_limit(sel); - if (lim != 0xfff) { - printf("FAIL: %s: limit of desc %#x is %lx\n", argv[1], i, lim); - return -1; - } - err = __dpmi_free_ldt_descriptor(sel); - if (err) { - printf("FAIL: %s: cannot free specific desc %#x\n", argv[1], i); - return -1; - } - } - printf("OKAY: %s: All descriptors checked and freed\n", argv[1]); - printf("Test 2 OK\n"); - - } else { // secondary - - unsigned short sel = 0; - - if (argc < 3) { - printf("FAIL: Missing argument (sel number)\n"); - return -2; - } - - sscanf(argv[2], "%hi", &sel); - if (!sel) { - printf("FAIL: %s: bad sel value %s\n", argv[1], argv[2]); - return -1; - } - lim = __dpmi_get_segment_limit(sel); - if (lim == 0) { - printf("FAIL: %s: sel %#x not allocated\n", argv[1], sel); - return -1; - } - if (lim != 0xfff) { - printf("FAIL: %s: limit of %#x is %lx\n", argv[1], sel, lim); - return -1; - } - printf("OKAY: %s: limit of %#x is %#lx\n", argv[1], sel, lim); - - for (i = 0; i < 0x10; i++) { - sel = (i << 3) | 7; - err = __dpmi_allocate_specific_ldt_descriptor(sel); - if (err) { - printf("FAIL: %s: cannot allocate specific desc %#x\n", argv[1], i); - return -1; - } - lim = __dpmi_get_segment_limit(sel); - if (lim) { - printf("FAIL: %s: limit of desc %#x is %lx\n", argv[1], i, lim); - return -1; - } - err = __dpmi_free_ldt_descriptor(sel); - if (err) { - printf("FAIL: %s: cannot free specific desc %#x\n", argv[1], i); - return -1; - } - } - printf("OKAY: %s: Allocated and freed 16 LDT descriptors\n", argv[1]); - printf("Test 1 OK\n"); - } - - return 0; -} -""") - - results = self.runDosemu("testit.bat", config=CONFIG) - - self.assertIn("Test 1 OK", results) - self.assertIn("Test 2 OK", results) - self.assertNotIn("FAILURE:", results) diff --git a/test/func_memory_dpmi_japheth.py b/test/func_memory_dpmi_japheth.py deleted file mode 100644 index ff7c1a5..0000000 --- a/test/func_memory_dpmi_japheth.py +++ /dev/null @@ -1,158 +0,0 @@ -import re - -TTAR = "TEST_JAPHETH.tar" -TFILES = { - 218: ("dpmihxrt218.exe", "65fda018f4422c39dbf36860aac2c537cfee466b"), - 219: ("dpmihxrt219.exe", "4b0f60346244a5be9e3208fe63063bd26209d234"), - 220: ("dpmihxrt220.exe", "c2a37cf9b8bab4fe911186821989fc49e6c0feb2"), # Pre2 -} - - -def doit(self, version, switch, eofisok=False): - self.unTarOrSkip(TTAR, [TFILES[version],]) - tfile = self.workdir / TFILES[version][0] - tfile.rename(self.workdir / "dpmi.exe") - - self.mkfile("testit.bat", """\ -c:\\dpmi %s -rem end -""" % switch, newline="\r\n") - - return self.runDosemu("testit.bat", config="""\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -$_dpmi = (0x40000) -""", timeout=60, eofisok=eofisok) - - -def bare(self): - results = doit(self, 218, "") - -#Cpu is in V86-mode -#Int 15h, ax=e801h, extended memory: 8256 kB -#int 15h, ax=e820h, available memory at 000100000, size 8256 kB -#XMS v3.0 host found, largest free block: 8192 kB -#No VCPI host found -#DPMI v0.90 host found, cpu: 05, support of 32-bit clients: 1 -#entry initial switch to protected-mode: F000:F500 -#size task-specific memory: 230 paragraphs -#now in protected mode, client CS/SS/DS/FS/GS: A7/AF/AF/0/0 -#Eflags=206, ES (=PSP): B7 (environment: BF, parent PSP segm: 431) -#GDTR: 17.A308100 IDTR: 7FF.A308200 LDTR: 0 TR: 0 -#DPMI version flags: 5 -#master/slave PICs base: 08/70 -#state save protected-mode: 97:1, real-mode: F000:F514 -#size state save buffer: 52 bytes -#raw jump to real-mode: 97:0, protected-mode: F000:F513 -#largest free/lockable memory block (kB): 131004/131004 -#free unlocked (=virtual) memory (kB): 131004 -#total/free address space (kB): 32768/32768 -#total/free physical memory (kB): 131072/131004 -#Coprocessor status: 4D -#vendor: DOSEMU Version 2.0, version: 0.90 -#capabilities: 78 -#vendor 'MS-DOS' API entry: 97:130 -#'MS-DOS' API, ax=100h (get LDT selector): E7 - - self.assertRegex(results, r"DPMI v\d.\d+ host found, cpu: \d+, support of 32-bit clients: 1") - self.assertRegex(results, r"DPMI version flags: 5") - self.assertRegex(results, r"vendor: DOSEMU2 Version 2.0, version: \d.\d+") - self.assertRegex(results, r"capabilities: \d+") - - -def _c(self): - results = doit(self, 218, "-c") - self.assertRegex(results, r"time.*CLI/STI: \d+ ms") - self.assertRegex(results, r"time.*interrupts via DPMI: \d+ ms") - - -def _d(self): - results = doit(self, 219, "-d") - t = re.search(r"(\d+) descriptors allocated", results) - self.assertIsNotNone(t, "Unable to parse number of allocated descriptors") - num = int(t.group(1)) - self.assertGreater(num, 8000, results) - - -def _e(self): - # Dosemu2 shuts down with stack exhaustion so we have to allow EOF - results = doit(self, 219, "-e", eofisok=True) - # We want to achieve in the future at least the current level of nesting (192) - self.assertIn('ERROR: DPMI: too many nested realmode invocations, in_dpmi_rm_stack=192', results) - - -def _i(self): - results = doit(self, 218, "-i") - self.assertRegex(results, r"time.*IN 21: \d+ ms") - - -def _m(self): - results = doit(self, 218, "-m") - t = re.search(r"alloc largest mem block \(size=(\d+) kB\) returned handle [0-9a-fA-F]+, base \d+", results) - self.assertIsNotNone(t, "Unable to parse memory block size") - size = int(t.group(1)) - self.assertGreater(size, 128000, results) - - -def _r(self): - results = doit(self, 218, "-r") - self.assertRegex(results, r"time.*INT 69h: \d+ ms") - self.assertRegex(results, r"time.*INT 31h, AX=0300h \(Sim INT 69h\): \d+ ms") - self.assertRegex(results, r"time.*real-mode callback: \d+ ms") - self.assertRegex(results, r"time.*raw mode switches PM->RM->PM: \d+ ms") - - -def _t(self): - results = doit(self, 218, "-t") - -#C:\>c:\dpmi -t -#allocated rm callback FF10:214, rmcs=AF:20E4 -#calling rm proc [53A:8B6], rm cx=1 -# inside rm proc, ss:sp=7A8:1FC, cx=1 -# calling rm callback FF10:214 -# inside rm callback, ss:esp=9F:EFF4, ds:esi=F7:1FC -# es:edi=AF:20E4, rm ss:sp=7A8:1FC, rm cx=1 -# calling rm proc [53A:8B6] -# inside rm proc, ss:sp=7A8:1F8, cx=2 -# calling rm callback FF10:214 -# inside rm callback, ss:esp=9F:EFE0, ds:esi=F7:1F8 -# es:edi=AF:20E4, rm ss:sp=7A8:1F8, rm cx=2 -# exiting -# back in rm proc, ss:sp=7A8:1F8; exiting -# back in rm callback, rm ss:sp=7A8:1FC, rm cx=2; exiting -# back in rm proc, ss:sp=7A8:1FC; exiting -#back in protected-mode, rm ss:sp=7A8:200, rm cx=2 - - self.assertRegex(results, re.compile(r"^allocated rm callback", re.MULTILINE)) - self.assertRegex(results, re.compile(r"^ inside rm proc", re.MULTILINE)) - self.assertRegex(results, re.compile(r"^ inside rm callback", re.MULTILINE)) - self.assertRegex(results, re.compile(r"^ inside rm proc", re.MULTILINE)) - self.assertRegex(results, re.compile(r"^ inside rm callback", re.MULTILINE)) - self.assertRegex(results, re.compile(r"^ back in rm proc", re.MULTILINE)) - self.assertRegex(results, re.compile(r"^ back in rm callback", re.MULTILINE)) - self.assertRegex(results, re.compile(r"^ back in rm proc", re.MULTILINE)) - self.assertRegex(results, re.compile(r"^back in protected-mode", re.MULTILINE)) - - -def _z(self): - results = doit(self, 220, "-z") - - t = re.search(r"DPMI: launch succeeded, int 21h calls: (\d+)", results) - self.assertIsNotNone(t, "Unable to parse number of int 21h calls") - num = int(t.group(1)) - self.assertGreater(num, 800, results) - - -def memory_dpmi_japheth(self, switch): - f = { - '': bare, - '-c': _c, - '-d': _d, - '-e': _e, - '-i': _i, - '-m': _m, - '-r': _r, - '-t': _t, - '-z': _z, - } - f[switch](self) diff --git a/test/func_memory_dpmi_leak_check.py b/test/func_memory_dpmi_leak_check.py deleted file mode 100644 index d3e12f9..0000000 --- a/test/func_memory_dpmi_leak_check.py +++ /dev/null @@ -1,89 +0,0 @@ -import re - - -def memory_dpmi_leak_check(self, tipo): - - self.mkfile("testit.bat", """\ -c:\\dpmileak TEST0 {0} -c:\\dpmileak TEST1 {0} -c:\\dpmileak TEST2 {0} -c:\\dpmileak TEST3 {0} -c:\\dpmileak TEST4 {0} -c:\\dpmileak TEST5 {0} -c:\\dpmileak TEST6 {0} -c:\\dpmileak TEST7 {0} -c:\\dpmileak TEST8 {0} -c:\\dpmileak TEST9 {0} -rem end -""".format(tipo), newline="\r\n") - - self.mkexe_with_djgpp("dpmileak", r""" -#include -#include -#include -#include -#include -#include -#include - -int main(int argc, char *argv[]) -{ - - __dpmi_meminfo info = {}; - int dofree = 1; - - if (argc < 2) { - printf("FAIL: Missing argument IDSTRING (normal|nofree)\n"); - return -2; - } - - if (argc > 2 && strcmp(argv[2], "nofree") == 0) - dofree = 0; - - info.size = 0x20000; - - if (__dpmi_allocate_memory(&info) == -1) { - printf("FAIL: (%s) DPMI allocation failed\n", argv[1]); - return -1; - } - - printf("INFO: (%s) DPMI allocation info: HNDL=%08lx, SIZE=%08lx, ADDR=%08lx\n", - argv[1], info.handle, info.size, info.address); - - if (dofree) { - if (__dpmi_free_memory(info.handle) == -1) { - printf("FAIL: (%s) DPMI free failed\n", argv[1]); - return -1; - } - printf("INFO: (%s) Successful Free\n", argv[1]); - } else { - printf("INFO: (%s) Skipping Free\n", argv[1]); - } - - printf("DONE: (%s)", argv[1]); - return 0; -} -""") - - results = self.runDosemu("testit.bat", config="""\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -""") - - # INFO: (TEST0) DPMI allocation info: HNDL=00000012, SIZE=00020000, ADDR=21199000 - - m = re.search(r'\(TEST0\).*HNDL=([\da-f]+), SIZE=([\da-f]+), ADDR=([\da-f]+)', results) - self.assertIsNotNone(m, results) - - FMT = r'(?m)^INFO: \(%s\).*, SIZE=%s, ADDR=%s[\r\n]+' - - self.assertRegex(results, FMT % ('TEST1', m.group(2), m.group(3))) - self.assertRegex(results, FMT % ('TEST2', m.group(2), m.group(3))) - self.assertRegex(results, FMT % ('TEST3', m.group(2), m.group(3))) - self.assertRegex(results, FMT % ('TEST4', m.group(2), m.group(3))) - self.assertRegex(results, FMT % ('TEST5', m.group(2), m.group(3))) - self.assertRegex(results, FMT % ('TEST6', m.group(2), m.group(3))) - self.assertRegex(results, FMT % ('TEST7', m.group(2), m.group(3))) - self.assertRegex(results, FMT % ('TEST8', m.group(2), m.group(3))) - self.assertRegex(results, FMT % ('TEST9', m.group(2), m.group(3))) - self.assertNotIn("FAIL:", results) diff --git a/test/func_memory_dpmi_leak_check_dos.py b/test/func_memory_dpmi_leak_check_dos.py deleted file mode 100644 index b2bb4bb..0000000 --- a/test/func_memory_dpmi_leak_check_dos.py +++ /dev/null @@ -1,88 +0,0 @@ -import re - - -def memory_dpmi_leak_check_dos(self, tipo): - - self.mkfile("testit.bat", """\ -c:\\dpmileak TEST0 {0} -c:\\dpmileak TEST1 {0} -c:\\dpmileak TEST2 {0} -c:\\dpmileak TEST3 {0} -c:\\dpmileak TEST4 {0} -c:\\dpmileak TEST5 {0} -c:\\dpmileak TEST6 {0} -c:\\dpmileak TEST7 {0} -c:\\dpmileak TEST8 {0} -c:\\dpmileak TEST9 {0} -rem end -""".format(tipo), newline="\r\n") - - self.mkexe_with_djgpp("dpmileak", r""" -#include -#include -#include -#include -#include -#include -#include - -int main(int argc, char *argv[]) -{ - - int selector, segment; - int dofree = 1; - - if (argc < 2) { - printf("FAIL: Missing argument IDSTRING (normal|nofree)\n"); - return -2; - } - - if (argc > 2 && strcmp(argv[2], "nofree") == 0) - dofree = 0; - - segment = __dpmi_allocate_dos_memory(4096, &selector); - if (segment == -1) { - printf("FAIL: (%s) DPMI allocation (DOS) failed\n", argv[1]); - return -1; - } - - printf("INFO: (%s) DPMI allocation (DOS) info: SEGMENT=%04x, SELECTOR=%04x\n", - argv[1], segment, selector); - - if (dofree) { - if (__dpmi_free_dos_memory(selector) == -1) { - printf("FAIL: (%s) DPMI free (DOS) failed\n", argv[1]); - return -1; - } - printf("INFO: (%s) Successful Free (DOS)\n", argv[1]); - } else { - printf("INFO: (%s) Skipping Free (DOS)\n", argv[1]); - } - - printf("DONE: (%s)", argv[1]); - return 0; -} -""") - - results = self.runDosemu("testit.bat", config="""\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -""") - - # INFO: (TEST0) DPMI allocation (DOS) info: SEGMENT=04c5, SELECTOR=01bf - - m = re.search(r'\(TEST0\).*info: SEGMENT=([\da-f]+), SELECTOR=([\da-f]+)', results) - self.assertIsNotNone(m, results) - - FMT = r'(?m)^INFO: \(%s\).*info: SEGMENT=%s, SELECTOR=%s[\r\n]+' - - self.assertRegex(results, FMT % ('TEST1', m.group(1), m.group(2))) - self.assertRegex(results, FMT % ('TEST2', m.group(1), m.group(2))) - self.assertRegex(results, FMT % ('TEST3', m.group(1), m.group(2))) - self.assertRegex(results, FMT % ('TEST4', m.group(1), m.group(2))) - self.assertRegex(results, FMT % ('TEST5', m.group(1), m.group(2))) - self.assertRegex(results, FMT % ('TEST6', m.group(1), m.group(2))) - self.assertRegex(results, FMT % ('TEST7', m.group(1), m.group(2))) - self.assertRegex(results, FMT % ('TEST8', m.group(1), m.group(2))) - self.assertRegex(results, FMT % ('TEST9', m.group(1), m.group(2))) - self.assertNotIn("FAIL:", results) diff --git a/test/func_memory_hma.py b/test/func_memory_hma.py deleted file mode 100644 index c42df61..0000000 --- a/test/func_memory_hma.py +++ /dev/null @@ -1,601 +0,0 @@ -BATCHFILE = """\ -c:\\%s -rem end -""" - -CONFIG = """\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -""" - - -def memory_hma_freespace(self): - - if 'FDPP' in self.version: - self.mkfile("userhook.sys", """DOS=HIGH\n""", newline="\r\n") - - self.mkfile("testit.bat", BATCHFILE % 'hmaspace', newline="\r\n") - - self.mkcom_with_ia16("hmaspace", r""" - -#include -#include -#include - - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - struct SREGS rs; - int ret = 0; - - r.x.ax = 0x4a01; // get hma free space - int86x(0x2f, &r, &r, &rs); - if (r.x.bx == 0) { - printf("INFO: DOS not using HMA(BX==0)\n"); - ret += 1; - } - if (rs.es == 0xffff && r.x.di == 0xffff) { - printf("INFO: DOS not using HMA(ES:DI==FFFF:FFFF)\n"); - ret += 1; - } - - if (ret != 0) { - printf("FAIL: No HMA available\n"); - return ret; - } - - printf("INFO: HMA free space == 0x%04x\n", r.x.bx); - printf("INFO: HMA area at %04X:%04X\n", rs.es, r.x.di); - printf("PASS: HMA available\n"); - return 0; -} - -""") - - results = self.runDosemu("testit.bat", config=CONFIG) - - self.assertIn("PASS:", results) - - -def memory_hma_alloc(self): - - if 'FDPP' in self.version: - self.mkfile("userhook.sys", """DOS=HIGH\n""", newline="\r\n") - - self.mkfile("testit.bat", BATCHFILE % 'hmaalloc', newline="\r\n") - - self.mkcom_with_ia16("hmaalloc", r""" - -#include -#include -#include - - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - struct SREGS rs; - int ret = 0; - - r.x.ax = 0x4a02; // get hma memory block - r.x.bx = 35; // alloc 35 bytes, should get rounded up to 48 - int86x(0x2f, &r, &r, &rs); - - printf("INFO: HMA size returned %d\n", r.x.bx); - printf("INFO: HMA block allocated at %04X:%04X\n", rs.es, r.x.di); - - if (r.x.bx != 48) { - printf("WARN: HMA returned size unexpected\n"); - ret += 1; - } - - if (rs.es != 0xffff) { - printf("WARN: HMA block allocated in wrong segment\n"); - ret += 1; - } - - if (ret != 0) { - printf("FAIL: Test failed\n"); - return ret; - } - - printf("PASS: HMA allocation successful\n"); - return 0; -} - -""") - - results = self.runDosemu("testit.bat", config=CONFIG) - - self.assertIn("PASS:", results) - - -def memory_hma_alloc3(self): - - if 'FDPP' in self.version: - self.mkfile("userhook.sys", """DOS=HIGH\n""", newline="\r\n") - - self.mkfile("testit.bat", BATCHFILE % 'hmaalloc', newline="\r\n") - - self.mkcom_with_ia16("hmaalloc", r""" - -#include -#include -#include - -struct HMCB { - uint8_t signature[2]; // "MS" - uint16_t owner; // 0000=free, 0001=DOS, FF33=IO.SYS, FFFF=MSDOS.SYS - uint16_t size; // bytes not including this header - uint16_t next; // offset of next memory block in segment FFFFh, or 0000h if last - uint8_t reserved[8]; // unused (explicitly set to 0 for MS-DOS 7.10) -}; - -/* -Windows95 - DOS KERNEL - (DE)ALLOCATE HMA MEMORY BLOCK - -AX = 4A03h -CX = segment of block's owner??? -DL = subfunction - 00h allocate block - BX = number of bytes - Return: - DI=FFFFh if unable to allocate - ES:DI -> allocated block - // We do get the allocated size in BX, RBIL misses this - - 01h resize block // Seemingly can grow as well as shrink - ES:DI -> previously-allocated block - BX = new size in bytes - Return: - DI=FFFFh if unable to allocate - ES:DI -> reallocated block - // Maybe we get the reallocated size in BX - Win95 FE & SE never seem to free the initial block after creating the - replacement. In addition, subsequent frees of the replacement block - fail. - - 02h free block - ES:DI -> block to be freed - Return: - Nothing, but checking the ID in the requested block can indicate - whether the block was freed. -*/ - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - struct SREGS rs; - int ret; - struct HMCB hmcb; - uint16_t hma_seg, hma_off; - -// Alloc subfunction - ret = 0; - r.x.ax = 0x4a03; // hma alloc/realloc/free memory block - r.x.bx = 35; // alloc 35 bytes, should get rounded up to 48 - r.x.cx = __libi86_get_cs(); // segment of block's owner - r.h.dl = 0; // subfunction 0 - alloc - - printf("INFO: Int2f/4a03, dl=0 alloc\n"); - int86x(0x2f, &r, &r, &rs); - - printf("INFO: HMA size returned %d\n", r.x.bx); - printf("INFO: HMA block allocated at %04X:%04X\n", rs.es, r.x.di); - - // Copy back to near structure to make printfs easier - memset(&hmcb, 0, sizeof(hmcb)); - _fmemcpy(&hmcb, MK_FP(rs.es, r.x.di - 0x10), sizeof(hmcb)); - - printf("INFO: \"%c%c\" // signature\n", hmcb.signature[0], hmcb.signature[1]); - printf("INFO: %04X // owner, our CS = %04X\n", hmcb.owner, __libi86_get_cs()); - printf("INFO: %04X // size (hex bytes)\n", hmcb.size); - printf("INFO: %04X // offset to next HMA block\n", hmcb.next); - - if (r.x.di == 0xffff) { - printf("WARN: HMA returned offset indicates failure (DI == 0xffff)\n"); - ret += 1; - } - - if (r.x.bx != 48) { - printf("WARN: HMA returned size unexpected (BX == %d)\n", r.x.bx); - ret += 1; - } - - if (r.x.bx != hmcb.size) { - printf("WARN: hmcb.size != HMA returned size (%d != %d)\n", hmcb.size, r.x.bx); - ret += 1; - } - - if (ret != 0) { - printf("FAIL: Alloc test failed\n"); - return ret; - } - - hma_seg = rs.es; - hma_off = r.x.di; - - printf("\n"); - -#if 0 // Disable resize tests as the function doesn't seem to work on Win95 SE - // allocating multiple blocks and preventing final free. - -// Realloc subfunction (shrink block) - ret = 0; - r.x.ax = 0x4a03; // hma alloc/realloc/free memory block - r.x.bx = 29; // realloc 29 bytes, should get rounded up to 32 - r.x.cx = __libi86_get_cs(); // segment of block's owner - r.h.dl = 1; // subfunction 1 - realloc - rs.es = hma_seg; // old block seg:off - r.x.di = hma_off; - - printf("INFO: Int2f/4a03, dl=1 realloc (shrink)(%04X:%04X)\n", rs.es, r.x.di); - int86x(0x2f, &r, &r, &rs); - - printf("INFO: HMA size returned %d\n", r.x.bx); - printf("INFO: HMA block reallocated at %04X:%04X\n", rs.es, r.x.di); - - // Copy back to near structure to make printfs easier - memset(&hmcb, 0, sizeof(hmcb)); - _fmemcpy(&hmcb, MK_FP(rs.es, r.x.di - 0x10), sizeof(hmcb)); - - printf("INFO: \"%c%c\" // signature\n", hmcb.signature[0], hmcb.signature[1]); - printf("INFO: %04X // owner, our CS = %04X\n", hmcb.owner, __libi86_get_cs()); - printf("INFO: %04X // size (hex bytes)\n", hmcb.size); - printf("INFO: %04X // offset to next HMA block\n", hmcb.next); - - if (r.x.di == 0xffff) { - printf("WARN: HMA returned offset indicates failure (DI == 0xffff)\n"); - ret += 1; - } - - if (r.x.bx != 32) { - printf("WARN: HMA returned size unexpected (BX == %d)\n", r.x.bx); - ret += 1; - } - - if (r.x.bx != hmcb.size) { - printf("WARN: hmcb.size != HMA returned size (%d != %d)\n", hmcb.size, r.x.bx); - ret += 1; - } - - if (ret != 0) { - printf("FAIL: Realloc(shrink) test failed\n"); - return ret; - } - - hma_seg = rs.es; - hma_off = r.x.di; - - printf("\n"); - -// Realloc subfunction (grow block) - ret = 0; - r.x.ax = 0x4a03; // hma alloc/realloc/free memory block - r.x.bx = 65; // realloc 65 bytes, should get rounded up to 80 - r.x.cx = __libi86_get_cs(); // segment of block's owner - r.h.dl = 1; // subfunction 1 - realloc - rs.es = hma_seg; // old block seg:off - r.x.di = hma_off; - - printf("INFO: Int2f/4a03, dl=1 realloc (grow)(%04X:%04X)\n", rs.es, r.x.di); - int86x(0x2f, &r, &r, &rs); - - printf("INFO: HMA size returned %d\n", r.x.bx); - printf("INFO: HMA block reallocated at %04X:%04X\n", rs.es, r.x.di); - - // Copy back to near structure to make printfs easier - memset(&hmcb, 0, sizeof(hmcb)); - _fmemcpy(&hmcb, MK_FP(rs.es, r.x.di - 0x10), sizeof(hmcb)); - - printf("INFO: \"%c%c\" // signature\n", hmcb.signature[0], hmcb.signature[1]); - printf("INFO: %04X // owner, our CS = %04X\n", hmcb.owner, __libi86_get_cs()); - printf("INFO: %04X // size (hex bytes)\n", hmcb.size); - printf("INFO: %04X // offset to next HMA block\n", hmcb.next); - - if (r.x.di == 0xffff) { - printf("WARN: HMA returned offset indicates failure (DI == 0xffff)\n"); - ret += 1; - } - - if (r.x.bx != 80) { - printf("WARN: HMA returned size unexpected (BX == %d)\n", r.x.bx); - ret += 1; - } - - if (r.x.bx != hmcb.size) { - printf("WARN: hmcb.size != HMA returned size (%d != %d)\n", hmcb.size, r.x.bx); - ret += 1; - } - - if (ret != 0) { - printf("FAIL: Realloc(grow) test failed\n"); - return ret; - } - - hma_seg = rs.es; - hma_off = r.x.di; - - printf("\n"); - -#endif - -// Free block subfunction - ret = 0; - r.x.ax = 0x4a03; // hma alloc/realloc/free memory block - r.x.cx = __libi86_get_cs(); // segment of block's owner - r.h.dl = 2; // subfunction 2 - free - rs.es = hma_seg; // old block seg:off - r.x.di = hma_off; - - printf("INFO: Int2f/4a03, dl=2 free (%04X:%04X)\n", rs.es, r.x.di); - int86x(0x2f, &r, &r, &rs); - - // Free doesn't return anything to indicate success, so we have to check the - // requested block to see if it's still marked as ours - - // Copy back to near structure to make access easier - memset(&hmcb, 0, sizeof(hmcb)); - _fmemcpy(&hmcb, MK_FP(rs.es, r.x.di - 0x10), sizeof(hmcb)); - - if (hmcb.signature[0] == 'M' && hmcb.signature[1] == 'S' && - hmcb.owner == __libi86_get_cs()) { - printf("WARN: Freed block still marked as ours\n"); - ret += 1; - } - - if (ret != 0) { - printf("FAIL: Free test failed\n"); - return ret; - } - - printf("\n"); - - printf("PASS: HMA alloc/realloc/free successful\n"); - return 0; -} - -""") - - results = self.runDosemu("testit.bat", config=CONFIG) - - self.assertIn("PASS:", results) - - -def memory_hma_chain(self): - - if 'FDPP' in self.version: - self.mkfile("userhook.sys", """DOS=HIGH\n""", newline="\r\n") - - self.mkfile("testit.bat", BATCHFILE % 'hmachain', newline="\r\n") - - self.mkcom_with_ia16("hmachain", r""" - -#include -#include -#include - -struct HMCB { - uint8_t signature[2]; // "MS" - uint16_t owner; // 0000=free, 0001=DOS, FF33=IO.SYS, FFFF=MSDOS.SYS - uint16_t size; // bytes not including this header - uint16_t next; // offset of next memory block in segment FFFFh, or 0000h if last - uint8_t reserved[8]; // unused (explicitly set to 0 for MS-DOS 7.10) -}; - -/* - INT 2F U - Windows95 - DOS KERNEL - GET START OF HMA MEMORY CHAIN - AX = 4A04h - Return: AX = 0000h if function supported - ES:DI -> first HMA memory control block (see #02800) -*/ - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - struct SREGS rs; - int ret; - struct HMCB hmcb; - -// Alloc subfunction - ret = 0; - r.x.ax = 0x4a04; // get start of hma chain - - printf("INFO: Int2f/4a04\n"); - int86x(0x2f, &r, &r, &rs); - - if (r.x.ax != 0) { - printf("WARN: HMA get chain returned (0x%04x), unsupported\n", r.x.ax); - ret += 1; - } else { - printf("INFO: HMA head at %04X:%04X\n", rs.es, r.x.di); - - // Copy back to near structure to make printfs easier - memset(&hmcb, 0, sizeof(hmcb)); - _fmemcpy(&hmcb, MK_FP(rs.es, r.x.di), sizeof(hmcb)); - - printf("INFO: \"%c%c\" // signature\n", hmcb.signature[0], hmcb.signature[1]); - printf("INFO: %04X // owner\n", hmcb.owner); - printf("INFO: %04X // size (hex bytes)\n", hmcb.size); - printf("INFO: %04X // offset to next HMA block\n", hmcb.next); - - if (hmcb.signature[0] != 'M' || hmcb.signature[1] != 'S') { - printf("WARN: HMA head signature incorrect\n"); - ret += 1; - } - } - - if (ret != 0) { - printf("FAIL: HMA get chain failed\n"); - return ret; - } - - printf("PASS: HMA get chain successful\n"); - return 0; -} - -""") - - results = self.runDosemu("testit.bat", config=CONFIG) - - self.assertIn("PASS:", results) - - -def memory_hma_a20(self): - - if 'FDPP' in self.version: - self.mkfile("userhook.sys", """DOS=HIGH\n""", newline="\r\n") - - self.mkfile("testit.bat", BATCHFILE % 'hmaa20', newline="\r\n") - - self.mkcom_with_ia16("hmaa20", r""" - -#include -#include -#include - -#define TSTRING "HELLO THERE" - -int main(int argc, char *argv[]) -{ - union REGS r = {}; - struct SREGS rs; - char testbuf[sizeof(TSTRING)]; - char savebuf[sizeof(TSTRING)]; - char __far *hma_location; - char __far *cnv_location; - int ret = 0; - int a20; - int res1, res2, val1, val2; - - r.x.ax = 0x4a02; // get hma memory block - r.x.bx = 35; // alloc 35 bytes, should get rounded up to 48 - int86x(0x2f, &r, &r, &rs); - - printf("INFO: HMA size returned %d\n", r.x.bx); - printf("INFO: HMA block allocated at %04X:%04X\n", rs.es, r.x.di); - - if (rs.es != 0xffff) { - printf("WARN: HMA block allocated in wrong segment\n"); - ret += 1; - } - - // Note: wrapped address will always be in first segment - hma_location = MK_FP(rs.es, r.x.di); - cnv_location = MK_FP(0x0000, ((rs.es << 4) + r.x.di) & 0xffff); - - _disable(); - - // Get A20 status - r.x.ax = 0x2402; - r.x.cflag = 1; - int86x(0x15, &r, &r, &rs); - if (!r.x.cflag) { - a20 = r.h.al; - } else { - a20 = 1; // default to on - } - res1 = r.x.cflag; - val1 = r.h.al; - val2 = r.h.ah; - - // Save memory - _fmemcpy(savebuf, cnv_location, sizeof(TSTRING)); - - // Write to HMA memory - _fmemcpy(hma_location, TSTRING, sizeof(TSTRING)); - - // Read from the wrapped address - _fmemcpy(testbuf, cnv_location, sizeof(TSTRING)); - - // Restore corrupted memory as soon as possible - _fmemcpy(cnv_location, savebuf, sizeof(TSTRING)); - - _enable(); - - if (!res1) { - printf("INFO: A20 is initially %s\n", val1 == 0 ? "disabled" : "enabled"); - } else { - printf("WARN: A20 status could not be determined (0x%02x)\n", val2); - ret += 1; - } - - // Compare to make sure we are not writing in the wrong place - if (memcmp(testbuf, TSTRING, sizeof(TSTRING)) == 0) { - printf("WARN: Wrapping is evident\n"); - ret += 1; - } else { - printf("INFO: Wrapping is not evident\n"); - } - - _disable(); - - // Disable the A20 to enable the wrapping of memory - r.x.ax = 0x2400; - r.x.cflag = 1; - int86x(0x15, &r, &r, &rs); - res1 = r.x.cflag; - if (res1) - val1 = r.h.ah; - - // Save memory - _fmemcpy(savebuf, cnv_location, sizeof(TSTRING)); - - // Write to HMA memory - _fmemcpy(hma_location, TSTRING, sizeof(TSTRING)); - - // Read from the wrapped address - _fmemcpy(testbuf, cnv_location, sizeof(TSTRING)); - - // Restore corrupted memory as soon as possible - _fmemcpy(cnv_location, savebuf, sizeof(TSTRING)); - - // Maybe reenable the A20 to return to normal - if (a20) { - r.x.ax = 0x2401; - r.x.cflag = 1; - int86x(0x15, &r, &r, &rs); - res2 = r.x.cflag; - val2 = r.h.ah; - } - - _enable(); - - if (!res1) { - printf("INFO: A20 successfully disabled\n"); - } else { - printf("WARN: A20 could not be disabled (0x%02x)\n", val1); - ret += 1; - } - - if (a20) - if (!res2) { - printf("INFO: A20 successfully reenabled\n"); - } else { - printf("WARN: A20 could not be reenabled\n (0x%02x)\n", val2); - ret += 1; - } - - // Compare - if (memcmp(testbuf, TSTRING, sizeof(TSTRING)) == 0) { - printf("INFO: Wrapping is evident and expected\n"); - } else { - printf("WARN: Wrapping is not evident\n"); - ret += 1; - } - - if (ret != 0) { - printf("FAIL: Test failed\n"); - return ret; - } - - printf("PASS: HMA allocation successful\n"); - return 0; -} - -""") - - results = self.runDosemu("testit.bat", config=CONFIG) - - self.assertIn("PASS:", results) diff --git a/test/func_memory_uma.py b/test/func_memory_uma.py deleted file mode 100644 index f97f4dd..0000000 --- a/test/func_memory_uma.py +++ /dev/null @@ -1,164 +0,0 @@ -BATCHFILE = """\ -c:\\%s -rem end -""" - -CONFIG = """\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -""" - - -def memory_uma_strategy(self): - - self.mkfile("testit.bat", BATCHFILE % 'umastrat', newline="\r\n") - - self.mkexe_with_djgpp("umastrat", r"""\ -#include -#include -#include -#include -#include -#include -#include - -typedef unsigned FAR_PTR; - -struct PSP { - unsigned short opint20; /* 0x00 */ - unsigned short memend_frame; /* 0x02 */ - unsigned char dos_reserved4; /* 0x04 */ - unsigned char cpm_function_entry[0xa-0x5]; /* 0x05 */ - FAR_PTR int22_copy; /* 0x0a */ - FAR_PTR int23_copy; /* 0x0e */ - FAR_PTR int24_copy; /* 0x12 */ - unsigned short parent_psp; /* 0x16 */ - unsigned char file_handles[20]; /* 0x18 */ - unsigned short envir_frame; /* 0x2c */ - FAR_PTR system_stack; /* 0x2e */ - unsigned short max_open_files; /* 0x32 */ - FAR_PTR file_handles_ptr; /* 0x34 */ - unsigned char dos_reserved38[0x50-0x38]; /* 0x38 */ - unsigned char high_language_dos_call[0x53-0x50]; /* 0x50 */ - unsigned char dos_reserved53[0x5c-0x53]; /* 0x53 */ - unsigned char FCB1[0x6c-0x5c]; /* 0x5c */ - unsigned char FCB2[0x80-0x6c]; /* 0x6c */ - unsigned char cmdline_len; /* 0x80 */ - char cmdline[0x100-0x81]; /* 0x81 */ -} __attribute__((packed)); -static struct PSP psp; // make it static to be %ds-addresable - -int main() -{ - __dpmi_regs r = {}; - int err; - unsigned long psp_addr; - unsigned short psp_seg; - int alloced, want_alloc; - int ret = 0; - - err = __dpmi_get_segment_base_address(_stubinfo->psp_selector, &psp_addr); - if (err || (psp_addr & 0xf) || psp_addr >= 0x110000) { - printf("FAIL: get psp failed\n"); - exit(1); - } - psp_seg = psp_addr >> 4; - printf("INFO: PSP at %x\n", psp_seg); - if (psp_seg > 0xa000) { - printf("FAIL: test loaded high, BAD. Use SHELL_LOADHIGH_DEFAULT=0 dosemu arg\n"); - exit(1); - } - movedata(_stubinfo->psp_selector, 0, _my_ds(), (uintptr_t)&psp, sizeof(psp)); - printf("INFO: mem end: %x\n", psp.memend_frame); - if (psp.memend_frame > 0xa000) { - printf("FAIL: too many memory allocated, FAILURE\n"); - exit(1); - } - - r.h.ah = 0x48; - r.x.bx = 1; - __dpmi_int(0x21, &r); /* allocate one-paragraph block */ - if ((r.x.flags & 1)) { - printf("FAIL: alloc failed\n"); - exit(1); - } - printf("INFO: alloc at %x\n", r.x.ax); - if (r.x.ax > 0xa000) { - printf("FAIL: initial alloc at UMB, FAILURE!\n"); - exit(1); - } - - r.x.es = r.x.ax; - r.h.ah = 0x49; - __dpmi_int(0x21, &r); /* free block */ - if ((r.x.flags & 1)) { - printf("FAIL: free failed\n"); - exit(1); - } - - /* try UMB alloc */ - r.x.ax = 0x5801; - r.x.bx = 0x80; - __dpmi_int(0x21, &r); -#if 1 - r.x.ax = 0x5803; - r.x.bx = 1; - __dpmi_int(0x21, &r); -#endif - r.h.ah = 0x48; - r.x.bx = 1; - __dpmi_int(0x21, &r); /* allocate one-paragraph block */ - if ((r.x.flags & 1)) { - printf("FAIL: alloc failed\n"); - exit(1); - } - printf("INFO: alloc at %x\n", r.x.ax); - if (r.x.ax < 0xa000) { - printf("FAIL: alloc at UMB FAILED\n"); - ret++; -// exit(1); - } else - printf("INFO: alloc at UMB OK\n"); - - r.x.es = r.x.ax; - r.h.ah = 0x49; - __dpmi_int(0x21, &r); /* free block */ - if ((r.x.flags & 1)) { - printf("FAIL: free failed\n"); - ret++; -// exit(1); - } - - /* try large low alloc */ - r.x.ax = 0x5801; - r.x.bx = 0; - __dpmi_int(0x21, &r); - want_alloc = 0xe000; - alloced = 0; - while (alloced < want_alloc) { - r.h.ah = 0x48; - r.x.bx = 0x100; - __dpmi_int(0x21, &r); - if ((r.x.flags & 1)) - break; - alloced += 0x100; - } - printf("INFO: allocated %i of %i\n", alloced << 4, want_alloc << 4); - if (alloced < 0xa000) { - printf("FAIL: UMB not allocated, FAILURE\n"); - ret++; - } - - if (ret == 0) - printf("PASS: Done\n"); - else - printf("FAIL: One or more non-fatal errors occurred\n"); - - return ret; -} -""") - - results = self.runDosemu("testit.bat", config=CONFIG) - - self.assertIn("PASS:", results) - self.assertNotIn("FAIL:", results) diff --git a/test/func_memory_xms.py b/test/func_memory_xms.py deleted file mode 100644 index 2de5c62..0000000 --- a/test/func_memory_xms.py +++ /dev/null @@ -1,216 +0,0 @@ -BATCHFILE = """\ -c:\\%s -rem end -""" - -CONFIG = """\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -""" - - -def memory_xms(self): - -# Note: Not sure if I need this - if 'FDPP' in self.version: - self.mkfile("userhook.sys", """DOS=HIGH\n""", newline="\r\n") - - self.mkfile("testit.bat", BATCHFILE % 'xmstest', newline="\r\n") - - self.mkexe_with_djgpp("xmstest", r""" -#include -#include -#include -#include -#include -#include - -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif - -struct __attribute__ ((__packed__)) EMM { - unsigned int Length; - unsigned short SourceHandle; - unsigned int SourceOffset; - unsigned short DestHandle; - unsigned int DestOffset; -}; - -static __dpmi_paddr xms; -static struct EMM e; - -static int call_xms(unsigned fn, unsigned arg, unsigned *ret) -{ - int rc, err; - - asm volatile("lcall *%[x]\n" - : "=a"(rc), "=d"(*ret), "=b"(err) - : [x]"m"(xms), "a"(fn << 8), "d"(arg) - : "cc", "memory"); - if (!rc) - printf("xms error %x\n", err & 0xff); - return rc; -} - -static int call_xms0(unsigned fn, unsigned arg) -{ - int rc, err; - - asm volatile("lcall *%[x]\n" - : "=a"(rc), "=b"(err) - : [x]"m"(xms), "a"(fn << 8), "d"(arg) - : "cc", "memory"); - if (!rc) - printf("xms error %x\n", err & 0xff); - return rc; -} - -static int call_xms_dxbx(unsigned fn, unsigned arg, unsigned *ret) -{ - int rc; - unsigned dx, bx; - - asm volatile("lcall *%[x]\n" - : "=a"(rc), "=d"(dx), "=b"(bx) - : [x]"m"(xms), "a"(fn << 8), "d"(arg) - : "cc", "memory"); - *ret = (dx << 16) | bx; - return rc; -} - -static int call_xms_dssi(unsigned fn, void *ptr) -{ - int rc, err; - - asm volatile("lcall *%[x]\n" - : "=a"(rc), "=b"(err) - : [x]"m"(xms), "a"(fn << 8), "S"(ptr) - : "cc", "memory"); - if (!rc) - printf("xms error %x\n", err & 0xff); - return rc; -} - -int main() -{ - unsigned handle; - unsigned addr; - char *ptr; - char buf[PAGE_SIZE]; - int err; - __dpmi_meminfo dm = {}; - __dpmi_regs r = {}; - static const char *str1 = "request"; - static const char *str2 = "response"; - const int offs1 = 35; - const int offs2 = 174; - - /* check xms */ - r.x.ax = 0x4300; - __dpmi_int(0x2f, &r); - if (r.h.al != 0x80) { - printf("FAILURE: XMS unsupported\n"); - exit(1); - } - printf("XMS present\n"); - - /* get entry */ - asm volatile( - "int $0x2f\n" - "mov %%es, %0\n" - : "=r"(xms.selector), "=b"(xms.offset32) - : "a"(0x4310)); - printf("XMS at %x:%lx\n", xms.selector, xms.offset32); - /* alloc one page emb */ - if (!call_xms(9, 4, &handle)) { - printf("FAILURE: EMB alloc failed\n"); - exit(1); - } - printf("XMS alloc ok\n"); - - /* put test string there - length must be even */ - e.Length = (strlen(str1) + 1 + 1) & ~1; - e.SourceHandle = 0; - e.SourceOffset = (uintptr_t)str1; - e.DestHandle = handle; - e.DestOffset = offs1; - if (!call_xms_dssi(0xb, &e)) { - printf("FAILURE: XMS move failed\n"); - exit(1); - } - printf("XMS move ok\n"); - - /* map EMB */ - if (!call_xms_dxbx(0xc, handle, &addr)) { - printf("FAILURE: XMS map failed\n"); - exit(1); - } - printf("XMS map ok\n"); - - dm.address = addr; - dm.size = PAGE_SIZE; - err = __dpmi_physical_address_mapping(&dm); - if (err) { - printf("FAILURE: failed to get XMS page\n"); - exit(1); - } - printf("DPMI map ok, addr=0x%08lx\n", dm.address); - /* enable 4G wrap-around */ - if (!__djgpp_nearptr_enable()) { - printf("FAILURE: 4G wrap-around failed\n"); - exit(1); - } - ptr = (char *)(dm.address + __djgpp_conventional_base); - printf("DPMI wrap-around ok, ptr=%p, base=%08x\n", ptr, - -__djgpp_conventional_base); - printf("Got this string: %s\n", ptr + offs1); - if (strcmp(str1, ptr + offs1) != 0) - printf("FAILURE: Test 1 FAILURE\n"); - else - printf("Test 1 OK\n"); - - strcpy(ptr + offs2, str2); - /* disable wrap */ - __djgpp_nearptr_disable(); - /* unmap */ - err = __dpmi_free_physical_address_mapping(&dm); - if (err) { - printf("FAILURE: failed to put XMS page\n"); - exit(1); - } - if (!call_xms0(0xd, handle)) { - printf("FAILURE: XMS unmap failed\n"); - exit(1); - } - printf("XMS unmap ok\n"); - /* copy back our page */ - e.Length = PAGE_SIZE; - e.SourceHandle = handle; - e.SourceOffset = offs2; - e.DestHandle = 0; - e.DestOffset = (uintptr_t)buf; - if (!call_xms_dssi(0xb, &e)) { - printf("XMS bad move2 failed, OK\n"); -// exit(1); - } - e.Length -= offs2; - if (!call_xms_dssi(0xb, &e)) { - printf("FAILURE: XMS move2 failed\n"); - exit(1); - } - printf("XMS move2 ok\n"); - printf("Got back this string: %s\n", buf); - if (strcmp(str2, buf) != 0) - printf("FAILURE: Test 2 FAILURE\n"); - else - printf("Test 2 OK\n"); - return 0; -} -""") - - results = self.runDosemu("testit.bat", config=CONFIG) - - self.assertIn("Test 1 OK", results) - self.assertIn("Test 2 OK", results) - self.assertNotIn("FAILURE:", results) diff --git a/test/func_mfs_truename.py b/test/func_mfs_truename.py index 6db15d9..f20f591 100644 --- a/test/func_mfs_truename.py +++ b/test/func_mfs_truename.py @@ -1,21 +1,19 @@ -from pathlib import Path +from os import makedirs +from os.path import join from common_framework import (VFAT_MNTPNT, setup_vfat_mounted_image, teardown_vfat_mounted_image) -def mfs_truename(self, fstype, tocreate, tests): +def mfs_truename(self, fstype, tocreate, nametype, instring, expected): ename = "mfstruen" if fstype == "UFS": - testdir = Path("test-imagedir/dXXXXs/d") - testdir.mkdir(parents=True, exist_ok=True) + testdir = "test-imagedir/dXXXXs/d" + makedirs(testdir, exist_ok=True) batchfile = """\ -mkdir RootC -d: -cd Sub -c:\\%s +%s rem end """ % ename @@ -25,15 +23,13 @@ $_floppy_a = "" """ elif fstype == "VFAT": - testdir = Path(VFAT_MNTPNT) + testdir = VFAT_MNTPNT setup_vfat_mounted_image(self) batchfile = """\ lredir X: /mnt/dosemu lredir -mkdir RootC x: -cd Sub c:\\%s rem end """ % ename @@ -49,97 +45,93 @@ $_lredir_paths = "/mnt/dosemu" # Make test files and directory names for i in tocreate: - p = testdir / i[1] if i[0] == "FILE": - p.parents[0].mkdir(parents=True, exist_ok=True) - p.write_text("Some data") + with open(join(testdir, i[1]), "w") as f: + f.write("Some data") elif i[0] == "DIR": - p.mkdir(parents=True, exist_ok=True) + makedirs(join(testdir, i[1]), exist_ok=True) + if nametype == "LFN0": + intnum = "0x7160" + qtype = "0" + elif nametype == "LFN1": + intnum = "0x7160" + qtype = "1" + elif nametype == "LFN2": + intnum = "0x7160" + qtype = "2" + elif nametype == "SFN": + intnum = "0x6000" + qtype = "0" + else: + self.fail("Incorrect argument") + + # common self.mkfile("testit.bat", batchfile, newline="\r\n") - def mkctests(xtests): - cnv = { - 'LFN0': ('0x7160', '0'), - 'LFN1': ('0x7160', '1'), - 'LFN2': ('0x7160', '2'), - 'SFN': ('0x6000', '0'), - } - results = "test_t test[] = {\n" - for t in xtests: - results += ' {%s, %s, "%s", "%s"},\n' % (*cnv[t[0]], t[1], t[2]) - results += ' };\n' - results += ' int tlen = %d;' % len(xtests) - return results - # compile sources - self.mkcom_with_ia16(ename, r""" + self.mkcom_with_gas(ename, r""" +.text +.code16 -#include -#include -#include -#include + .globl _start16 +_start16: -typedef struct { - uint16_t intr; - uint8_t tipo; - const char *input; - const char *expected; -} test_t; + push %%cs + pop %%ds + push %%cs + pop %%es -%s -char dst[1024]; + movw $%s, %%ax + movw $%s, %%cx + movw $src, %%si + movw $dst, %%di + int $0x21 -int main(void) -{ - int ret = 0; - union REGS r = {}; - struct SREGS rs; - int i; + movw $128, %%cx + movb $0, %%al + cld + repne scasb + movb $')', -1(%%di) + movb $'$', (%%di) - for (i = 0; i < tlen; i++) { - r.x.ax = test[i].intr; - if (r.x.ax == 0x7160) - r.x.cx = test[i].tipo; - rs.ds = FP_SEG(test[i].input); - r.x.si = FP_OFF(test[i].input); - rs.es = FP_SEG(dst); - r.x.di = FP_OFF(dst); - // need to set CF so we can detect if the function is implemented - r.x.cflag = 1; - int86x(0x21, &r, &r, &rs); - if (r.x.cflag) { - if (r.x.ax == 0x7100) { - snprintf(dst, sizeof(dst), "ERROR: not implemented, or perhaps ignored as not our drive\n"); - } else if (r.x.ax == 0x2) { - snprintf(dst, sizeof(dst), "ERROR: invalid component"); - } else if (r.x.ax == 0x3) { - snprintf(dst, sizeof(dst), "ERROR: malformed path or invalid drive letter"); - } else { - snprintf(dst, sizeof(dst), "ERROR: unknown error code 0x%%04x", r.x.ax); - } - } + jnc prsucc - if (strcmp(dst, test[i].expected) != 0) { - printf("FAIL: 0x%%04x/%%d, (sent '%%s', expected '%%s', got '%%s')\n", - test[i].intr, test[i].tipo, test[i].input, test[i].expected, dst); - ret += 1; - } else { - if (test[i].intr == 0x7160) { - printf("OKAY: 0x%%04x/%%d, (sent '%%s', got '%%s')\n", - test[i].intr, test[i].tipo, test[i].input, dst); - } else { - printf("OKAY: 0x%%04x , (sent '%%s', got '%%s')\n", - test[i].intr, test[i].input, dst); - } - } - } +prfail: + movw $failmsg, %%dx + movb $0x9, %%ah + int $0x21 - if (ret == 0) - printf("PASS:\n"); - return ret; -} -""" % mkctests(tests)) + jmp exit + +prsucc: + movw $succmsg, %%dx + movb $0x9, %%ah + int $0x21 + +prresult: + movb $0x9, %%ah + movw $pdst, %%dx + int $0x21 + +exit: + movb $0x4c, %%ah + int $0x21 + +src: + .asciz "%s" + +succmsg: + .ascii "Directory Operation Success\r\n$" +failmsg: + .ascii "Directory Operation Failed\r\n$" + +pdst: + .byte '(' +dst: + .fill 128, 1, '$' + +""" % (intnum, qtype, instring.replace("\\", "\\\\"))) results = self.runDosemu("testit.bat", config=config) @@ -147,4 +139,8 @@ int main(void) teardown_vfat_mounted_image(self) self.assertRegex(results, r"X: = .*LINUX\\FS/mnt/dosemu") - self.assertNotIn("FAIL", results) + if expected is None: + self.assertIn("Directory Operation Failed", results) + else: + self.assertIn("Directory Operation Success", results) + self.assertIn("(" + expected + ")", results) diff --git a/test/func_network.py b/test/func_network.py deleted file mode 100644 index b2e7552..0000000 --- a/test/func_network.py +++ /dev/null @@ -1,88 +0,0 @@ - -from http.server import BaseHTTPRequestHandler, HTTPServer -import threading - -from common_framework import setup_tap_interface, teardown_tap_interface - -# Note: this is the address assigned to libvirt's virbr0 bridge interface -HOST = '192.168.122.1' -PORT = 8080 - -CONTENT = b"""\ -This is very short string. Ideally we'd use the new random byte generator -in python 3.9, but not all test platforms have that yet(mine included)""" - - -class MyServer(BaseHTTPRequestHandler): - def do_GET(self): - self.send_response(200) - self.send_header("Content-type", "application/octet-stream") - self.end_headers() - self.wfile.write(CONTENT) - raise KeyboardInterrupt # Close afterwards - - def log_message(self, format, *args): - pass # Quieten stderr - - -def little_webserver(): - with HTTPServer((HOST, PORT), MyServer) as ws: - try: - ws.serve_forever() - except KeyboardInterrupt: - pass - - -def network_pktdriver_mtcp(self, driver): - setup_tap_interface(self) - self.addCleanup(teardown_tap_interface, self) - - thread = threading.Thread(target=little_webserver, daemon=True) - thread.start() - - self.unTarOrSkip("TEST_CRYNWR.tar", [ - ("ne2000.com", "297cf2bc04aded016bb8051a9d2b061940c39569"), - ]) - - self.unTarOrSkip("TEST_MTCP.tar", [ - ("dhcp.exe", "3658786197def91dce139f0d2aa1524ba409e426"), - ("htget.exe", "26e72660d62a274577e874ba68bd6af03962fcce"), - ("ping.exe", "6f8814e9ef4366b0a7597f005d1aad587eb6fc93"), - ("pkttool.exe", "66a26d7fc18c0102ba6672c37fb6b04a027dc6ee"), - ]) - - # Note: Only load the DOS NE2000 driver if you are going to use it - # as it interferes with the builtin packet driver's receipt - # of packets. - if driver == 'ne2000': - pktintr = '0x61' - mtcpcfg = 'c:\\ne2000 %s 10 0x310' % pktintr - else: - pktintr = '0x60' - mtcpcfg = '' - - self.mkfile("mtcp.cfg", """\ -packetint %s -hostname dosemu -dhcp_lease_request_secs 3600 -dhcp_lease_threshold 360 -""" % pktintr, newline="\r\n") - - self.mkfile("testit.bat", """\ -%s -set MTCPCFG=c:\\mtcp.cfg -dhcp -htget -o test.fil http://%s:%d/test.fil -rem end -""" % (mtcpcfg, HOST, PORT), newline="\r\n") - - results = self.runDosemu("testit.bat", config="""\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -$_pktdriver = (on) -$_vnet = "tap" -$_tapdev = "tap0" -""", timeout=30) - - testfil = self.workdir / 'test.fil' - self.assertEqual(CONTENT, testfil.read_bytes()) diff --git a/test/func_pit_mode_2.py b/test/func_pit_mode_2.py deleted file mode 100644 index b82392e..0000000 --- a/test/func_pit_mode_2.py +++ /dev/null @@ -1,138 +0,0 @@ - -def pit_mode_2(self): - - self.mkfile("testit.bat", """\ -pitmode2 -rem end -""", newline="\r\n") - -# compile sources - self.mkcom_with_ia16("pitmode2", r""" -/* - Sample program #15 - Demonstrates absolute timestamping in mode two - Part of the PC Timing FAQ / Application notes - By K. Heidenstrom (kheidens@actrix.gen.nz) - - Rewritten to be non-interactive and compile with ia16-elf-gcc -*/ - -#define _BORLANDC_SOURCE - -#include -#include -#include - -typedef struct { - unsigned int part; - unsigned long ticks; -} __attribute__((packed)) timestamp; - -// #define BIOS_TICK_COUNT_P ((volatile unsigned long far *)0x0040006CL) -volatile unsigned long __far *BIOS_TICK_COUNT_P = MK_FP(0x0040, 0x006C); - -void set_mode2(void) -{ - unsigned int tick_loword; - tick_loword = *BIOS_TICK_COUNT_P; - while ((unsigned int)*BIOS_TICK_COUNT_P == tick_loword) - /* do nothing */; - -#if 0 - asm pushf; - asm cli; - outportb(0x43, 0x34); /* Channel 0, mode 2 */ - outportb(0x40, 0x00); /* Loword of divisor */ - outportb(0x40, 0x00); /* Hiword of divisor */ - asm popf; -#endif - - asm volatile("pushf\n" - "push %%ax\n" - "cli\n" - "mov $0x34, %%al\n" - "outb %%al, $0x43\n" /* Channel 0, mode 2 */ - "mov $0x00, %%al\n" - "outb %%al, $0x40\n" /* Loword of divisor */ - "outb %%al, $0x40\n" /* Hiword of divisor */ - "pop %%ax\n" - "popf\n" - : - : - : - ); - return; -} - -void get_timestamp(timestamp *tsp) -{ - unsigned long tickcount1, tickcount2; - unsigned int ctcvalue; - unsigned char ctclow, ctchigh; - -again: - tickcount1 = *BIOS_TICK_COUNT_P; - outportb(0x43, 0); /* Latch value */ - ctclow = inportb(0x40); - ctchigh = inportb(0x40); /* Read count in progress */ - ctcvalue = -((ctchigh << 8) + ctclow); - tickcount2 = *BIOS_TICK_COUNT_P; - if (tickcount2 != tickcount1) - goto again; - tsp->ticks = tickcount1; - tsp->part = ctcvalue; - return; -} - -int main(void) -{ - timestamp ts, ts1, ts2; - uint64_t start; - - printf("Sample program #15 - Demonstrates absolute timestamping\n"); - printf("Part of the PC Timing FAQ / Application notes\n"); - printf("By K. Heidenstrom (kheidens@actrix.gen.nz)\n\n"); - - set_mode2(); - - // Info - get_timestamp(&ts); /* Get timestamp */ - printf("Absolute timestamp: 0x%04X%04X%04X units of 0.8381 us\n", (unsigned int)(ts.ticks >> 16), - (unsigned int)(ts.ticks & 0xFFFF), ts.part); - - // Continuous test for 2 minutes - printf("\nContinuous timestamp test - start\n\n"); - - for (start = (ts.ticks << 16) + ts.part; /* */; /* */) { - ts2.ticks = ts1.ticks; - ts2.part = ts1.part; - ts1.ticks = ts.ticks; - ts1.part = ts.part; - get_timestamp(&ts); -// printf("0x%04X%04X%04X\r", (unsigned int)(ts.ticks >> 16), (unsigned int)(ts.ticks & 0xFFFF), ts.part); - if ((ts.ticks < ts1.ticks) || ((ts.ticks == ts1.ticks) && (ts.part < ts1.part))) { /* Went backwards? */ - printf("Timestamp went backwards: 0x%04X%04X%04X, 0x%04X%04X%04X, then 0x%04X%04X%04X\n", - (unsigned int)(ts2.ticks >> 16), (unsigned int)(ts2.ticks & 0xFFFF), ts2.part, - (unsigned int)(ts1.ticks >> 16), (unsigned int)(ts1.ticks & 0xFFFF), ts1.part, - (unsigned int)(ts.ticks >> 16), (unsigned int)(ts.ticks & 0xFFFF), ts.part); - } - if (((uint64_t)((ts.ticks << 16) + ts.part) - start) > 143181004) // 120 secs: 120/(0.8381/1000000) - break; - } - - printf("\nContinuous timestamp test - complete\n\n"); - - return 0; -} -""") - - starttime = self.utcnow() - results = self.runDosemu("testit.bat", config="""\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -""", timeout=150) - endtime = self.utcnow() - - self.assertIn("Continuous timestamp test - complete", results) - self.assertNotIn("Timestamp went backwards", results) - self.assertLess((endtime - starttime).seconds, 125) diff --git a/test/test_dos.py b/test/test_dos.py index 48ef217..97a8bce 100755 --- a/test/test_dos.py +++ b/test/test_dos.py @@ -7,15 +7,15 @@ import re from datetime import datetime from difflib import unified_diff -from os import statvfs, uname, utime, environ, access, R_OK, W_OK +from os import statvfs, uname, utime, rename, environ, access, R_OK, W_OK from os.path import exists, isdir, join from pathlib import Path from shutil import copy -from subprocess import call, CalledProcessError, run +from subprocess import call, check_call, CalledProcessError, DEVNULL, TimeoutExpired from sys import argv, exit, modules from time import mktime -from common_framework import (BaseTestCase, get_test_binaries, main, mkstring, +from common_framework import (BaseTestCase, main, mkstring, IPROMPT, KNOWNFAIL, UNSUPPORTED) from func_cpu_trap_flag import cpu_trap_flag @@ -31,27 +31,11 @@ from func_ds3_lock_twice import ds3_lock_twice from func_ds3_lock_writable import ds3_lock_writable from func_ds3_share_open_access import ds3_share_open_access from func_ds3_share_open_twice import ds3_share_open_twice -from func_lfn_voln_info import lfn_voln_info -from func_lfs_disk_info import lfs_disk_info -from func_label_create import (label_create, label_create_on_lfns, - label_create_noduplicate, label_create_nonrootdir, - label_delete_wildcard, label_delete_recreate) from func_lfs_file_info import lfs_file_info from func_lfs_file_seek_tell import lfs_file_seek_tell -from func_libi86_testsuite import libi86_create_items -from func_memory_dpmi_dpmi10_ldt import memory_dpmi_dpmi10_ldt -from func_memory_dpmi_japheth import memory_dpmi_japheth -from func_memory_dpmi_leak_check import memory_dpmi_leak_check -from func_memory_dpmi_leak_check_dos import memory_dpmi_leak_check_dos from func_memory_ems_borland import memory_ems_borland -from func_memory_hma import (memory_hma_freespace, memory_hma_alloc, memory_hma_a20, - memory_hma_alloc3, memory_hma_chain) -from func_memory_uma import memory_uma_strategy -from func_memory_xms import memory_xms from func_mfs_findfile import mfs_findfile from func_mfs_truename import mfs_truename -from func_network import network_pktdriver_mtcp -from func_pit_mode_2 import pit_mode_2 SYSTYPE_DRDOS_ENHANCED = "Enhanced DR-DOS" SYSTYPE_DRDOS_ORIGINAL = "Original DR-DOS" @@ -72,8 +56,6 @@ PRGFIL_LFN = "Program Files" class OurTestCase(BaseTestCase): - attrs = ['cputest', 'dpmitest', 'hmatest', 'nettest', 'umatest', 'xmstest', - 'labeltest'] pname = "test_dos" # Tests using assembler @@ -127,79 +109,76 @@ rem end # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds - - mov ax, %s - mov dx, dname - int 21h + movw $%s, %%ax + movw $dname, %%dx + int $0x21 jnc prsucc prfail: - mov dx, failmsg - jmp @1 + movw $failmsg, %%dx + jmp 1f prsucc: - mov dx, succmsg -@1: - mov ah, 9 - int 21h + movw $succmsg, %%dx +1: + movb $0x9, %%ah + int $0x21 - mov ax, %s - cmp ax, 0x7147 + movw $%s, %%ax + cmpw $0x7147, %%ax je prcwd - cmp ax, 0x4700 + cmpw $0x4700, %%ax je prcwd exit: - mov ah, 4ch - int 21h + movb $0x4c, %%ah + int $0x21 prcwd: -; get cwd - mov dl, 0 - mov si, curdir - int 21h +# get cwd + movb $0, %%dl + movw $curdir, %%si + int $0x21 - push ds - pop es - mov di, si + push %%ds + pop %%es + movw %%si, %%di - mov cx, 128 - mov al, 0 + movw $128, %%cx + movb $0, %%al cld repne scasb - mov byte [di-1], ')' - mov byte [di], '$' + movb $')', -1(%%di) + movb $'$', (%%di) - mov ah, 9 - mov dx, pcurdir - int 21h + movb $0x9, %%ah + movw $pcurdir, %%dx + int $0x21 jmp exit -section .data - dname: - db "%s",0 + .asciz "%s" succmsg: - db "Directory Operation Success",13,10,'$' + .ascii "Directory Operation Success\r\n$" failmsg: - db "Directory Operation Failed",13,10,'$' + .ascii "Directory Operation Failed\r\n$" pcurdir: - db '(' + .byte '(' curdir: - times 128 db '$' + .fill 128, 1, '$' """ % (intnum, cwdnum, testname)) @@ -284,48 +263,45 @@ rem end """ % (PRGFIL_SFN, ename), newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds +# get cwd + movw $%s, %%ax + movb $0, %%dl + movw $curdir, %%si + int $0x21 -; get cwd - mov ax, %s - mov dl, 0 - mov si, curdir - int 21h + push %%ds + pop %%es + movw %%si, %%di - push ds - pop es - mov di, si - - mov cx, 128 - mov al, 0 + movw $128, %%cx + movb $0, %%al cld repne scasb - mov byte [di-1], ')' - mov byte [di], '$' + movb $')', -1(%%di) + movb $'$', (%%di) - mov ah, 9 - mov dx, pcurdir - int 21h + movb $0x9, %%ah + movw $pcurdir, %%dx + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 pcurdir: - db '(' + .byte '(' curdir: - times 128 db '$' + .fill 128, 1, '$' """ % cwdnum) @@ -372,111 +348,109 @@ rem end # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %cs + pop %ds - push cs - pop ds +# Get current drive and store its letter in fspath + movw $0x1900, %ax + int $0x21 + addb $'A', %al + movb %al, fspath -; Get current drive and store its letter in fspath - mov ax, 1900h - int 21h - add al, 'A' - mov byte [fspath], al +# Get Volume info +# Windows95 - LONG FILENAME - GET VOLUME INFORMATION +# +# Call: +# AX = 71A0h +# DS:DX -> ASCIZ root name (e.g. "C:\") +# ES:DI -> buffer for file system name +# CX = size of ES:DI buffer +# +# Return: +# CF clear if successful +# AX destroyed (0000h and 0200h seen) +# BX = file system flags (see #01783) +# CX = maximum length of file name [usually 255] +# DX = maximum length of path [usually 260] +# ES:DI buffer filled (ASCIZ, e.g. "FAT","NTFS","CDFS") +# +# CF set on error +# AX = error code +# 7100h if function not supported -; Get Volume info -; Windows95 - LONG FILENAME - GET VOLUME INFORMATION -; -; Call: -; AX = 71A0h -; DS:DX -> ASCIZ root name (e.g. "C:\") -; ES:DI -> buffer for file system name -; CX = size of ES:DI buffer -; -; Return: -; CF clear if successful -; AX destroyed (0000h and 0200h seen) -; BX = file system flags (see ;01783) -; CX = maximum length of file name [usually 255] -; DX = maximum length of path [usually 260] -; ES:DI buffer filled (ASCIZ, e.g. "FAT","NTFS","CDFS") -; -; CF set on error -; AX = error code -; 7100h if function not supported - - mov ax, 71a0h - mov dx, fspath ; ds:dx - mov di, fstype ; es:di - mov cx, fstypelen + movw $0x71a0, %ax + movw $fspath, %dx # ds:dx + movw $fstype, %di # es:di + movw $fstypelen, %cx stc - int 21h + int $0x21 jc chkfail - cmp byte [fstype], '$' + cmpb $'$', fstype je prnofstype prsuccess: - mov di, fstype - mov cx, fstypelen - mov al, 0 + movw $fstype, %di + movw fstypelen, %cx + movb $0, %al cld repne scasb - mov byte [di-1], ')' - mov byte [di], 13 - mov byte [di+1], 10 - mov byte [di+2], '$' - mov dx, success + movb $')', -1(%di) + movb $'\r', (%di) + movb $'\n', 1(%di) + movb $'$', 2(%di) + movw $success, %dx jmp exit prnofstype: - mov dx, nofstype + movw $nofstype, %dx jmp exit prnotsupported: - mov dx, notsupported + movw $notsupported, %dx jmp exit prcarryset: - mov dx, carryset + movw $carryset, %dx jmp exit chkfail: - cmp ax, 7100h + cmpw $0x7100, %ax jne prcarryset jmp prnotsupported exit: - mov ah, 9 - int 21h + movb $0x9, %ah + int $0x21 - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %ah + int $0x21 carryset: - db "Carry Set",13,10,'$' + .ascii "Carry Set\r\n$" notsupported: - db "Not Supported(AX=0x7100)",13,10,'$' + .ascii "Not Supported(AX=0x7100)\r\n$" nofstype: - db "Carry Not Set But No Filesystem Type",13,10,'$' + .ascii "Carry Not Set But No Filesystem Type\r\n$" success: - db "Operation Success(" + .ascii "Operation Success(" fstype: - times 32 db '$' -fstypelen equ $ - fstype + .fill 32, 1, '$' +fstypelen = (. - fstype) successend: - times 4 db 0 + .space 4 fspath: - db "?:\", 0 + .asciz "?:\\" + """) results = self.runDosemu("testit.bat", config=config) @@ -532,92 +506,90 @@ rem end """ % (testdata, ename), newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds - mov ax, 0f00h ; open file - mov dx, fcb - int 21h - cmp al, 0 + movw $0x0f00, %%ax # open file + movw $fcb, %%dx + int $0x21 + cmpb $0, %%al jne prfailopen - mov ax, 1400h ; read from file - mov dx, fcb - int 21h - cmp al, 3 ; partial read + movw $0x1400, %%ax # read from file + movw $fcb, %%dx + int $0x21 + cmpb $03, %%al # partial read jne prfailread jmp prsucc prfailopen: - mov dx, failopen - jmp @1 + movw $failopen, %%dx + jmp 1f prfailread: - mov ax, 1000h ; close file - mov dx, fcb - int 21h - mov dx, failread - jmp @1 + movw $0x1000, %%ax # close file + movw $fcb, %%dx + int $0x21 + movw $failread, %%dx + jmp 1f prsucc: - mov dx, succstart - mov ah, 9 - int 21h + movw $succstart, %%dx + movb $0x9, %%ah + int $0x21 - mov ax, 2f00h ; get DTA address in ES:BX - int 21h + movw $0x2f00, %%ax # get DTA address in ES:BX + int $0x21 - mov byte [es:bx+%d], '$'; terminate - push es - pop ds - mov dx, bx - mov ah, 9 - int 21h + movb $'$', %%es:%d(%%bx) # terminate + push %%es + pop %%ds + movw %%bx, %%dx + movb $0x9, %%ah + int $0x21 - mov ax, 1000h ; close file - mov dx, fcb - int 21h + movw $0x1000, %%ax # close file + movw $fcb, %%dx + int $0x21 - push cs - pop ds - mov dx, succend + push %%cs + pop %%ds + movw $succend, %%dx -@1: - mov ah, 9 - int 21h +1: + movb $0x9, %%ah + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 fcb: - db 0 ; 0 default drive + .byte 0 # 0 default drive fn1: - db "% -8s" ; 8 bytes + .ascii "% -8s" # 8 bytes fe1: - db "% -3s" ; 3 bytes + .ascii "% -3s" # 3 bytes wk1: - times 24 db 0 + .space 24 succstart: - db "Operation Success($" + .ascii "Operation Success($" succend: - db ')',13,10,'$' + .ascii ")\r\n$" failopen: - db "Open Operation Failed",13,10,'$' + .ascii "Open Operation Failed\r\n$" failread: - db "Read Operation Failed",13,10,'$' + .ascii "Read Operation Failed\r\n$" """ % (len(testdata), "test", "fil")) @@ -661,114 +633,111 @@ rem end """ % (testdata, ename), newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds + movw $0x1a00, %%ax # set DTA + movw $altdta, %%dx + int $0x21 - mov ax, 1a00h ; set DTA - mov dx, altdta - int 21h - - mov ax, 2f00h ; get DTA address in ES:BX - int 21h - mov ax, cs - mov dx, es - cmp dx, ax + movw $0x2f00, %%ax # get DTA address in ES:BX + int $0x21 + movw %%cs, %%ax + movw %%es, %%dx + cmpw %%ax, %%dx jne prfaildtaset - cmp bx, altdta + cmpw $altdta, %%bx jne prfaildtaset - mov ax, 0f00h ; open file - mov dx, fcb - int 21h - cmp al, 0 + movw $0x0f00, %%ax # open file + movw $fcb, %%dx + int $0x21 + cmpb $0, %%al jne prfailopen - mov ax, 1400h ; read from file - mov dx, fcb - int 21h - cmp al, 3 ; partial read + movw $0x1400, %%ax # read from file + movw $fcb, %%dx + int $0x21 + cmpb $03, %%al # partial read jne prfailread jmp prsucc prfaildtaset: - mov dx, faildtaset - jmp @1 + movw $faildtaset, %%dx + jmp 1f prfailopen: - mov dx, failopen - jmp @1 + movw $failopen, %%dx + jmp 1f prfailread: - mov ax, 1000h ; close file - mov dx, fcb - int 21h - mov dx, failread - jmp @1 + movw $0x1000, %%ax # close file + movw $fcb, %%dx + int $0x21 + movw $failread, %%dx + jmp 1f prsucc: - mov dx, succstart - mov ah, 9 - int 21h + movw $succstart, %%dx + movb $0x9, %%ah + int $0x21 - mov ax, 2f00h ; get DTA address in ES:BX - int 21h + movw $0x2f00, %%ax # get DTA address in ES:BX + int $0x21 - mov byte [es:bx+%d], '$'; terminate - push es - pop ds - mov dx, bx - mov ah, 9 - int 21h + movb $'$', %%es:%d(%%bx) # terminate + push %%es + pop %%ds + movw %%bx, %%dx + movb $0x9, %%ah + int $0x21 - mov ax, 1000h ; close file - mov dx, fcb - int 21h + movw $0x1000, %%ax # close file + movw $fcb, %%dx + int $0x21 - push cs - pop ds - mov dx, succend + push %%cs + pop %%ds + movw $succend, %%dx -@1: - mov ah, 9 - int 21h +1: + movb $0x9, %%ah + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 fcb: - db 0 ; 0 default drive + .byte 0 # 0 default drive fn1: - db "% -8s" ; 8 bytes + .ascii "% -8s" # 8 bytes fe1: - db "% -3s" ; 3 bytes + .ascii "% -3s" # 3 bytes wk1: - times 24 db 0 + .space 24 succstart: - db "Operation Success($" + .ascii "Operation Success($" succend: - db ')',13,10,'$' + .ascii ")\r\n$" faildtaset: - db "Set DTA Operation Failed",13,10,'$' + .ascii "Set DTA Operation Failed\r\n$" failopen: - db "Open Operation Failed",13,10,'$' + .ascii "Open Operation Failed\r\n$" failread: - db "Read Operation Failed",13,10,'$' + .ascii "Read Operation Failed\r\n$" altdta: - times 128 db 0 + .space 128 """ % (len(testdata), "test", "fil")) @@ -785,56 +754,6 @@ altdta: """MFS FCB file read alternate DTA""" self._test_fcb_read_alt_dta("MFS") - def test_fat_label_create_simple(self): - """FAT FCB label create simple""" - label_create(self, "FAT", None) - test_fat_label_create_simple.labeltest = True - - def test_fat_label_create_bpb12(self): - """FAT FCB label create BPB FAT12""" - label_create(self, "FAT", 'bpb12') - test_fat_label_create_bpb12.labeltest = True - - def test_fat_label_create_bpb16(self): - """FAT FCB label create BPB FAT16""" - label_create(self, "FAT", 'bpb16') - test_fat_label_create_bpb16.labeltest = True - - def test_fat_label_create_bpb32(self): - """FAT FCB label create BPB FAT32""" - label_create(self, "FAT", 'bpb32') - test_fat_label_create_bpb32.labeltest = True - - def test_fat_label_create_prefile(self): - """FAT FCB label create file beforehand""" - label_create(self, "FAT", 'prefile') - test_fat_label_create_prefile.labeltest = True - - def test_fat_label_create_predir(self): - """FAT FCB label create directory beforehand""" - label_create(self, "FAT", 'predir') - test_fat_label_create_predir.labeltest = True - - def test_fat_label_create_postfile(self): - """FAT FCB label create file afterwards""" - label_create(self, "FAT", 'postfile') - test_fat_label_create_postfile.labeltest = True - - def test_fat_label_create_postdir(self): - """FAT FCB label create directory afterwards""" - label_create(self, "FAT", 'postdir') - test_fat_label_create_postdir.labeltest = True - - def test_fat_label_create_on_lfns(self): - """FAT FCB label create on top of LFNs""" - label_create_on_lfns(self) - test_fat_label_create_on_lfns.labeltest = True - - def test_fat_label_create_noduplicate(self): - """FAT FCB label create no duplicate""" - label_create_noduplicate(self, "FAT") - test_fat_label_create_noduplicate.labeltest = True - def _test_fcb_write(self, fstype): testdir = self.mkworkdir('d') @@ -862,99 +781,98 @@ rem end """ % ename, newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + popw %%ds - push cs - pop ds - - mov ax, 1600h ; create file - mov dx, fcb - int 21h - cmp al, 0 + movw $0x1600, %%ax # create file + movw $fcb, %%dx + int $0x21 + cmpb $0, %%al jne prfailopen - mov si, data ; copy data to DTA - mov ax, 2f00h ; get DTA address in ES:BX - int 21h - mov di, bx - mov cx, datalen + movw $data, %%si # copy data to DTA + movw $0x2f00, %%ax # get DTA address in ES:BX + int $0x21 + movw %%bx, %%di + movw $DATALEN, %%cx cld repnz movsb - mov ax, 1500h ; write to file - mov dx, fcb - mov word [flrs], datalen; only the significant part - int 21h - cmp al , 0 + movw $0x1500, %%ax # write to file + movw $fcb, %%dx + movw $DATALEN, flrs # only the significant part + int $0x21 + cmpb $0, %%al jne prfailwrite - mov dx, donewrite - jmp @2 + movw $donewrite, %%dx + jmp 2f prfailwrite: - mov dx, failwrite - jmp @2 + movw $failwrite, %%dx + jmp 2f prfailopen: - mov dx, failopen - jmp @1 + movw $failopen, %%dx + jmp 1f -@2: - mov ax, 1000h ; close file - push dx - mov dx, fcb - int 21h - pop dx +2: + movw $0x1000, %%ax # close file + push %%dx + movw $fcb, %%dx + int $0x21 + popw %%dx -@1: - mov ah, 9 - int 21h +1: + movb $0x9, %%ah + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 data: - db "Operation Success(%s)",13,10,'$' -datalen equ $ - data - 1 + .ascii "Operation Success(%s)\r\n" +dend: +DATALEN = (dend - data) + .ascii "$" # for printing fcb: - db 0 ; 0 default drive + .byte 0 # 0 default drive fn1: - db "% -8s" ; 8 bytes + .ascii "% -8s" # 8 bytes fe1: - db "% -3s" ; 3 bytes + .ascii "% -3s" # 3 bytes fcbn: - dw 0 + .word 0 flrs: - dw 0 + .word 0 ffsz: - dd 0 + .long 0 fdlw: - dw 0 + .word 0 ftlw: - dw 0 + .word 0 res8: - times 8 db 0 + .space 8 fcbr: - db 0 + .byte 0 frrn: - dd 0 + .long 0 failopen: - db "Open Operation Failed",13,10,'$' + .ascii "Open Operation Failed\r\n$" failwrite: - db "Write Operation Failed",13,10,'$' + .ascii "Write Operation Failed\r\n$" donewrite: - db "Write Operation Done",13,10,'$' + .ascii "Write Operation Done\r\n$" """ % (testdata, "test", "fil")) @@ -1044,58 +962,55 @@ rem end """ % ename, newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds + movw $0x1700, %%ax + movw $fcb, %%dx + int $0x21 - mov ax, 1700h - mov dx, fcb - int 21h - - cmp al, 0 + cmpb $0, %%al je prsucc prfail: - mov dx, failmsg - jmp @1 + movw $failmsg, %%dx + jmp 1f prsucc: - mov dx, succmsg -@1: - mov ah, 9 - int 21h + movw $succmsg, %%dx +1: + movb $0x9, %%ah + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 fcb: - db 0 ; 0 default drive + .byte 0 # 0 default drive fn1: - db "% -8s" ; 8 bytes + .ascii "% -8s" # 8 bytes fe1: - db "% -3s" ; 3 bytes + .ascii "% -3s" # 3 bytes wk1: - times 5 db 0 + .space 5 fn2: - db "% -8s" ; 8 bytes + .ascii "% -8s" # 8 bytes fe2: - db "% -3s" ; 3 bytes + .ascii "% -3s" # 3 bytes wk2: - times 16 db 0 + .space 16 succmsg: - db "Rename Operation Success",13,10,'$' + .ascii "Rename Operation Success$" failmsg: - db "Rename Operation Failed",13,10,'$' + .ascii "Rename Operation Failed$" """ % (fn1, fe1, fn2, fe2)) @@ -1103,7 +1018,7 @@ failmsg: if fstype == "MFS": self.assertTrue(exists(join(testdir, f + "." + e)), msg) else: - self.assertRegex(results.upper(), r"%s( +|\.)%s" % (f.upper(), e.upper())) + self.assertRegex(results.upper(), "%s( +|\.)%s" % (f.upper(), e.upper())) if fstype == "MFS": results = self.runDosemu("testit.bat", config="""\ @@ -1264,52 +1179,49 @@ rem end """ % ename, newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds + movw $0x1300, %%ax + movw $fcb, %%dx + int $0x21 - mov ax, 1300h - mov dx, fcb - int 21h - - cmp al, 0 + cmpb $0, %%al je prsucc prfail: - mov dx, failmsg - jmp @1 + movw $failmsg, %%dx + jmp 1f prsucc: - mov dx, succmsg -@1: - mov ah, 9 - int 21h + movw $succmsg, %%dx +1: + movb $0x9, %%ah + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 fcb: - db 0 ; 0 default drive + .byte 0 # 0 default drive fn1: - db "% -8s" ; 8 bytes + .ascii "% -8s" # 8 bytes fe1: - db "% -3s" ; 3 bytes + .ascii "% -3s" # 3 bytes wk1: - times 25 db 0 + .space 25 succmsg: - db "Delete Operation Success",13,10,'$' + .ascii "Delete Operation Success$" failmsg: - db "Delete Operation Failed",13,10,'$' + .ascii "Delete Operation Failed$" """ % (fn1, fe1)) @@ -1317,13 +1229,13 @@ failmsg: if fstype == "MFS": self.assertTrue(exists(join(testdir, f + "." + e)), msg) else: - self.assertRegex(results.upper(), r"%s( +|\.)%s" % (f.upper(), e.upper())) + self.assertRegex(results.upper(), "%s( +|\.)%s" % (f.upper(), e.upper())) def assertIsNotPresent(testdir, results, fstype, f, e, msg=None): if fstype == "MFS": self.assertFalse(exists(join(testdir, f + "." + e)), msg) else: - self.assertNotRegex(results.upper(), r"%s( +|\.)%s" % (f.upper(), e.upper())) + self.assertNotRegex(results.upper(), "%s( +|\.)%s" % (f.upper(), e.upper())) if fstype == "MFS": results = self.runDosemu("testit.bat", config="""\ @@ -1455,102 +1367,99 @@ rem end """ % ename, newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds + # Get DTA -> ES:BX + movw $0x2f00, %%ax + int $0x21 + pushw %%es + pushw %%bx + popl pdta - ; Get DTA -> ES:BX - mov ax, 2f00h - int 21h - push es - push bx - pop long [pdta] - - ; FindFirst + # FindFirst findfirst: - mov ax, 1100h - mov dx, fcb - int 21h + movw $0x1100, %%ax + movw $fcb, %%dx + int $0x21 - cmp al, 0 + cmpb $0, %%al je prsucc prfail: - mov dx, failmsg - mov ah, 9 - int 21h + movw $failmsg, %%dx + movb $0x9, %%ah + int $0x21 jmp exit prsucc: - mov dx, succmsg - mov ah, 9 - int 21h + movw $succmsg, %%dx + movb $0x9, %%ah + int $0x21 prfilename: - push ds - lds si, [pdta] - inc si + push %%ds + lds pdta, %%si + inc %%si - push cs - pop es - mov di, prires - inc di + push %%cs + pop %%es + movw $prires, %%di + inc %%di - mov cx, 11 + movw $11, %%cx cld repne movsb - pop ds - mov dx, prires - mov ah, 9 - int 21h + pop %%ds + movw $prires, %%dx + movb $0x9, %%ah + int $0x21 - ; FindNext + # FindNext findnext: - mov ax, 1200h - mov dx, fcb - int 21h + movw $0x1200, %%ax + movw $fcb, %%dx + int $0x21 - cmp al, 0 + cmpb $0, %%al je prfilename exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 fcb: - db 0 ; 0 default drive + .byte 0 # 0 default drive fn1: - db "% -8s" ; 8 bytes + .ascii "% -8s" # 8 bytes fe1: - db "% -3s" ; 3 bytes + .ascii "% -3s" # 3 bytes wk1: - times 25 db 0 + .space 25 pdta: - dd 0 + .long 0 prires: - db "(" + .ascii "(" fname: - times 8 db 20 + .space 8, 20 fext: - times 3 db 20 - db ')',13,10,'$' + .space 3, 20 + .ascii ")\r\n$" succmsg: - db "Find Operation Success",13,10,'$' + .ascii "Find Operation Success\r\n$" failmsg: - db "Find Operation Failed",13,10,'$' + .ascii "Find Operation Failed\r\n$" """ % (fn1, fe1)) @@ -1668,107 +1577,104 @@ rem end """ % (testdata, ename), newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds - - mov ax, 3d00h ; open file readonly - mov dx, fname - int 21h + movw $0x3d00, %%ax # open file readonly + movw $fname, %%dx + int $0x21 jc prfailopen - mov word [fhndl], ax + movw %%ax, fhndl - mov ax, 3f00h ; read from file, should be partial (35) - mov bx, word [fhndl] - mov cx, 64 - mov dx, fdata - int 21h + movw $0x3f00, %%ax # read from file, should be partial (35) + movw fhndl, %%bx + movw $64, %%cx + movw $fdata, %%dx + int $0x21 jc prfailread - cmp ax, 35 + cmpw $35, %%ax jne prnumread - mov ax, 3f00h ; read from file again to get EOF - mov bx, word [fhndl] - mov cx, 64 - mov dx, fdata - int 21h + movw $0x3f00, %%ax # read from file again to get EOF + movw fhndl, %%bx + movw $64, %%cx + movw $fdata, %%dx + int $0x21 jc prcarryset - cmp ax, 0 + cmpw $0, %%ax jne praxnotzero jmp prsucc prfailopen: - mov dx, failopen - jmp @1 + movw $failopen, %%dx + jmp 1f prfailread: - mov dx, failread - jmp @2 + movw $failread, %%dx + jmp 2f prnumread: - mov dx, numread - jmp @2 + movw $numread, %%dx + jmp 2f praxnotzero: - mov dx, axnotzero - jmp @2 + movw $axnotzero, %%dx + jmp 2f prcarryset: - mov dx, carryset - jmp @2 + movw $carryset, %%dx + jmp 2f prsucc: - mov byte [fdata + 32], ')' - mov byte [fdata + 33], 13 - mov byte [fdata + 34], 10 - mov byte [fdata + 35], '$' - mov dx, success - jmp @2 + movb $')', (fdata + 32) + movb $'\r', (fdata + 33) + movb $'\n', (fdata + 34) + movb $'$', (fdata + 35) + movw $success, %%dx + jmp 2f -@2: - mov ax, 3e00h ; close file - mov bx, word [fhndl] - int 21h +2: + movw $0x3e00, %%ax # close file + movw fhndl, %%bx + int $0x21 -@1: - mov ah, 9 ; print string - int 21h +1: + movb $0x9, %%ah # print string + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 fname: - db "%s",0 + .asciz "%s" fhndl: - dw 0 + .word 0 success: - db "Operation Success(" + .ascii "Operation Success(" fdata: - times 64 db 0 + .space 64 failopen: - db "Open Operation Failed",13,10,'$' + .ascii "Open Operation Failed\r\n$" failread: - db "Read Operation Failed",13,10,'$' + .ascii "Read Operation Failed\r\n$" numread: - db "Partial Read Not 35 Chars",13,10,'$' + .ascii "Partial Read Not 35 Chars\r\n$" carryset: - db "Carry Set at EOF",13,10,'$' + .ascii "Carry Set at EOF\r\n$" axnotzero: - db "AX Not Zero at EOF",13,10,'$' + .ascii "AX Not Zero at EOF\r\n$" """ % "test.fil") @@ -1815,108 +1721,105 @@ rem end """ % (testdata, ename), newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds + movw $0x1a00, %%ax # set DTA + movw $altdta, %%dx + int $0x21 - mov ax, 1a00h ; set DTA - mov dx, altdta - int 21h - - mov ax, 2f00h ; get DTA address in ES:BX - int 21h - mov ax, cs - mov dx, es - cmp dx, ax + movw $0x2f00, %%ax # get DTA address in ES:BX + int $0x21 + movw %%cs, %%ax + movw %%es, %%dx + cmpw %%ax, %%dx jne prfaildtaset - cmp bx, altdta + cmpw $altdta, %%bx jne prfaildtaset - mov ax, 3d00h ; open file readonly - mov dx, fname - int 21h + movw $0x3d00, %%ax # open file readonly + movw $fname, %%dx + int $0x21 jc prfailopen - mov word [fhndl], ax + movw %%ax, fhndl - mov ax, 3f00h ; read from file, should be partial (35) - mov bx, word [fhndl] - mov cx, 64 - mov dx, fdata - int 21h + movw $0x3f00, %%ax # read from file, should be partial (35) + movw fhndl, %%bx + movw $64, %%cx + movw $fdata, %%dx + int $0x21 jc prfailread - cmp ax, 35 + cmpw $35, %%ax jne prnumread jmp prsucc prfaildtaset: - mov dx, faildtaset - jmp @1 + movw $faildtaset, %%dx + jmp 1f prfailopen: - mov dx, failopen - jmp @1 + movw $failopen, %%dx + jmp 1f prfailread: - mov dx, failread - jmp @2 + movw $failread, %%dx + jmp 2f prnumread: - mov dx, numread - jmp @2 + movw $numread, %%dx + jmp 2f prsucc: - mov byte [fdata + 32], ')' - mov byte [fdata + 33], 13 - mov byte [fdata + 34], 10 - mov byte [fdata + 35], '$' - mov dx, success - jmp @2 + movb $')', (fdata + 32) + movb $'\r', (fdata + 33) + movb $'\n', (fdata + 34) + movb $'$', (fdata + 35) + movw $success, %%dx + jmp 2f -@2: - mov ax, 3e00h ; close file - mov bx, word [fhndl] - int 21h +2: + movw $0x3e00, %%ax # close file + movw fhndl, %%bx + int $0x21 -@1: - mov ah, 9 ; print string - int 21h +1: + movb $0x9, %%ah # print string + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 fname: - db "%s",0 + .asciz "%s" fhndl: - dw 0 + .word 0 success: - db "Operation Success(" + .ascii "Operation Success(" fdata: - times 64 db 0 + .space 64 faildtaset: - db "Set DTA Operation Failed",13,10,'$' + .ascii "Set DTA Operation Failed\r\n$" failopen: - db "Open Operation Failed",13,10,'$' + .ascii "Open Operation Failed\r\n$" failread: - db "Read Operation Failed",13,10,'$' + .ascii "Read Operation Failed\r\n$" numread: - db "Partial Read Not 35 Chars",13,10,'$' + .ascii "Partial Read Not 35 Chars\r\n$" altdta: - times 128 db 0 + .space 128 """ % "test.fil") @@ -2046,49 +1949,46 @@ rem end """ % (extrad, ename), newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds + push %%cs + pop %%es - push cs - pop ds - push cs - pop es - - mov ax, 5600h - mov dx, src - mov di, dst - int 21h + movw $0x5600, %%ax + movw $src, %%dx + movw $dst, %%di + int $0x21 jnc prsucc prfail: - mov dx, failmsg - jmp @1 + movw $failmsg, %%dx + jmp 1f prsucc: - mov dx, succmsg -@1: - mov ah, 9 - int 21h + movw $succmsg, %%dx +1: + movb $0x9, %%ah + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 src: - db "%s",0 ; Full path + .asciz "%s" # Full path dst: - db "%s",0 ; Full path + .asciz "%s" # Full path succmsg: - db "Rename Operation Success",13,10,'$' + .ascii "Rename Operation Success$" failmsg: - db "Rename Operation Failed",13,10,'$' + .ascii "Rename Operation Failed$" """ % (fn1 + "." + fe1, fn2 + "." + fe2)) @@ -2096,7 +1996,7 @@ failmsg: if fstype == "MFS": self.assertTrue(exists(join(testdir, f + "." + e)), msg) else: - self.assertRegex(results.upper(), r"%s( +|\.)%s" % (f.upper(), e.upper()), msg) + self.assertRegex(results.upper(), "%s( +|\.)%s" % (f.upper(), e.upper()), msg) def assertIsPresentDir(testdir, results, fstype, f, msg=None): if fstype == "MFS": @@ -2211,44 +2111,41 @@ rem end """ % ename, newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds - - mov ax, 4100h - mov dx, src - int 21h + movw $0x4100, %%ax + movw $src, %%dx + int $0x21 jnc prsucc prfail: - mov dx, failmsg - jmp @1 + movw $failmsg, %%dx + jmp 1f prsucc: - mov dx, succmsg -@1: - mov ah, 9 - int 21h + movw $succmsg, %%dx +1: + movb $0x9, %%ah + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 src: - db "%s",0 ; Full path + .asciz "%s" # Full path succmsg: - db "Delete Operation Success",13,10,'$' + .ascii "Delete Operation Success$" failmsg: - db "Delete Operation Failed",13,10,'$' + .ascii "Delete Operation Failed$" """ % (fn1 + "." + fe1)) @@ -2256,7 +2153,7 @@ failmsg: if fstype == "MFS": self.assertFalse(exists(join(testdir, f + "." + e)), msg) else: - self.assertNotRegex(results.upper(), r"%s( +|\.)%s" % (f.upper(), e.upper())) + self.assertNotRegex(results.upper(), "%s( +|\.)%s" % (f.upper(), e.upper())) if fstype == "MFS": results = self.runDosemu("testit.bat", config="""\ @@ -2336,100 +2233,101 @@ rem end """ % ename, newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds + # Get DTA -> ES:BX + movw $0x2f00, %%ax + int $0x21 + pushw %%es + pushw %%bx + popl pdta - ; Get DTA -> ES:BX - mov ax, 2f00h - int 21h - push es - push bx - pop long [pdta] - - ; FindFirst + # FindFirst findfirst: - mov ax, 4e00h - mov cx, 0 - mov dx, fpatn - int 21h + movw $0x4e00, %%ax + movw $0, %%cx + movw $fpatn, %%dx + int $0x21 jnc prsucc prfail: - mov dx, failmsg - mov ah, 9 - int 21h + movw $failmsg, %%dx + movb $0x9, %%ah + int $0x21 jmp exit prsucc: - mov dx, succmsg - mov ah, 9 - int 21h + movw $succmsg, %%dx + movb $0x9, %%ah + int $0x21 prfilename: - push ds - lds ax, [pdta] - add ax, 1eh - mov si, ax + push %%ds + lds pdta, %%ax + addw $0x1e, %%ax + movw %%ax, %%si - push cs - pop es - mov di, prires + 1 + push %%cs + pop %%es + movw $(prires + 1), %%di - mov cx, 13 + movw $13, %%cx cld -@1: - cmp byte [ds:si], 0 - je @2 +1: + cmpb $0, %%ds:(%%si) + je 2f movsb - loop @1 + loop 1b -@2: - mov byte [es:di], ')' - mov byte [es:di + 1], 13 - mov byte [es:di + 2], 10 - mov byte [es:di + 3], '$' +2: + movb $')', %%es:(%%di) + inc %%di + movb $'\r', %%es:(%%di) + inc %%di + movb $'\n', %%es:(%%di) + inc %%di + movb $'$', %%es:(%%di) + inc %%di - pop ds - mov dx, prires - mov ah, 9 - int 21h + pop %%ds + movw $prires, %%dx + movb $0x9, %%ah + int $0x21 - ; FindNext + # FindNext findnext: - mov ax, 4f00h - int 21h + movw $0x4f00, %%ax + int $0x21 jnc prfilename exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 fpatn: - db "%s",0 + .asciz "%s" pdta: - dd 0 + .long 0 prires: - db "(" - times 32 db 0 + .ascii "(" + .space 32 succmsg: - db "Findfirst Operation Success",13,10,'$' + .ascii "Findfirst Operation Success\r\n$" failmsg: - db "Findfirst Operation Failed",13,10,'$' + .ascii "Findfirst Operation Failed\r\n$" """ % (fn1 + "." + fe1)) @@ -2525,42 +2423,42 @@ $_floppy_a = "" ename = "ds2fndfi" - ATTR = "0x00" + ATTR = "$0x00" if testname == "file_exists": - FSPEC = r"\fileexst.ext" + FSPEC = r"\\fileexst.ext" elif testname == "file_exists_as_dir": - FSPEC = r"\fileexst.ext\somefile.ext" + FSPEC = r"\\fileexst.ext\\somefile.ext" elif testname == "file_not_found": - FSPEC = r"\Notfname.ext" + FSPEC = r"\\Notfname.ext" elif testname == "no_more_files": - FSPEC = r"\????????.??x" + FSPEC = r"\\????????.??x" elif testname == "path_not_found_wc": - FSPEC = r"\NotDir\????????.???" + FSPEC = r"\\NotDir\\????????.???" elif testname == "path_not_found_pl": - FSPEC = r"\NotDir\plainfil.txt" + FSPEC = r"\\NotDir\\plainfil.txt" elif testname == "path_exists_empty": - FSPEC = r"\DirExist" + FSPEC = r"\\DirExist" elif testname == "path_exists_not_empty": - FSPEC = r"\DirExis2" + FSPEC = r"\\DirExis2" elif testname == "path_exists_file_not_dir": - FSPEC = r"\DirExis2\fileexst.ext" - ATTR = "0x10" + FSPEC = r"\\DirExis2\\fileexst.ext" + ATTR = "$0x10" elif testname == "dir_exists_pl": - FSPEC = r"\DirExis2" - ATTR = "0x10" + FSPEC = r"\\DirExis2" + ATTR = "$0x10" elif testname == "dir_exists_wc": - FSPEC = r"\Di?Exis?" - ATTR = "0x10" + FSPEC = r"\\Di?Exis?" + ATTR = "$0x10" elif testname == "dir_not_exists_pl": - FSPEC = r"\dirNOTex" - ATTR = "0x10" + FSPEC = r"\\dirNOTex" + ATTR = "$0x10" elif testname == "dir_not_exists_wc": - FSPEC = r"\dirNOTex\wi??card.???" - ATTR = "0x10" + FSPEC = r"\\dirNOTex\\wi??card.???" + ATTR = "$0x10" elif testname == "dir_not_exists_fn": - FSPEC = r"\dirNOTex\somefile.ext" - ATTR = "0x10" + FSPEC = r"\\dirNOTex\\somefile.ext" + ATTR = "$0x10" self.mkfile("testit.bat", """\ d: @@ -2574,77 +2472,74 @@ rem end """ % ename, newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds - - mov ax, 4e00h - mov cx, %s - mov dx, fspec - int 21h + movw $0x4e00, %%ax + movw %s, %%cx + movw $fspec, %%dx + int $0x21 jnc prsucc - cmp ax, 2 + cmpw $0x02, %%ax je fail02 - cmp ax, 3 + cmpw $0x03, %%ax je fail03 - cmp ax, 12h + cmpw $0x12, %%ax je fail12 jmp genfail fail02: - mov dx, filenotfound - jmp @1 + movw $filenotfound, %%dx + jmp 1f fail03: - mov dx, pathnotfoundmsg - jmp @1 + movw $pathnotfoundmsg, %%dx + jmp 1f fail12: - mov dx, nomoremsg - jmp @1 + movw $nomoremsg, %%dx + jmp 1f genfail: - mov dx, genfailmsg - jmp @1 + movw $genfailmsg, %%dx + jmp 1f prsucc: - mov dx, succmsg + movw $succmsg, %%dx -@1: - mov ah, 9 - int 21h +1: + movb $0x9, %%ah + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 fspec: - db "%s",0 ; Full path + .asciz "%s" # Full path succmsg: - db "FindFirst Operation Success",13,10,'$' + .ascii "FindFirst Operation Success\r\n$" filenotfound: - db "FindFirst Operation Returned FILE_NOT_FOUND(0x02)",13,10,'$' + .ascii "FindFirst Operation Returned FILE_NOT_FOUND(0x02)\r\n$" pathnotfoundmsg: - db "FindFirst Operation Returned PATH_NOT_FOUND(0x03)",13,10,'$' + .ascii "FindFirst Operation Returned PATH_NOT_FOUND(0x03)\r\n$" nomoremsg: - db "FindFirst Operation Returned NO_MORE_FILES(0x12)",13,10,'$' + .ascii "FindFirst Operation Returned NO_MORE_FILES(0x12)\r\n$" genfailmsg: - db "FindFirst Operation Returned Unexpected Errorcode",13,10,'$' + .ascii "FindFirst Operation Returned Unexpected Errorcode\r\n$" """ % (ATTR, FSPEC)) @@ -2819,113 +2714,114 @@ rem end """ % ename, newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text + push %%cs + pop %%ds - push cs - pop ds + # Get DTA -> ES:BX + movw $0x2f00, %%ax + int $0x21 + pushw %%es + pushw %%bx + popl pdta - ; Get DTA -> ES:BX - mov ax, 2f00h - int 21h - push es - push bx - pop long [pdta] + # First FindFirst + movw $0x4e00, %%ax + movw $0, %%cx + movw $fwild, %%dx + int $0x21 - ; First FindFirst - mov ax, 4e00h - mov cx, 0 - mov dx, fwild - int 21h + # Set alternate DTA + movw $0x1a00, %%ax + movw $altdta, %%dx + int $0x21 - ; Set alternate DTA - mov ax, 1a00h - mov dx, altdta - int 21h + # Second FindFirst + movw $0x4e00, %%ax + movw $0, %%cx + movw $fsmpl, %%dx + int $0x21 - ; Second FindFirst - mov ax, 4e00h - mov cx, 0 - mov dx, fsmpl - int 21h + # Set default DTA + movw $0x1a00, %%ax + lds pdta, %%dx + int $0x21 - ; Set default DTA - mov ax, 1a00h - lds dx, [pdta] - int 21h - - ; FindNext - mov ax, 4f00h - int 21h + # FindNext + movw $0x4f00, %%ax + int $0x21 jnc prsucc prfail: - mov dx, failmsg - mov ah, 9 - int 21h + movw $failmsg, %%dx + movb $0x9, %%ah + int $0x21 jmp exit prsucc: - push ds - lds ax, [pdta] - add ax, 1eh - mov si, ax + push %%ds + lds pdta, %%ax + addw $0x1e, %%ax + movw %%ax, %%si - push cs - pop es - mov di, prires + 1 + push %%cs + pop %%es + movw $(prires + 1), %%di - mov cx, 13 + movw $13, %%cx cld -@1: - cmp byte [ds:si], 0 - je @2 +1: + cmpb $0, %%ds:(%%si) + je 2f movsb - loop @1 + loop 1b -@2: - mov byte [es:di], ')' - mov byte [es:di + 1], 13 - mov byte [es:di + 2], 10 - mov byte [es:di + 3], '$' +2: + movb $')', %%es:(%%di) + inc %%di + movb $'\r', %%es:(%%di) + inc %%di + movb $'\n', %%es:(%%di) + inc %%di + movb $'$', %%es:(%%di) + inc %%di - pop ds - mov dx, succmsg - mov ah, 9 - int 21h + pop %%ds + movw $succmsg, %%dx + movb $0x9, %%ah + int $0x21 exit: - mov ah, 4ch - int 21h - -section .data + movb $0x4c, %%ah + int $0x21 fwild: - db "a*.txt",0 + .asciz "a*.txt" fsmpl: - db "%s",0 + .asciz "%s" altdta: - times 0x80 db 0 + .space 0x80 pdta: - dd 0 + .long 0 succmsg: - db "Findnext Operation Success" + .ascii "Findnext Operation Success" prires: - db "(" - times 32 db 0 + .ascii "(" + .space 32 failmsg: - db "Findnext Operation Failed",13,10,'$' + .ascii "Findnext Operation Failed\r\n$" """ % fsmpl) @@ -2965,118 +2861,117 @@ rem end """ % (ename, cmdline), newline="\r\n") # compile sources - self.mkcom_with_nasm(ename, r""" -bits 16 -cpu 386 + self.mkcom_with_gas(ename, r""" +.text +.code16 -org 100h + .globl _start16 +_start16: -section .text +# designate target segment + push %%cs + pop %%ax + addw $0x0200, %%ax + movw %%ax, %%es -; designate target segment - push cs - pop ax - add ax, 0200h - mov es, ax +# create PSP in memory + movw %%es, %%dx + movw $0x2600, %%ax + int $0x21 -; create PSP in memory - mov dx, es - mov ax, 2600h - int 21h - -; see if the exit field is set - cmp word [es:0000], 20cdh +# see if the exit field is set + cmpw $0x20cd, %%es:(0x0000) jne extfail -; see if the parent PSP is zero - cmp word [es:0016h], 0 +# see if the parent PSP is zero + cmpw $0x0000, %%es:(0x0016) je pntzero -; see if the parent PSP points to a PSP - push es - push word [es:0016h] - pop es - cmp word [es:0000h], 20cdh - pop es +# see if the parent PSP points to a PSP + push %%es + pushw %%es:(0x0016) + pop %%es + cmpw $0x20cd, %%es:(0x0000) + pop %%es jne pntnpsp -; see if the 'INT 21,RETF' is there - cmp word [es:0050h], 21cdh +# see if the 'INT 21,RETF' is there + cmpw $0x21cd, %%es:(0x0050) jne int21ms - cmp byte [es:0052h], 0cbh + cmpb $0xcb, %%es:(0x0052) jne int21ms -; see if the cmdtail is there - movzx cx, byte [es:0080h] - cmp cx, %d +# see if the cmdtail is there + movzx %%es:(0x0080), %%cx + cmpw $%d, %%cx jne cmdlngth - inc cx - mov si, cmdline - mov di, 81h + inc %%cx + mov $cmdline, %%si + mov $0x0081, %%di cld repe cmpsb jne cmdtail success: - mov dx, successmsg + movw $successmsg, %%dx jmp exit extfail: - mov dx, extfailmsg + movw $extfailmsg, %%dx jmp exit pntzero: - mov dx, pntzeromsg + movw $pntzeromsg, %%dx jmp exit pntnpsp: - mov dx, pntnpspmsg + movw $pntnpspmsg, %%dx jmp exit int21ms: - mov dx, int21msmsg + movw $int21msmsg, %%dx jmp exit cmdlngth: - mov dx, cmdlngthmsg + movw $cmdlngthmsg, %%dx jmp exit cmdtail: - mov dx, cmdtailmsg + movw $cmdtailmsg, %%dx jmp exit exit: - mov ah, 9 - int 21h + movb $0x9, %%ah + int $0x21 - mov ah, 4ch - int 21h + movb $0x4c, %%ah + int $0x21 extfailmsg: - db "PSP exit field not set to CD20",13,10,'$' + .ascii "PSP exit field not set to CD20\r\n$" pntzeromsg: - db "PSP parent is zero",13,10,'$' + .ascii "PSP parent is zero\r\n$" pntnpspmsg: - db "PSP parent doesn't point to a PSP",13,10,'$' + .ascii "PSP parent doesn't point to a PSP\r\n$" int21msmsg: - db "PSP is missing INT21, RETF",13,10,'$' + .ascii "PSP is missing INT21, RETF\r\n$" cmdlngthmsg: - db "PSP has incorrect command length",13,10,'$' + .ascii "PSP has incorrect command length\r\n$" cmdtailmsg: - db "PSP has incorrect command tail",13,10,'$' + .ascii "PSP has incorrect command tail\r\n$" successmsg: - db "PSP structure okay",13,10,'$' + .ascii "PSP structure okay\r\n$" -; 05 20 54 45 53 54 0d +# 05 20 54 45 53 54 0d cmdline: - db " %s",13 + .ascii " %s\r" """ % (1 + len(cmdline), cmdline)) @@ -3194,7 +3089,6 @@ $_floppy_a = "" self.assertRegex(results, r"Calling real mode procedure which called callback successful") self.assertRegex(results, r"Child process terminated okay, back in real mode") self.assertNotIn("fail", results) - test_memory_dpmi_ecm_alloc.dpmitest=True def test_memory_dpmi_ecm_mini(self): """Memory DPMI (ECM) mini""" @@ -3210,7 +3104,6 @@ $_floppy_a = "" self.assertRegex(results, r"32-bit code segment breakpoint at") self.assertRegex(results, r"Welcome in 32-bit protected mode") self.assertNotIn("fail", results) - test_memory_dpmi_ecm_mini.dpmitest=True def test_memory_dpmi_ecm_modeswitch(self): """Memory DPMI (ECM) Mode Switch""" @@ -3228,7 +3121,6 @@ $_floppy_a = "" self.assertRegex(results, r"Mode-switched to real mode") self.assertRegex(results, r"In protected mode again") self.assertNotIn("fail", results) - test_memory_dpmi_ecm_modeswitch.dpmitest=True def test_memory_dpmi_ecm_psp(self): """Memory DPMI (ECM) psp""" @@ -3252,52 +3144,116 @@ $_floppy_a = "" self.assertRegex(results, r"Calling real mode procedure which called callback successful") self.assertRegex(results, r"Child process terminated okay, back in real mode") self.assertNotIn("fail", results) - test_memory_dpmi_ecm_psp.dpmitest=True + + def _test_memory_dpmi_japheth(self, switch): + self.unTarOrSkip("VARIOUS.tar", [ + ("dpmihxrt218.exe", "65fda018f4422c39dbf36860aac2c537cfee466b"), + ]) + rename(self.workdir / "dpmihxrt218.exe", self.workdir / "dpmi.exe") + + self.mkfile("testit.bat", """\ +c:\\dpmi %s +rem end +""" % switch, newline="\r\n") + + return self.runDosemu("testit.bat", config="""\ +$_hdimage = "dXXXXs/c:hdtype1 +1" +$_floppy_a = "" +""", timeout=60) def test_memory_dpmi_japheth(self): """Memory DPMI (Japheth) ''""" - memory_dpmi_japheth(self, '') - test_memory_dpmi_japheth.dpmitest=True + results = self._test_memory_dpmi_japheth("") + +#Cpu is in V86-mode +#Int 15h, ax=e801h, extended memory: 8256 kB +#int 15h, ax=e820h, available memory at 000100000, size 8256 kB +#XMS v3.0 host found, largest free block: 8192 kB +#No VCPI host found +#DPMI v0.90 host found, cpu: 05, support of 32-bit clients: 1 +#entry initial switch to protected-mode: F000:F500 +#size task-specific memory: 230 paragraphs +#now in protected mode, client CS/SS/DS/FS/GS: A7/AF/AF/0/0 +#Eflags=206, ES (=PSP): B7 (environment: BF, parent PSP segm: 431) +#GDTR: 17.A308100 IDTR: 7FF.A308200 LDTR: 0 TR: 0 +#DPMI version flags: 5 +#master/slave PICs base: 08/70 +#state save protected-mode: 97:1, real-mode: F000:F514 +#size state save buffer: 52 bytes +#raw jump to real-mode: 97:0, protected-mode: F000:F513 +#largest free/lockable memory block (kB): 131004/131004 +#free unlocked (=virtual) memory (kB): 131004 +#total/free address space (kB): 32768/32768 +#total/free physical memory (kB): 131072/131004 +#Coprocessor status: 4D +#vendor: DOSEMU Version 2.0, version: 0.90 +#capabilities: 78 +#vendor 'MS-DOS' API entry: 97:130 +#'MS-DOS' API, ax=100h (get LDT selector): E7 + + self.assertRegex(results, r"DPMI v0.90 host found, cpu: \d+, support of 32-bit clients: 1") + self.assertRegex(results, r"DPMI version flags: 5") + self.assertRegex(results, r"vendor: DOSEMU Version 2.0, version: 0.90") + self.assertRegex(results, r"capabilities: 78") def test_memory_dpmi_japheth_c(self): """Memory DPMI (Japheth) '-c'""" - memory_dpmi_japheth(self, '-c') - test_memory_dpmi_japheth_c.dpmitest=True - - def test_memory_dpmi_japheth_d(self): - """Memory DPMI (Japheth) '-d'""" - memory_dpmi_japheth(self, '-d') - test_memory_dpmi_japheth_d.dpmitest=True - - def test_memory_dpmi_japheth_e(self): - """Memory DPMI (Japheth) '-e'""" - memory_dpmi_japheth(self, '-e') - test_memory_dpmi_japheth_e.dpmitest=True + results = self._test_memory_dpmi_japheth("-c") + self.assertRegex(results, r"time.*CLI/STI: \d+ ms") + self.assertRegex(results, r"time.*interrupts via DPMI: \d+ ms") def test_memory_dpmi_japheth_i(self): """Memory DPMI (Japheth) '-i'""" - memory_dpmi_japheth(self, '-i') - test_memory_dpmi_japheth_i.dpmitest=True + results = self._test_memory_dpmi_japheth("-i") + self.assertRegex(results, r"time.*IN 21: \d+ ms") def test_memory_dpmi_japheth_m(self): """Memory DPMI (Japheth) '-m'""" - memory_dpmi_japheth(self, '-m') - test_memory_dpmi_japheth_m.dpmitest=True + results = self._test_memory_dpmi_japheth("-m") + t = re.search(r"alloc largest mem block \(size=(\d+) kB\) returned handle [0-9a-fA-F]+, base \d+", results) + self.assertIsNotNone(t, "Unable to parse memory block size") + size = int(t.group(1)) + self.assertGreater(size, 128000, results) def test_memory_dpmi_japheth_r(self): """Memory DPMI (Japheth) '-r'""" - memory_dpmi_japheth(self, '-r') - test_memory_dpmi_japheth_r.dpmitest=True + results = self._test_memory_dpmi_japheth("-r") + self.assertRegex(results, r"time.*INT 69h: \d+ ms") + self.assertRegex(results, r"time.*INT 31h, AX=0300h \(Sim INT 69h\): \d+ ms") + self.assertRegex(results, r"time.*real-mode callback: \d+ ms") + self.assertRegex(results, r"time.*raw mode switches PM->RM->PM: \d+ ms") def test_memory_dpmi_japheth_t(self): """Memory DPMI (Japheth) '-t'""" - memory_dpmi_japheth(self, '-t') - test_memory_dpmi_japheth_t.dpmitest=True + results = self._test_memory_dpmi_japheth("-t") - def test_memory_dpmi_japheth_z(self): - """Memory DPMI (Japheth) '-z'""" - memory_dpmi_japheth(self, '-z') - test_memory_dpmi_japheth_z.dpmitest=True +#C:\>c:\dpmi -t +#allocated rm callback FF10:214, rmcs=AF:20E4 +#calling rm proc [53A:8B6], rm cx=1 +# inside rm proc, ss:sp=7A8:1FC, cx=1 +# calling rm callback FF10:214 +# inside rm callback, ss:esp=9F:EFF4, ds:esi=F7:1FC +# es:edi=AF:20E4, rm ss:sp=7A8:1FC, rm cx=1 +# calling rm proc [53A:8B6] +# inside rm proc, ss:sp=7A8:1F8, cx=2 +# calling rm callback FF10:214 +# inside rm callback, ss:esp=9F:EFE0, ds:esi=F7:1F8 +# es:edi=AF:20E4, rm ss:sp=7A8:1F8, rm cx=2 +# exiting +# back in rm proc, ss:sp=7A8:1F8; exiting +# back in rm callback, rm ss:sp=7A8:1FC, rm cx=2; exiting +# back in rm proc, ss:sp=7A8:1FC; exiting +#back in protected-mode, rm ss:sp=7A8:200, rm cx=2 + + self.assertRegex(results, re.compile(r"^allocated rm callback", re.MULTILINE)) + self.assertRegex(results, re.compile(r"^ inside rm proc", re.MULTILINE)) + self.assertRegex(results, re.compile(r"^ inside rm callback", re.MULTILINE)) + self.assertRegex(results, re.compile(r"^ inside rm proc", re.MULTILINE)) + self.assertRegex(results, re.compile(r"^ inside rm callback", re.MULTILINE)) + self.assertRegex(results, re.compile(r"^ back in rm proc", re.MULTILINE)) + self.assertRegex(results, re.compile(r"^ back in rm callback", re.MULTILINE)) + self.assertRegex(results, re.compile(r"^ back in rm proc", re.MULTILINE)) + self.assertRegex(results, re.compile(r"^back in protected-mode", re.MULTILINE)) def test_memory_emm286_borland(self): """Memory EMM286 (Borland)""" @@ -3311,7 +3267,7 @@ $_floppy_a = "" # Modify the config.sys contents = (self.workdir / self.confsys).read_text() contents = re.sub(r"device=(c:\\)?dosemu\\umb.sys", r"device=\1dosemu\\umb.sys /full", contents) - contents = re.sub(r"devicehigh=(c:\\)?dosemu\\ems.sys", r"devicehigh=c:\\emm286.exe 2048", contents) + contents = re.sub(r"devicehigh=(c:\\)?dosemu\\ems.sys", r"devicehigh=c:\\emm286.exe 4096", contents) self.mkfile(self.confsys, contents, newline="\r\n") self.mkfile("testit.bat", """\ @@ -3332,66 +3288,6 @@ $_floppy_a = "" """Memory EMS (Borland)""" memory_ems_borland(self) - def test_memory_hma_a20(self): - """Memory HMA a20 toggle""" - memory_hma_a20(self) - test_memory_hma_a20.hmatest = True - - def test_memory_hma_alloc(self): - """Memory HMA allocation""" - memory_hma_alloc(self) - test_memory_hma_alloc.hmatest = True - - def test_memory_hma_alloc3(self): - """Memory HMA alloc/resize/dealloc""" - memory_hma_alloc3(self) - test_memory_hma_alloc3.hmatest = True - - def test_memory_hma_freespace(self): - """Memory HMA freespace""" - memory_hma_freespace(self) - test_memory_hma_freespace.hmatest = True - - def test_memory_hma_chain(self): - """Memory HMA get chain""" - memory_hma_chain(self) - test_memory_hma_chain.hmatest = True - - def test_memory_xms(self): - """Memory XMS""" - memory_xms(self) - test_memory_xms.xmstest = True - - def test_memory_dpmi10_ldt(self): - """Memory DPMI-1.0 LDT""" - memory_dpmi_dpmi10_ldt(self) - test_memory_dpmi10_ldt.dpmitest = True - - def test_memory_dpmi_leak_check_nofree(self): - """Memory DPMI Leak Check No Free""" - memory_dpmi_leak_check(self, 'nofree') - test_memory_dpmi_leak_check_nofree.dpmitest = True - - def test_memory_dpmi_leak_check_normal(self): - """Memory DPMI Leak Check Normal""" - memory_dpmi_leak_check(self, 'normal') - test_memory_dpmi_leak_check_normal.dpmitest = True - - def test_memory_dpmi_leak_check_dos_nofree(self): - """Memory DPMI Leak Check DOS No Free""" - memory_dpmi_leak_check_dos(self, 'nofree') - test_memory_dpmi_leak_check_dos_nofree.dpmitest = True - - def test_memory_dpmi_leak_check_dos_normal(self): - """Memory DPMI Leak Check DOS Normal""" - memory_dpmi_leak_check_dos(self, 'normal') - test_memory_dpmi_leak_check_dos_normal.dpmitest = True - - def test_memory_uma_strategy(self): - """Memory UMA Strategy""" - memory_uma_strategy(self) - test_memory_uma_strategy.umatest = True - def test_floppy_img(self): """Floppy image file""" # Note: image must have @@ -3464,10 +3360,7 @@ rem end testdir = self.mkworkdir('d') - testfil = testdir / "there.txt" - testfil.write_text('there') - - name = self.mkimage_vbr(fat, cwd=testdir) + name = self.mkimage(fat, cwd=testdir) results = self.runDosemu("testit.bat", config="""\ $_hdimage = "dXXXXs/c:hdtype1 %s +1" @@ -3488,10 +3381,6 @@ $_hdimage = "dXXXXs/c:hdtype1 %s +1" r"HELLO[\t ]+TXT[\t ]+8" r"|" r"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}\s+8\s+HELLO.TXT") - self.assertRegex(results, - r"THERE[\t ]+TXT[\t ]+5" - r"|" - r"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}\s+5\s+THERE.TXT") def test_fat12_img_d_writable(self): """FAT12 image file D writable""" @@ -3501,14 +3390,6 @@ $_hdimage = "dXXXXs/c:hdtype1 %s +1" """FAT16 image file D writable""" self._test_fat_img_d_writable("16") - def test_fat16b_img_d_writable(self): - """FAT16B image file D writable""" - self._test_fat_img_d_writable("16b") - - def test_fat32_img_d_writable(self): - """FAT32 image file D writable""" - self._test_fat_img_d_writable("32") - def test_mfs_lredir_auto_hdc(self): """MFS lredir auto C drive redirection""" self.mkfile("testit.bat", "lredir\r\nrem end\r\n") @@ -3618,189 +3499,93 @@ $_floppy_a = "" """MFS truename UFS LFN""" names_to_create = ( ("DIR", "Program Files"), - ("DIR", "RealDir2"), - ("DIR", "Sub"), - ("DIR", "Sub/RealDir"), - ("FILE", "Sub/Very Long realName"), - ("FILE", "Sub/verylongRealname.txt"), - ("FILE", "Sub/RealDir/Very Long realName"), + ("FILE", "very long testname"), + ("FILE", "verylongtestname.txt"), ) - tests = ( # Note: CurDrv == D:, CurDir == \Sub + tests = ( +# NOTE: not sure that the output should be UPCASED. + ("LFN0", "very long testname", "C:\\VERY LONG TESTNAME"), + ("LFN0", "d:\\verylongtestname.txt", "D:\\VERYLONGTESTNAME.TXT"), + ("LFN0", "d:\\very long testname", "D:\\VERY LONG TESTNAME"), + ("LFN0", "aux", "C:/AUX"), + ("LFN0", "d:very long testname", "D:\\VERY LONG TESTNAME"), +# FAIL ("LFN0", "d:\\fakedir\\very long testname", None), - # These LFN 7160/0 tests are proven on Win98 and are seen - # to have the following rules: - # 1/ Any '..' are resolved. - # 2/ Any '.\' are stripped. - # 3/ If no drive specification, then default drive is prepended. - # 4/ If not absolute path, then current directory for drive - # is inserted between drive and relative path. - # 5/ All path components (except final) are upcased. - # 6/ Final path component case is preserved from the request. - # 7/ No path component has to exist on the filesystem or - # is checked against it and updated for case. - - ("LFN0", r"aux", r"D:/AUX"), - # D:\Sub exists as a directory - ("LFN0", r"nonExist", r"D:\\SUB\\nonExist"), - ("LFN0", r"\\nonExist", r"D:\\nonExist"), - ("LFN0", r"\\Sub\\nonExist", r"D:\\SUB\\nonExist"), - ("LFN0", r"c:nonExist", r"C:\\nonExist"), - ("LFN0", r"c:\\nonExist", r"C:\\nonExist"), - ("LFN0", r"c:\\RootC\\nonExist", r"C:\\ROOTC\\nonExist"), - # Both D:\RealDir2 and D:\\Sub\\RealDir exist as directories - ("LFN0", r"d:realdir", r"D:\\SUB\\realdir"), - ("LFN0", r"d:\\realdir2", r"D:\\realdir2"), - ("LFN0", r"d:\\realdir2\\noNexist.TxT", r"D:\\REALDIR2\\noNexist.TxT"), - # D:\Sub exists as a directory - ("LFN0", r"nonExist\\NewFile.txt", r"D:\\SUB\\NONEXIST\\NewFile.txt"), - ("LFN0", r"d:nonExist\\NewFile.txt", r"D:\\SUB\\NONEXIST\\NewFile.txt"), - ("LFN0", r"d:\\nonExist\\NewFile.txt", r"D:\\NONEXIST\\NewFile.txt"), - ("LFN0", r"..\\Sub\\RealDir\\..\\NewFile.txt", r"D:\\SUB\\NewFile.txt"), - # D:\Program Files exists as a directory - ("LFN0", r"D:\\progra~1", r"D:\\progra~1"), - ("LFN0", r"D:\\PROGRA~1", r"D:\\PROGRA~1"), - ("LFN0", r"D:\\program files", r"D:\\program files"), - ("LFN0", r"D:\\PROGRAM FILES", r"D:\\PROGRAM FILES"), - ("LFN0", r"D:\\Program Files", r"D:\\Program Files"), - ("LFN0", r"D:\\Program Files\\NewFile.txt", r"D:\\PROGRAM FILES\\NewFile.txt"), - ("LFN0", r"D:\\Program Files\\NewFile.txt", r"D:\\PROGRAM FILES\\NewFile.txt"), - ("LFN0", r"D:\\Program Files\\NonExist\\NewFile.txt", r"D:\\PROGRAM FILES\\NONEXIST\\NewFile.txt"), - - ("LFN1", r"d:very long realname", r"D:\\SUB\\VERYL~CV"), - ("LFN1", r"d:\\very long realname", r"ERROR: invalid component"), - ("LFN1", r"d:\\Sub\\VERYLONGrEALNAME.TXT", r"D:\\SUB\\VERYL~6S.TXT"), - ("LFN1", r"D:\\program files", r"D:\\PROGR~-I"), - ("LFN1", r"D:\\PROGRAM FILES", r"D:\\PROGR~-I"), - ("LFN1", r"D:\\Program Files", r"D:\\PROGR~-I"), - - ("LFN2", r"D:\\SUB\\VERYL~CV", r"D:\\Sub\\Very Long realName"), - ("LFN2", r"D:\\SUB\\VERYL~6S.TXT", r"D:\\Sub\\verylongRealname.txt"), - ("LFN2", r"D:\\progr~-i", r"D:\\Program Files"), - ("LFN2", r"D:\\PROGR~-I", r"D:\\Program Files"), + ("LFN0", "D:\\PROGR~-I", "D:\\PROGR~-I"), + ("LFN1", "D:\\Program Files", "D:\\PROGR~-I"), + ("LFN2", "D:\\PROGR~-I", "D:\\Program Files"), ) - mfs_truename(self, "UFS", names_to_create, tests) + for t in tests: + with self.subTest(t=t): + mfs_truename(self, "UFS", names_to_create, *t) def test_mfs_truename_ufs_sfn(self): """MFS truename UFS SFN""" names_to_create = ( - ("DIR", "Sub"), - ("DIR", "Sub/testname"), + ("DIR", "testname"), ("FILE", "shrtname.txt"), ) - tests = ( # Note: CurDrv == D:, CurDir == \SUB - ("SFN", r"aux", r"D:/AUX"), - - ("SFN", r"fakename", r"D:\\SUB\\FAKENAME"), # Non existent - ("SFN", r"\\fakename", r"D:\\FAKENAME"), # Non existent - ("SFN", r"\\Sub\\fakename", r"D:\\SUB\\FAKENAME"), # Non existent - ("SFN", r"c:fakename", r"C:\\FAKENAME"), # Non existent - ("SFN", r"c:\\fakename", r"C:\\FAKENAME"), # Non existent - ("SFN", r"c:\\Sub\\fakename", r"C:\\SUB\\FAKENAME"), # Non existent - - ("SFN", r"testname", r"D:\\SUB\\TESTNAME"), - ("SFN", r"\\Sub\\testname", r"D:\\SUB\\TESTNAME"), - ("SFN", r"d:testname", r"D:\\SUB\\TESTNAME"), - ("SFN", r"d:\\Sub\\testname", r"D:\\SUB\\TESTNAME"), - - ("SFN", r"shrtname.txt", r"D:\\SUB\\SHRTNAME.TXT"), # Non existent - ("SFN", r"\\shrtname.txt", r"D:\\SHRTNAME.TXT"), - ("SFN", r"d:shrtname.txt", r"D:\\SUB\\SHRTNAME.TXT"), # Non existent - ("SFN", r"d:\\shrtname.txt", r"D:\\SHRTNAME.TXT"), + tests = ( + ("SFN", "testname", "C:\\TESTNAME"), + ("SFN", "d:\\shrtname.txt", "D:\\SHRTNAME.TXT"), + ("SFN", "d:\\testname", "D:\\TESTNAME"), + ("SFN", "aux", "C:/AUX"), + ("SFN", "d:testname", "D:\\TESTNAME"), +# FAIL ("SFN", "d:\\fakedir\\testname", None), ) - mfs_truename(self, "UFS", names_to_create, tests) + for t in tests: + with self.subTest(t=t): + mfs_truename(self, "UFS", names_to_create, *t) def test_mfs_truename_vfat_linux_mounted_lfn(self): """MFS truename VFAT Linux mounted LFN""" names_to_create = ( ("DIR", "Program Files"), - ("FILE", "lfnInRoot.tXt"), - ("FILE", "Sub/verylongfilename.txt"), - ("FILE", "Sub/verylongfilename2.txt"), - ("FILE", "Sub/space embedded filename.txt"), - ("FILE", "Sub/MixedCaseFilename.ext"), - ("DIR", "Sub/test/1234567890987654321"), - ("DIR", "Sub/abcdefgfedcba/1234567890987654321"), - ("FILE", "Sub/1234567890987654321/abcdefgfedcba.txt"), - ("FILE", "Sub/1234567890987654321/abcdefclash.txt"), + ("FILE", "verylongfilename.txt"), + ("FILE", "verylongfilename2.txt"), + ("FILE", "space embedded filename.txt"), + ("FILE", "MixedCaseFilename.ext"), ) tests = ( - # Since Truename 0x7160/0 does not interact with the filesystem, - # the tests on UFS should give coverage, but just do a few for - # belt and braces. - ("LFN0", r"D:\\progra~1", r"D:\\progra~1"), - ("LFN0", r"D:\\PROGRA~1", r"D:\\PROGRA~1"), - ("LFN0", r"D:\\program files", r"D:\\program files"), - ("LFN0", r"D:\\PROGRAM FILES", r"D:\\PROGRAM FILES"), - ("LFN0", r"D:\\Program Files", r"D:\\Program Files"), - ("LFN0", r"D:\\Program Files\\NewFile.txt", r"D:\\PROGRAM FILES\\NewFile.txt"), - ("LFN0", r"D:\\Program Files\\NewFile.txt", r"D:\\PROGRAM FILES\\NewFile.txt"), - ("LFN0", r"D:\\Program Files\\NonExist\\NewFile.txt", r"D:\\PROGRAM FILES\\NONEXIST\\NewFile.txt"), + ("LFN1", "X:\\verylongfilename.txt", "X:\\VERYLO~1.TXT"), + ("LFN1", "X:\\verylongfilename2.txt", "X:\\VERYLO~2.TXT"), + ("LFN1", "X:\\space embedded filename.txt", "X:\\SPACEE~1.TXT"), + ("LFN1", "X:\\MixedCaseFilename.ext", "X:\\MIXEDC~1.EXT"), - ("LFN1", r"X:\\lfnNotInRoot.tXt", r"ERROR: invalid component"), # Non existent - ("LFN1", r"..\\lfnNotInRoot.tXt", r"ERROR: invalid component"), # Non existent - ("LFN1", r"X:\\lfnInRoot.tXt", r"X:\\LFNINR~1.TXT"), - ("LFN1", r"..\\lfnInRoot.tXt", r"X:\\LFNINR~1.TXT"), - ("LFN1", r"..\\rootc\\..\\lfnInRoot.tXt", r"X:\\LFNINR~1.TXT"), - ("LFN1", r"X:\\sub\\verylongfilename.txt", r"X:\\SUB\\VERYLO~1.TXT"), - ("LFN1", r"X:\\sub\\verylongfilename2.txt", r"X:\\SUB\\VERYLO~2.TXT"), - ("LFN1", r"X:\\sub\\space embedded filename.txt", r"X:\\SUB\\SPACEE~1.TXT"), - ("LFN1", r"X:\\sub\\MixedCaseFilename.ext", r"X:\\SUB\\MIXEDC~1.EXT"), - ("LFN1", r"X:\\sub\\test\\1234567890987654321", r"X:\\SUB\\TEST\\123456~1"), - ("LFN1", r"X:\\sub\\abcdefgfedcba\\1234567890987654321", r"X:\\SUB\\ABCDEF~1\\123456~1"), - ("LFN1", r"X:\\sub\\1234567890987654321\\abcdefgfedcba.txt", r"X:\\SUB\\123456~1\\ABCDEF~1.TXT"), - ("LFN1", r"X:\\sub\\1234567890987654321\\abcdefclash.txt", r"X:\\SUB\\123456~1\\ABCDEF~2.TXT"), - ("LFN1", r"1234567890987654321\\abcdefclash.txt", r"X:\\SUB\\123456~1\\ABCDEF~2.TXT"), - ("LFN1", r".\\1234567890987654321\\abcdefclash.txt", r"X:\\SUB\\123456~1\\ABCDEF~2.TXT"), - ("LFN1", r"..\\sub\\1234567890987654321\\abcdefclash.txt", r"X:\\SUB\\123456~1\\ABCDEF~2.TXT"), - ("LFN1", r"X:\\program files", r"X:\\PROGRA~1"), - ("LFN1", r"X:\\PROGRAM FILES", r"X:\\PROGRA~1"), - ("LFN1", r"X:\\Program Files", r"X:\\PROGRA~1"), + ("LFN2", "X:\\VERYLO~1.TXT", "X:\\verylongfilename.txt"), + ("LFN2", "X:\\VERYLO~2.TXT", "X:\\verylongfilename2.txt"), + ("LFN2", "X:\\SPACEE~1.TXT", "X:\\space embedded filename.txt"), + ("LFN2", "X:\\MIXEDC~1.EXT", "X:\\MixedCaseFilename.ext"), - ("LFN2", r"X:\\LFNNOT~1.TXT", r"ERROR: invalid component"), # Non existent - ("LFN2", r"X:\\LFNINR~1.TXT", r"X:\\lfnInRoot.tXt"), - ("LFN2", r"X:\\sub\\VERYLO~1.TXT", r"X:\\Sub\\verylongfilename.txt"), - ("LFN2", r"X:\\sub\\VERYLO~2.TXT", r"X:\\Sub\\verylongfilename2.txt"), - ("LFN2", r"X:\\sub\\SPACEE~1.TXT", r"X:\\Sub\\space embedded filename.txt"), - ("LFN2", r"X:\\sub\\MIXEDC~1.EXT", r"X:\\Sub\\MixedCaseFilename.ext"), - ("LFN2", r"X:\\sub\\TEST\\123456~1", r"X:\\Sub\\test\\1234567890987654321"), - ("LFN2", r"X:\\sub\\ABCDEF~1\\123456~1", r"X:\\Sub\\abcdefgfedcba\\1234567890987654321"), - ("LFN2", r"X:\\sub\\123456~1\\ABCDEF~1.TXT", r"X:\\Sub\\1234567890987654321\\abcdefgfedcba.txt"), - ("LFN2", r"X:\\sub\\123456~1\\ABCDEF~2.TXT", r"X:\\Sub\\1234567890987654321\\abcdefclash.txt"), - ("LFN2", r"X:\\progra~1", r"X:\\Program Files"), - ("LFN2", r"X:\\PROGRA~1", r"X:\\Program Files"), - ("LFN2", r"X:\\PROGRA~1", r"X:\\Program Files"), + ("LFN0", "X:\\progra~1", "X:\\PROGRA~1"), + ("LFN1", "X:\\Program Files", "X:\\PROGRA~1"), + ("LFN2", "X:\\PROGRA~1", "X:\\Program Files"), ) - mfs_truename(self, "VFAT", names_to_create, tests) + for t in tests: + with self.subTest(t=t): + mfs_truename(self, "VFAT", names_to_create, *t) def test_mfs_truename_vfat_linux_mounted_sfn(self): """MFS truename VFAT Linux mounted SFN""" names_to_create = ( ("DIR", "testname"), - ("FILE", "Sub/shrtname.txt"), - ("FILE", "Sub/verylongfilename.txt"), - ("FILE", "Sub/verylongfilename2.txt"), - ("FILE", "Sub/space embedded filename.txt"), - ("FILE", "Sub/MixedCaseFilename.ext"), - ("DIR", "Sub/test/1234567890987654321"), - ("DIR", "Sub/abcdefgfedcba/1234567890987654321"), - ("FILE", "Sub/654321fedcba/abcdef123456.txt"), - ("FILE", "Sub/654321fedcba/abcdefclash.txt"), + ("FILE", "shrtname.txt"), + ("FILE", "verylongfilename.txt"), + ("FILE", "verylongfilename2.txt"), + ("FILE", "space embedded filename.txt"), + ("FILE", "MixedCaseFilename.ext"), ) - tests = ( # Note: CurDrv == X:, CurDir == \SUB - ("SFN", r"X:\\testname", r"X:\\TESTNAME"), - ("SFN", r"..\\testname", r"X:\\TESTNAME"), - ("SFN", r"testname", r"X:\\SUB\\TESTNAME"), # Non existent - ("SFN", r"X:\\sub\\shrtname.txt", r"X:\\SUB\\SHRTNAME.TXT"), - ("SFN", r"X:\\sub\\verylo~1.txt", r"X:\\SUB\\VERYLO~1.TXT"), - ("SFN", r"X:\\sub\\verylo~2.txt", r"X:\\SUB\\VERYLO~2.TXT"), - ("SFN", r"X:\\sub\\spacee~1.txt", r"X:\\SUB\\SPACEE~1.TXT"), - ("SFN", r"X:\\sub\\mixedc~1.ext", r"X:\\SUB\\MIXEDC~1.EXT"), - ("SFN", r"X:\\sub\\test\\123456~1", r"X:\\SUB\\TEST\\123456~1"), - ("SFN", r"X:\\sub\\abcdef~1\\123456~1", r"X:\\SUB\\ABCDEF~1\\123456~1"), - ("SFN", r"X:\\sub\\654321~1\\abcdef~1", r"X:\\SUB\\654321~1\\ABCDEF~1"), - ("SFN", r"X:\\sub\\654321~1\\abcdef~2", r"X:\\SUB\\654321~1\\ABCDEF~2"), + tests = ( + ("SFN", "X:\\testname", "X:\\TESTNAME"), + ("SFN", "d:\\shrtname.txt", "D:\\SHRTNAME.TXT"), + ("SFN", "X:\\verylo~1.txt", "X:\\VERYLO~1.TXT"), + ("SFN", "X:\\verylo~2.txt", "X:\\VERYLO~2.TXT"), + ("SFN", "X:\\spacee~1.txt", "X:\\SPACEE~1.TXT"), + ("SFN", "X:\\mixedc~1.ext", "X:\\MIXEDC~1.EXT"), ) - mfs_truename(self, "VFAT", names_to_create, tests) + for t in tests: + with self.subTest(t=t): + mfs_truename(self, "VFAT", names_to_create, *t) def _test_mfs_file_read(self, nametype): if nametype == "LFN": @@ -4011,17 +3796,204 @@ $_floppy_a = "" """MFS SFN file append""" self._test_mfs_file_write("SFN", "append") + def _test_lfn_volume_info(self, fstype): + if not fstype in ["MFS", "FAT"]: + self.fail("Incorrect argument") + + self.mkfile("testit.bat", """\ +c:\\lfnvinfo D:\\ +rem end +""", newline="\r\n") + + testdir = self.mkworkdir('d') + self.mkfile("foo.dat", "some content", dname=testdir) + + name = self.mkimage("16", cwd=testdir) + + # compile sources + self.mkexe_with_djgpp("lfnvinfo", r""" +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + int max_file_len, max_path_len; + char fsystype[32]; + unsigned rval; + + if (argc < 1) { + printf("missing volume argument e.g. 'C:\\'\n"); + return 1; + } + + rval = _get_volume_info(argv[1], &max_file_len, &max_path_len, fsystype); + if (rval == 0 && errno) { + printf("ERRNO(%d)\r\n", errno); + return 2; + } + if (rval == _FILESYS_UNKNOWN) { + printf("FILESYS_UNKNOWN(%d)\r\n", errno); + return 3; + } + + printf("FSTYPE(%s), FILELEN(%d), PATHLEN(%d), BITS(0x%04x)\r\n", + fsystype, max_file_len, max_path_len, rval); + + return 0; +} +""") + + if fstype == "MFS": + hdimage = "dXXXXs/c:hdtype1 dXXXXs/d:hdtype1" + elif fstype == "FAT": + hdimage = "dXXXXs/c:hdtype1 %s" % name + + results = self.runDosemu("testit.bat", config="""\ +$_hdimage = "%s +1" +$_floppy_a = "" +""" % hdimage) + + if fstype == "MFS": + self.assertIn("FSTYPE(MFS)", results) + elif fstype == "FAT": + self.assertIn("ERRNO(27)", results) + def test_lfn_volume_info_mfs(self): """LFN volume info on MFS""" - lfn_voln_info(self, "MFS") + self._test_lfn_volume_info("MFS") - def test_lfn_volume_info_fat16(self): - """LFN volume info on FAT16""" - lfn_voln_info(self, "FAT16") + def test_lfn_volume_info_fat_img(self): + """LFN volume info on FAT(img)""" + self._test_lfn_volume_info("FAT") - def test_lfn_volume_info_fat32(self): - """LFN volume info on FAT32""" - lfn_voln_info(self, "FAT32") + def test_fat32_disk_info(self): + """FAT32 disk info""" + + path = "C:\\" + + self.mkfile("testit.bat", """\ +c:\\fat32dif %s +rem end +""" % path, newline="\r\n") + + # compile sources + self.mkexe_with_djgpp("fat32dif", r"""\ +#include +#include +#include + +struct dinfo { + uint16_t size; + uint16_t version; // (0000h) + uint32_t spc; + uint32_t bps; + uint32_t avail_clusters; + uint32_t total_clusters; + uint32_t avail_sectors; + uint32_t total_sectors; + uint32_t avail_units; + uint32_t total_units; + char reserved[8]; +}; + +#define MAXPATH 128 + +int main(int argc, char *argv[]) { + struct dinfo df; + uint8_t carry; + uint16_t ax; + int len; + + if (argc < 2) { + printf("path argument missing e.g. 'C:\\'\n"); + return 3; + } + + len = strlen(argv[1]) + 1; + if (len > MAXPATH) { + printf("path argument too long\n"); + return 2; + } + + /* + AX = 7303h + DS:DX -> ASCIZ string for drive ("C:\" or "\\SERVER\Share") + ES:DI -> buffer for extended free space structure (see #01789) + CX = length of buffer for extended free space + + Return: + CF clear if successful + ES:DI buffer filled + CF set on error + AX = error code + */ + + asm volatile("stc\n" + "int $0x21\n" + "setc %0\n" + : "=r"(carry), "=a"(ax) + : "a"(0x7303), "d"(argv[1]), "D"(&df), "c"(sizeof(df)) + : "cc", "memory"); + + if (carry) { + printf("Call failed (CARRY), AX = 0x%04x\n", ax); + return 1; + } + + /* See if we have valid data */ + if (df.size > sizeof(df)) { + printf("Call failed (Struct invalid), size = 0x%04x, version 0x%04x\n", df.size, df.version); + return 1; + } + + printf("size 0x%04x\n", df.size); + printf("version 0x%04x\n", df.version); + printf("spc 0x%08lx\n", df.spc); + printf("bps 0x%08lx\n", df.bps); + printf("avail_clusters 0x%08lx\n", df.avail_clusters); + printf("total_clusters 0x%08lx\n", df.total_clusters); + printf("avail_sectors 0x%08lx\n", df.avail_sectors); + printf("total_sectors 0x%08lx\n", df.total_sectors); + printf("avail_units 0x%08lx\n", df.avail_units); + printf("total_units 0x%08lx\n", df.total_units); + + printf("avail_bytes(%llu)\n", + (unsigned long long)df.spc * (unsigned long long)df.bps * (unsigned long long)df.avail_clusters); + printf("total_bytes(%llu)\n", + (unsigned long long)df.spc * (unsigned long long)df.bps * (unsigned long long)df.total_clusters); + return 0; +} +""") + + results = self.runDosemu("testit.bat", config="""\ +$_hdimage = "dXXXXs/c:hdtype1 +1" +$_floppy_a = "" +""") + + self.assertNotIn("Call failed", results) + + fsinfo = statvfs(self.workdir) + lfs_total = fsinfo.f_blocks * fsinfo.f_bsize + lfs_avail = fsinfo.f_bavail * fsinfo.f_bsize + + t = re.search(r'total_bytes\((\d+)\)', results) + self.assertIsNotNone(t, "Unable to parse 'total_bytes'") + dfs_total = int(t.group(1)) + a = re.search(r'avail_bytes\((\d+)\)', results) + self.assertIsNotNone(a, "Unable to parse 'avail_bytes'") + dfs_avail = int(a.group(1)) + +# see if we are within 5% of the values obtained from Linux + msg = "total dos %d, linux %d" % (dfs_total, lfs_total) + self.assertLessEqual(dfs_total, lfs_total * 1.05, msg) + self.assertGreaterEqual(dfs_total, lfs_total * 0.95, msg) + + msg = "avail dos %d, linux %d" % (dfs_avail, lfs_avail) + self.assertLessEqual(dfs_avail, lfs_avail * 1.05, msg) + self.assertGreaterEqual(dfs_avail, lfs_avail * 0.95, msg) def test_int21_disk_info(self): """INT21 disk info""" @@ -4131,14 +4103,9 @@ $_floppy_a = "" lfs_total = fsinfo.f_blocks * fsinfo.f_bsize lfs_avail = fsinfo.f_bavail * fsinfo.f_bsize - r1 = re.compile(r'total_bytes\((\d+)\)') - self.assertRegex(results, r1) - t = r1.search(results) + t = re.search(r'total_bytes\((\d+)\)', results) dfs_total = int(t.group(1)) - - r2 = re.compile(r'avail_bytes\((\d+)\)') - self.assertRegex(results, r2) - a = r2.search(results) + a = re.search(r'avail_bytes\((\d+)\)', results) dfs_avail = int(a.group(1)) # see if we are within 5% of the values obtained from Linux @@ -4154,14 +4121,6 @@ $_floppy_a = "" self.assertLessEqual(dfs_avail, lfs_avail * 1.05, msg) self.assertGreaterEqual(dfs_avail, lfs_avail * 0.95, msg) - def test_lfs_disk_info_fat32(self): - """LFS disk info FAT32""" - lfs_disk_info(self, "FAT32") - - def test_lfs_disk_info_mfs(self): - """LFS disk info MFS""" - lfs_disk_info(self, "MFS") - def test_mfs_lfs_file_info_1MiB(self): """MFS LFS file info (1 MiB)""" lfs_file_info(self, "MFS", "1MiB") @@ -4564,9 +4523,9 @@ $_floppy_a = "" """MFS DOSv3 file access write device readonly""" ds3_file_access(self, "MFSRO", "WRITE") -# def test_mfs_ds3_lock_readonly(self): -# """MFS DOSv3 lock file readonly""" -# ds3_lock_readonly(self, "MFS") + def test_mfs_ds3_lock_readonly(self): + """MFS DOSv3 lock file readonly""" + ds3_lock_readonly(self, "MFS") def test_fat_ds3_lock_readonly(self): """FAT DOSv3 lock file readonly""" @@ -4620,120 +4579,83 @@ $_floppy_a = "" """FAT DOSv3 share open twice""" ds3_share_open_twice(self, "FAT") - def test_mfs_ds3_share_open_delete_one_process_ds2(self): - """MFS DOSv3 share open delete one process DOSv2""" - ds3_share_open_access(self, "ONE", "MFS", "DELPTH") + def test_mfs_ds3_share_open_delete_ds2(self): + """MFS DOSv3 share open delete DOSv2""" + ds3_share_open_access(self, "MFS", "DELPTH") - def test_fat_ds3_share_open_delete_one_process_ds2(self): - """FAT DOSv3 share open delete one process DOSv2""" - ds3_share_open_access(self, "ONE", "FAT", "DELPTH") + def test_fat_ds3_share_open_delete_ds2(self): + """FAT DOSv3 share open delete DOSv2""" + ds3_share_open_access(self, "FAT", "DELPTH") - def test_mfs_ds3_share_open_delete_one_process_fcb(self): - """MFS DOSv3 share open delete one process FCB""" - ds3_share_open_access(self, "ONE", "MFS", "DELFCB") + def test_mfs_ds3_share_open_delete_fcb(self): + """MFS DOSv3 share open delete FCB""" + ds3_share_open_access(self, "MFS", "DELFCB") - def test_fat_ds3_share_open_delete_one_process_fcb(self): - """FAT DOSv3 share open delete one process FCB""" - ds3_share_open_access(self, "ONE", "FAT", "DELFCB") + def test_fat_ds3_share_open_delete_fcb(self): + """FAT DOSv3 share open delete FCB""" + ds3_share_open_access(self, "FAT", "DELFCB") - def test_mfs_ds3_share_open_rename_one_process_ds2(self): - """MFS DOSv3 share open rename one process DOSv2""" - ds3_share_open_access(self, "ONE", "MFS", "RENPTH") + def test_mfs_ds3_share_open_rename_ds2(self): + """MFS DOSv3 share open rename DOSv2""" + ds3_share_open_access(self, "MFS", "RENPTH") - def test_fat_ds3_share_open_rename_one_process_ds2(self): - """FAT DOSv3 share open rename one process DOSv2""" - ds3_share_open_access(self, "ONE", "FAT", "RENPTH") + def test_fat_ds3_share_open_rename_ds2(self): + """FAT DOSv3 share open rename DOSv2""" + ds3_share_open_access(self, "FAT", "RENPTH") - def test_mfs_ds3_share_open_rename_one_process_fcb(self): - """MFS DOSv3 share open rename one process FCB""" - ds3_share_open_access(self, "ONE", "MFS", "RENFCB") + def test_mfs_ds3_share_open_rename_fcb(self): + """MFS DOSv3 share open rename FCB""" + ds3_share_open_access(self, "MFS", "RENFCB") - def test_fat_ds3_share_open_rename_one_process_fcb(self): - """FAT DOSv3 share open rename one process FCB""" - ds3_share_open_access(self, "ONE", "FAT", "RENFCB") + def test_fat_ds3_share_open_rename_fcb(self): + """FAT DOSv3 share open rename FCB""" + ds3_share_open_access(self, "FAT", "RENFCB") - def test_mfs_ds3_share_open_setfattrs_one_process(self): - """MFS DOSv3 share open set file attrs one process DOSv2""" - ds3_share_open_access(self, "ONE", "MFS", "SETATT") + def test_mfs_ds3_share_open_setfattrs(self): + """MFS DOSv3 share open set file attrs DOSv2""" + ds3_share_open_access(self, "MFS", "SETATT") - def test_fat_ds3_share_open_setfattrs_one_process(self): - """FAT DOSv3 share open set file attrs one process DOSv2""" - ds3_share_open_access(self, "ONE", "FAT", "SETATT") - - def test_mfs_ds3_share_open_delete_two_process_ds2(self): - """MFS DOSv3 share open delete two process DOSv2""" - ds3_share_open_access(self, "TWO", "MFS", "DELPTH") - - def test_fat_ds3_share_open_delete_two_process_ds2(self): - """FAT DOSv3 share open delete two process DOSv2""" - ds3_share_open_access(self, "TWO", "FAT", "DELPTH") - - def test_mfs_ds3_share_open_delete_two_process_fcb(self): - """MFS DOSv3 share open delete two process FCB""" - ds3_share_open_access(self, "TWO", "MFS", "DELFCB") - - def test_fat_ds3_share_open_delete_two_process_fcb(self): - """FAT DOSv3 share open delete two process FCB""" - ds3_share_open_access(self, "TWO", "FAT", "DELFCB") - - def test_mfs_ds3_share_open_rename_two_process_ds2(self): - """MFS DOSv3 share open rename two process DOSv2""" - ds3_share_open_access(self, "TWO", "MFS", "RENPTH") - - def test_fat_ds3_share_open_rename_two_process_ds2(self): - """FAT DOSv3 share open rename two process DOSv2""" - ds3_share_open_access(self, "TWO", "FAT", "RENPTH") - - def test_mfs_ds3_share_open_rename_two_process_fcb(self): - """MFS DOSv3 share open rename two process FCB""" - ds3_share_open_access(self, "TWO", "MFS", "RENFCB") - - def test_fat_ds3_share_open_rename_two_process_fcb(self): - """FAT DOSv3 share open rename two process FCB""" - ds3_share_open_access(self, "TWO", "FAT", "RENFCB") - - def test_mfs_ds3_share_open_setfattrs_two_process(self): - """MFS DOSv3 share open set file attrs two process DOSv2""" - ds3_share_open_access(self, "TWO", "MFS", "SETATT") - - def test_fat_ds3_share_open_setfattrs_two_process(self): - """FAT DOSv3 share open set file attrs two process DOSv2""" - ds3_share_open_access(self, "TWO", "FAT", "SETATT") - - def test_network_pktdriver_mtcp_builtin(self): - """Network pktdriver mTCP built-in""" - network_pktdriver_mtcp(self, 'builtin') - test_network_pktdriver_mtcp_builtin.nettest = True - - def test_network_pktdriver_mtcp_ne2000(self): - """Network pktdriver mTCP NE2000""" - network_pktdriver_mtcp(self, 'ne2000') - test_network_pktdriver_mtcp_ne2000.nettest = True + def test_fat_ds3_share_open_setfattrs(self): + """FAT DOSv3 share open set file attrs DOSv2""" + ds3_share_open_access(self, "FAT", "SETATT") def _test_cpu(self, cpu_vm, cpu_vm_dpmi, cpu_emu): if ('kvm' in cpu_vm or 'kvm' in cpu_vm_dpmi) and not access("/dev/kvm", W_OK|R_OK): - self.skipTest("requires KVM") - if cpu_vm == 'vm86' and uname()[4] != 'i686': - self.skipTest("native vm86() only on 32bit x86") + self.skipTest("No KVM available") + if cpu_vm == 'vm86' and uname()[4] == 'x86_64': + self.skipTest("x86_64 doesn't support native vm86()") edir = self.topdir / "test" / "cpu" - # Native reference file is now checked in to git and will - # only need to be updated if the test source changes - reffile = edir / "reffile.log" - refoutput = [] - with reffile.open("r") as f: - refoutput = f.readlines() - - # DOS test binary is built as part of normal build process + try: + check_call(['make', '-C', str(edir), 'all'], stdout=DEVNULL, stderr=DEVNULL) + except CalledProcessError as e: + self.skipTest("Unable to build test binaries '%s'" % e) copy(edir / "dosbin.exe", self.workdir / "dosbin.exe") - dosfile = self.workdir / "dosfile.log" - # output from DOS under test + reffile = "reffile.log" + dosfile = "dosfile.log" + + # reference file + try: + with open(self.topdir / reffile, "w") as f: + check_call([str(edir / 'native32'), '--common-tests'], + stdout=f, stderr=DEVNULL) + except CalledProcessError as e: + self.skipTest("Host reference file error '%s'" % e) + + refoutput = [] + try: + with open(self.topdir / reffile, "r") as f: + refoutput = f.readlines() + except FileNotFoundError as e: + self.fail("Could not open reference file error '%s'" % e) + + # output from dos under test self.mkfile("testit.bat", """\ dosbin --common-tests > %s rem end -""" % dosfile.name, newline="\r\n") +""" % dosfile, newline="\r\n") self.runDosemu("testit.bat", timeout=20, config="""\ $_hdimage = "dXXXXs/c:hdtype1 +1" @@ -4746,70 +4668,68 @@ $_ignore_djgpp_null_derefs = (off) dosoutput = [] try: - with dosfile.open("r") as f: + with open(self.workdir / dosfile, "r") as f: dosoutput = f.readlines() except FileNotFoundError: - pass - if not dosoutput: self.fail("DOS output file not found") # Compare DOS output to reference file if dosoutput != refoutput: - diff = unified_diff(refoutput, dosoutput, fromfile=str(reffile), tofile=str(dosfile)) + diff = unified_diff(refoutput, dosoutput, fromfile=reffile, tofile=dosfile) self.fail('differences detected\n' + ''.join(list(diff))) def test_cpu_1_vm86native(self): - """CPU native vm86 + native DPMI (i386 only)""" + """CPU test: native vm86 + native DPMI (i386 only)""" self._test_cpu("vm86", "native", 0) test_cpu_1_vm86native.cputest = True def test_cpu_2_jitnative(self): - """CPU JIT vm86 + native DPMI""" + """CPU test: JIT vm86 + native DPMI""" self._test_cpu("emulated", "native", 0) test_cpu_2_jitnative.cputest = True def test_cpu_jitkvm(self): - """CPU JIT vm86 + KVM DPMI""" + """CPU test: JIT vm86 + KVM DPMI""" self._test_cpu("emulated", "kvm", 0) test_cpu_jitkvm.cputest = True def test_cpu_simnative(self): - """CPU simulated vm86 + native DPMI""" + """CPU test: simulated vm86 + native DPMI""" self._test_cpu("emulated", "native", 1) test_cpu_simnative.cputest = True def test_cpu_simkvm(self): - """CPU simulated vm86 + KVM DPMI""" + """CPU test: simulated vm86 + KVM DPMI""" self._test_cpu("emulated", "kvm", 1) test_cpu_simkvm.cputest = True def test_cpu_kvmnative(self): - """CPU KVM vm86 + native DPMI""" + """CPU test: KVM vm86 + native DPMI""" self._test_cpu("kvm", "native", 0) test_cpu_kvmnative.cputest = True def test_cpu_kvm(self): - """CPU KVM vm86 + KVM DPMI""" + """CPU test: KVM vm86 + KVM DPMI""" self._test_cpu("kvm", "kvm", 0) test_cpu_kvm.cputest = True def test_cpu_kvmjit(self): - """CPU KVM vm86 + JIT DPMI""" + """CPU test: KVM vm86 + JIT DPMI""" self._test_cpu("kvm", "emulated", 0) test_cpu_kvmjit.cputest = True def test_cpu_kvmsim(self): - """CPU KVM vm86 + simulated DPMI""" + """CPU test: KVM vm86 + simulated DPMI""" self._test_cpu("kvm", "emulated", 1) test_cpu_kvmsim.cputest = True def test_cpu_jit(self): - """CPU JIT vm86 + JIT DPMI""" + """CPU test: JIT vm86 + JIT DPMI""" self._test_cpu("emulated", "emulated", 0) test_cpu_jit.cputest = True def test_cpu_sim(self): - """CPU simulated vm86 + simulated DPMI""" + """CPU test: simulated vm86 + simulated DPMI""" self._test_cpu("emulated", "emulated", 1) test_cpu_sim.cputest = True @@ -4823,6 +4743,60 @@ $_ignore_djgpp_null_derefs = (off) cpu_trap_flag(self, 'kvm') test_cpu_trap_flag_kvm.cputest = True + def test_libi86_build(self): + """libi86 build and test script""" + if environ.get("SKIP_EXPENSIVE"): + self.skipTest("expensive test") + + i86repo = 'https://github.com/tkchia/libi86.git' + i86root = self.imagedir / 'i86root.git' + + args = ["git", "clone", "-q"] + args += ["--single-branch", "--branch=20220105"] + args += [i86repo, str(i86root)] + call(args, stdout=DEVNULL, stderr=DEVNULL) + + self.mkfile("dosemu.conf", """\ +$_hdimage = "dXXXXs/c:hdtype1 +1" +$_floppy_a = "" +""", dname=self.imagedir, mode="a") + + dose = self.topdir / "bin" / "dosemu" + opts = '-f {0}/dosemu.conf -n --Fimagedir {0}'.format(self.imagedir) + + build = i86root / "build-xxxx" + build.mkdir() + + if environ.get("CC"): + del environ["CC"] + + # logfiles + # - dosemu log not applicable as libi86 test suite invokes dosemu multiple times + # - libi86 test suite has its own log file called 'testsuite.log' + # which contains configure, build, and test. We will present it as + # our usual output log + # - expect log is not present as it's run non-interactively + self.logfiles['log'][1] = "testsuite.log" + del self.logfiles['xpt'] + + check_call(['../configure', '--host=ia16-elf', '--disable-elks-libc'], + cwd=build, env=environ, stdout=DEVNULL, stderr=DEVNULL) + + check_call(['make'], cwd=build, env=environ, stdout=DEVNULL, stderr=DEVNULL) + + try: + environ["TESTSUITEFLAGS"] = "--x-test-underlying --x-with-dosemu=%s --x-with-dosemu-options=\"%s\"" % (dose, opts) + starttime = datetime.utcnow() + check_call(['make', 'check'], + cwd=build, env=environ, timeout=900, stdout=DEVNULL, stderr=DEVNULL) + self.duration = datetime.utcnow() - starttime + except CalledProcessError: + copy(build / "tests" / "testsuite.log", self.logfiles['log'][0]) + raise self.failureException("Test error") from None + except TimeoutExpired: + copy(build / "tests" / "testsuite.log", self.logfiles['log'][0]) + raise self.failureException("Test timeout") from None + def test_pcmos_build(self): """PC-MOS build script""" if environ.get("SKIP_EXPENSIVE"): @@ -4831,10 +4805,7 @@ $_ignore_djgpp_null_derefs = (off) mosrepo = 'https://github.com/roelandjansen/pcmos386v501.git' mosroot = self.imagedir / 'pcmos.git' - try: - run(["git", "clone", "-q", "--depth=1", mosrepo, str(mosroot)], check=True) - except CalledProcessError: - self.skipTest("repository unavailable") + call(["git", "clone", "-q", "--depth=1", mosrepo, str(mosroot)]) outfiles = [mosroot / 'SOURCES/src/latest' / x for x in [ '$286n.sys', '$386.sys', '$all.sys', '$arnet.sys', @@ -4857,64 +4828,14 @@ $_ignore_djgpp_null_derefs = (off) $_hdimage = "dXXXXs/c:hdtype1 +1" $_floppy_a = "" """) - - self.assertNotIn('Timeout', results) - self.assertNotIn('NonZeroReturn', results) + if results == 'Timeout': + raise self.failureException("Timeout:\n") missing = [str(x.relative_to(mosroot)) for x in outfiles if not x.exists()] if len(missing): msg = "Output file(s) missing %s\n" % str(missing) raise self.failureException(msg) - def test_passing_environment_variable(self): - """Passing Environment Variable to DOS""" - - tstring1 = "0123456789aBcDeF" - - self.mkfile("testit.bat", """\ -@ECHO on -ECHO %TESTVAR1% -rem end -""", newline="\r\n") - - args = ["TESTVAR1=" + tstring1, "-q", "-E", "testit.bat"] - results = self.runDosemuCmdline(args, config="""\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -""") - - self.assertNotIn('Timeout', results) - self.assertNotIn('NonZeroReturn', results) - self.assertIn("rem end", results, msg="Test incomplete:\n") - self.assertIn(tstring1, results) - - def test_passing_dos_errorlevel_back(self): - """Passing DOS Errorlevel back""" - - self.mkcom_with_ia16("justerro", r""" -int main(int argc, char *argv[]) -{ - return 53; -} -""") - - results = self.runDosemuCmdline(["-q", "-E", "justerro.com"], config="""\ -$_hdimage = "dXXXXs/c:hdtype1 +1" -$_floppy_a = "" -""") - - self.assertNotIn('Timeout', results) - self.assertIn('NonZeroReturn:53', results) - - def test_pit_mode_2(self): - """PIT Mode 2""" - if environ.get("SKIP_EXPENSIVE"): - self.skipTest("expensive test") - if environ.get("SKIP_UNCERTAIN"): - self.skipTest("uncertain test") - - pit_mode_2(self) - class DRDOS701TestCase(OurTestCase, unittest.TestCase): # OpenDOS 7.01 @@ -4942,26 +4863,21 @@ class DRDOS701TestCase(OurTestCase, unittest.TestCase): ("boot-floppy.img", "d38fb2dba30185ce510cf3366bd71a1cbc2635da"), ] cls.actions = { - r"test_fat_ds3_share_open_setfattrs_(one|two)_process": KNOWNFAIL, - r"test_..._ds3_share_open_rename_one_process_fcb": KNOWNFAIL, - r"test_..._fcb_rename_simple": KNOWNFAIL, - r"test_..._fcb_rename_wild_\d": KNOWNFAIL, + "test_fat_ds3_share_open_setfattrs": KNOWNFAIL, + "test_fat_fcb_rename_simple": KNOWNFAIL, + "test_fat_fcb_rename_wild_1": KNOWNFAIL, + "test_fat_fcb_rename_wild_2": KNOWNFAIL, + "test_fat_fcb_rename_wild_3": KNOWNFAIL, + "test_fat_fcb_rename_wild_4": KNOWNFAIL, + "test_mfs_fcb_rename_simple": KNOWNFAIL, + "test_mfs_fcb_rename_wild_1": KNOWNFAIL, + "test_mfs_fcb_rename_wild_2": KNOWNFAIL, + "test_mfs_fcb_rename_wild_3": KNOWNFAIL, + "test_mfs_fcb_rename_wild_4": KNOWNFAIL, "test_mfs_truename_ufs_sfn": KNOWNFAIL, "test_mfs_truename_vfat_linux_mounted_sfn": KNOWNFAIL, - "test_fat32_img_d_writable": UNSUPPORTED, - "test_lfn_volume_info_fat16": KNOWNFAIL, - "test_lfn_volume_info_fat32": UNSUPPORTED, - "test_lfn_volume_info_mfs": KNOWNFAIL, - "test_lfs_disk_info_fat32": UNSUPPORTED, "test_floppy_vfs": KNOWNFAIL, - "test_memory_hma_alloc3": UNSUPPORTED, - "test_memory_hma_chain": UNSUPPORTED, "test_pcmos_build": KNOWNFAIL, - "test_passing_dos_errorlevel_back": KNOWNFAIL, - "test_fat_label_create_bpb12": KNOWNFAIL, - "test_fat_label_create_bpb16": KNOWNFAIL, - "test_fat_label_create_bpb32": UNSUPPORTED, - "test_fat_label_create_on_lfns": UNSUPPORTED, } cls.setUpClassPost() @@ -5043,24 +4959,17 @@ class FRDOS120TestCase(OurTestCase, unittest.TestCase): "test_mfs_findfile_vfat_linux_mounted_lfn": KNOWNFAIL, "test_mfs_findfile_vfat_linux_mounted_sfn": KNOWNFAIL, "test_fat_ds3_share_open_twice": KNOWNFAIL, - r"test_fat_ds3_share_open_(delete|rename)_.*": KNOWNFAIL, - r"test_mfs_ds3_share_open_rename_(one|two)_process_fcb": KNOWNFAIL, - r"test_fat_ds3_share_open_setfattrs_(one|two)_process": KNOWNFAIL, + "test_fat_ds3_share_open_delete_ds2": KNOWNFAIL, + "test_fat_ds3_share_open_delete_fcb": KNOWNFAIL, + "test_fat_ds3_share_open_rename_ds2": KNOWNFAIL, + "test_fat_ds3_share_open_rename_fcb": KNOWNFAIL, + "test_mfs_ds3_share_open_rename_fcb": KNOWNFAIL, + "test_fat_ds3_share_open_setfattrs": KNOWNFAIL, "test_create_new_psp": KNOWNFAIL, "test_command_com_keyword_exist": KNOWNFAIL, "test_memory_emm286_borland": KNOWNFAIL, - "test_memory_hma_alloc": KNOWNFAIL, - "test_memory_hma_alloc3": UNSUPPORTED, - "test_memory_hma_chain": UNSUPPORTED, - "test_memory_uma_strategy": KNOWNFAIL, "test_pcmos_build": KNOWNFAIL, - r"test_libi86_item_\d+": KNOWNFAIL, - "test_passing_dos_errorlevel_back": KNOWNFAIL, - "test_fat_label_create_bpb12": KNOWNFAIL, - "test_fat_label_create_bpb16": KNOWNFAIL, - "test_fat_label_create_bpb32": KNOWNFAIL, - "test_fat_label_create_prefile": KNOWNFAIL, - "test_fat_label_create_predir": KNOWNFAIL, + "test_libi86_build": KNOWNFAIL, } cls.setUpClassPost() @@ -5083,157 +4992,6 @@ class FRDOS120TestCase(OurTestCase, unittest.TestCase): self.mkfile(self.confsys, contents, newline="\r\n") -class FRDOS130TestCase(OurTestCase, unittest.TestCase): - - @classmethod - def setUpClass(cls): - super(FRDOS130TestCase, cls).setUpClass() - cls.version = "FreeDOS kernel 2043" - cls.prettyname = "FR-DOS-1.30" - cls.files = [ - ("kernel.sys", "2bdf90c8bc8c0406cfa01349265bf782507af016"), - ("command.com", "15abab3d3ee4a50449517131a13b2c5164610582"), - ("share.com", "cadc29d49115cb3a250f90921cca345e7c427464"), - ] - cls.systype = SYSTYPE_FRDOS_NEW - cls.autoexec = "fdautoem.bat" - cls.confsys = "fdconfig.sys" - cls.bootblocks = [ - ("boot-306-4-17.blk", "0092a320500d7a8359d40bddc48f592686745aed"), - ("boot-615-4-17.blk", "2b757178c7ba97f8a439c83dc627d61c2d6b3cf6"), - ("boot-900-15-17.blk", "8cd7adeff4a0265e8a8e20f7942672c677cbc891"), - ] - cls.images = [ - ("boot-floppy.img", "7b68b4dc2de5891bb3700816d8e1a323e8d150bb"), - ] - cls.actions = { - "test_command_com_keyword_exist": KNOWNFAIL, - "test_create_new_psp": KNOWNFAIL, - "test_fat_ds3_lock_readlckd": KNOWNFAIL, - "test_fat_ds3_lock_two_handles": KNOWNFAIL, - "test_fat_ds3_lock_writable": KNOWNFAIL, - r"test_fat_ds3_share_open_(delete|rename)_.*": KNOWNFAIL, - r"test_fat_ds3_share_open_setfattrs_(one|two)_process": KNOWNFAIL, - "test_fat_ds3_share_open_twice": KNOWNFAIL, - "test_fat_fcb_find_wild_1": KNOWNFAIL, - "test_fat_fcb_find_wild_2": KNOWNFAIL, - "test_fat_fcb_find_wild_3": KNOWNFAIL, - "test_fat_fcb_rename_wild_1": KNOWNFAIL, - "test_fat_fcb_rename_wild_2": KNOWNFAIL, - "test_fat_fcb_rename_wild_3": KNOWNFAIL, - "test_fat_fcb_rename_wild_4": KNOWNFAIL, - "test_fat_label_create_bpb12": KNOWNFAIL, - "test_fat_label_create_bpb16": KNOWNFAIL, - "test_fat_label_create_bpb32": KNOWNFAIL, - "test_fat_label_create_noduplicate": KNOWNFAIL, - "test_fat_label_create_predir": KNOWNFAIL, - "test_fat_label_create_prefile": KNOWNFAIL, - "test_memory_emm286_borland": KNOWNFAIL, - "test_memory_hma_alloc": KNOWNFAIL, - "test_memory_hma_alloc3": UNSUPPORTED, - "test_memory_hma_chain": UNSUPPORTED, - "test_memory_uma_strategy": KNOWNFAIL, - "test_mfs_fcb_rename_wild_1": KNOWNFAIL, - "test_mfs_fcb_rename_wild_2": KNOWNFAIL, - "test_mfs_fcb_rename_wild_3": KNOWNFAIL, - "test_mfs_fcb_rename_wild_4": KNOWNFAIL, - "test_passing_dos_errorlevel_back": KNOWNFAIL, - } - - cls.setUpClassPost() - - def setUpDosAutoexec(self): - # Use the (almost) standard shipped config - contents = (self.topdir / "src" / "bindist" / self.autoexec).read_text() - contents = re.sub(r"[Dd]:\\", r"c:\\", contents) - self.mkfile(self.autoexec, contents, newline="\r\n") - - def setUpDosConfig(self): - # Link back to std dosemu commands and scripts - p = self.workdir / "dosemu" - p.symlink_to(self.topdir / "commands" / "dosemu") - - # Use the (almost) standard shipped config - contents = (self.topdir / "src" / "bindist" / "c" / self.confsys).read_text() - contents = re.sub(r"[Dd]:\\", r"c:\\", contents) - contents = re.sub(r"rem SWITCHES=/F", r"SWITCHES=/F", contents) - self.mkfile(self.confsys, contents, newline="\r\n") - - -class FRDOSGITTestCase(OurTestCase, unittest.TestCase): - - @classmethod - def setUpClass(cls): - super(FRDOSGITTestCase, cls).setUpClass() - cls.version = "DOS version 7.10" - cls.prettyname = "FR-DOS-GIT" - cls.tarfile = "" - cls.systype = SYSTYPE_FRDOS_NEW - cls.autoexec = "fdautoem.bat" - cls.confsys = "fdconfig.sys" - cls.bootblocks = [ - ] - cls.images = [ - ] - cls.actions = { - "test_fat_ds3_lock_concurrent": KNOWNFAIL, - "test_fat_ds3_lock_readlckd": KNOWNFAIL, - "test_fat_ds3_lock_two_handles": KNOWNFAIL, - "test_fat_ds3_lock_writable": KNOWNFAIL, - "test_fat_ds3_share_open_delete_one_process_ds2": KNOWNFAIL, - "test_fat_ds3_share_open_delete_one_process_fcb": KNOWNFAIL, - "test_fat_ds3_share_open_rename_one_process_ds2": KNOWNFAIL, - "test_fat_ds3_share_open_rename_one_process_fcb": KNOWNFAIL, - "test_fat_ds3_share_open_setfattrs_one_process": KNOWNFAIL, - "test_fat_ds3_share_open_twice": KNOWNFAIL, - "test_fat_label_create_bpb12": KNOWNFAIL, - "test_fat_label_create_bpb16": KNOWNFAIL, - "test_fat_label_create_bpb32": KNOWNFAIL, - "test_fat_label_create_noduplicate": KNOWNFAIL, - "test_fat_label_create_predir": KNOWNFAIL, - "test_fat_label_create_prefile": KNOWNFAIL, - "test_memory_emm286_borland": KNOWNFAIL, - "test_memory_hma_alloc3": UNSUPPORTED, - "test_memory_hma_chain": UNSUPPORTED, - "test_memory_uma_strategy": KNOWNFAIL, - "test_passing_dos_errorlevel_back": KNOWNFAIL, - } - - cls.setUpClassPost() - - # Check files under test exist, or skip the whole thing - cls.files_to_copy = [ - Path(environ.get("FDOS_KERNEL_SYS", "../fdos/kernel.git/bin/kernel.sys")), - Path(environ.get("FDOS_COMMAND_COM", "../fdos/freecom.git/command.com")), - Path(environ.get("FDOS_SHARE_COM", "../fdos/share.git/src/share.com")), - ] - for f in cls.files_to_copy: - if not f.is_file(): - raise unittest.SkipTest("File '%s' not found" % f.name) - - def setUp(self): - super(FRDOSGITTestCase, self).setUp() - for f in self.files_to_copy: - copy(f, self.workdir) - - def setUpDosAutoexec(self): - # Use the (almost) standard shipped config - contents = (self.topdir / "src" / "bindist" / self.autoexec).read_text() - contents = re.sub(r"[Dd]:\\", r"c:\\", contents) - self.mkfile(self.autoexec, contents, newline="\r\n") - - def setUpDosConfig(self): - # Link back to std dosemu commands and scripts - p = self.workdir / "dosemu" - p.symlink_to(self.topdir / "commands" / "dosemu") - - # Use the (almost) standard shipped config - contents = (self.topdir / "src" / "bindist" / "c" / self.confsys).read_text() - contents = re.sub(r"[Dd]:\\", r"c:\\", contents) - contents = re.sub(r"rem SWITCHES=/F", r"SWITCHES=/F", contents) - self.mkfile(self.confsys, contents, newline="\r\n") - - class MSDOS622TestCase(OurTestCase, unittest.TestCase): @classmethod @@ -5258,17 +5016,6 @@ class MSDOS622TestCase(OurTestCase, unittest.TestCase): cls.images = [ ("boot-floppy.img", "14b8310910bf19d6e375298f3b06da7ffdec9932"), ] - cls.actions = { - "test_fat32_img_d_writable": UNSUPPORTED, - "test_lfn_volume_info_fat16": KNOWNFAIL, - "test_lfn_volume_info_fat32": UNSUPPORTED, - "test_lfs_disk_info_fat32": UNSUPPORTED, - "test_memory_hma_alloc3": UNSUPPORTED, - "test_memory_hma_chain": UNSUPPORTED, - "test_passing_dos_errorlevel_back": KNOWNFAIL, - "test_fat_label_create_bpb32": UNSUPPORTED, - "test_fat_label_create_on_lfns": UNSUPPORTED, - } cls.setUpClassPost() @@ -5293,125 +5040,6 @@ class MSDOS622TestCase(OurTestCase, unittest.TestCase): self.mkfile("version.bat", "ver\r\nrem end\r\n") -class MSDOS700TestCase(OurTestCase, unittest.TestCase): - # badged Win95 RTM at winworldpc.com - - @classmethod - def setUpClass(cls): - super(MSDOS700TestCase, cls).setUpClass() - cls.version = "Windows 95. [Version 4.00.950]" - cls.prettyname = "MS-DOS-7.00" - cls.files = [ - ("io.sys", "22924f93dd0f9ea6a4624ccdd1bbcdf5eb43a308"), - ("msdos.sys", "f5d01c68d518f4b8b2482d3815af8bb88003831d"), - ("command.com", "67696207c3963a0dc9afab8cf37dbdb966c1f663"), - ] - cls.systype = SYSTYPE_MSDOS_NEW - cls.autoexec = "autoemu.bat" - cls.bootblocks = [ - ("boot-306-4-17.blk", "8c016e339ca6b8126fd2026ed3a7eeeb6cbb8903"), - ("boot-615-4-17.blk", "b6fdddbfb37442a2762d5897de1aa7d7a694286a"), - ("boot-900-15-17.blk", "8c1243481112f320f2a5f557f30db11174fe7e3d"), - ] - cls.images = [ - ("boot-floppy.img", ""), - ] - cls.actions = { - "test_fat32_img_d_writable": UNSUPPORTED, - "test_fat_label_create_bpb32": UNSUPPORTED, - "test_lfn_volume_info_fat16": KNOWNFAIL, - "test_lfn_volume_info_fat32": UNSUPPORTED, - "test_lfs_disk_info_fat32": UNSUPPORTED, - "test_lfs_disk_info_mfs": KNOWNFAIL, - } - - cls.setUpClassPost() - - def setUpDosAutoexec(self): - # Use the (almost) standard shipped config - contents = (self.topdir / "src" / "bindist" / self.autoexec).read_text() - contents = re.sub(r"[Dd]:\\", r"c:\\", contents) - self.mkfile(self.autoexec, contents, newline="\r\n") - - def setUpDosConfig(self): - # Link back to std dosemu commands and scripts - p = self.workdir / "dosemu" - p.symlink_to(self.topdir / "commands" / "dosemu") - - # Use the (almost) standard shipped config - contents = (self.topdir / "src" / "bindist" / "c" / self.confsys).read_text() - contents = re.sub(r"[Dd]:\\", r"c:\\", contents) - contents = re.sub(r"rem SWITCHES=/F", r"SWITCHES=/F", contents) - self.mkfile(self.confsys, contents, newline="\r\n") - - def setUpDosVersion(self): - self.mkfile("version.bat", "ver\r\nrem end\r\n") - - # Disable the logo here or we get blank screen - self.mkfile("msdos.sys", """ -[Options] -BootGUI=0 -Logo=0 -""", newline="\r\n") - - -class MSDOS710TestCase(OurTestCase, unittest.TestCase): - # badged CDU (Chinese DOS Union) at winworldpc.com - - @classmethod - def setUpClass(cls): - super(MSDOS710TestCase, cls).setUpClass() - cls.version = "MS-DOS 7.1 [Version 7.10.1999]" - cls.prettyname = "MS-DOS-7.10" - cls.files = [ - ("io.sys", "8c586b1bf38fc2042f2383ca873283a466be2f44"), - ("msdos.sys", "cd1e6103ce9cdebbc7a5611df13ff4fbd5e2159c"), - ("command.com", "f6547d81e625a784633c059e536e90ee45532202"), - ] - cls.systype = SYSTYPE_MSDOS_NEW - cls.autoexec = "autoemu.bat" - cls.bootblocks = [ - ("boot-306-4-17.blk", "0f520de6e2a33ef8fd336b2844957689fc1060e9"), - ("boot-615-4-17.blk", "5e49a8ee7747191d87a2214cc0281736262687b9"), - ("boot-900-15-17.blk", "2c29d06909c7d5ca46a3ca26ddde9287a11ef315"), - ] - cls.images = [ - ("boot-floppy.img", ""), - ] - - cls.actions = { - } - - cls.setUpClassPost() - - def setUpDosAutoexec(self): - # Use the (almost) standard shipped config - contents = (self.topdir / "src" / "bindist" / self.autoexec).read_text() - contents = re.sub(r"[Dd]:\\", r"c:\\", contents) - self.mkfile(self.autoexec, contents, newline="\r\n") - - def setUpDosConfig(self): - # Link back to std dosemu commands and scripts - p = self.workdir / "dosemu" - p.symlink_to(self.topdir / "commands" / "dosemu") - - # Use the (almost) standard shipped config - contents = (self.topdir / "src" / "bindist" / "c" / self.confsys).read_text() - contents = re.sub(r"[Dd]:\\", r"c:\\", contents) - contents = re.sub(r"rem SWITCHES=/F", r"SWITCHES=/F", contents) - self.mkfile(self.confsys, contents, newline="\r\n") - - def setUpDosVersion(self): - self.mkfile("version.bat", "ver\r\nrem end\r\n") - - # Disable the logo here or we get blank screen - self.mkfile("msdos.sys", """ -[Options] -BootGUI=0 -Logo=0 -""", newline="\r\n") - - class PPDOSGITTestCase(OurTestCase, unittest.TestCase): @classmethod @@ -5436,9 +5064,6 @@ class PPDOSGITTestCase(OurTestCase, unittest.TestCase): if __name__ == '__main__': - # Dynamically create libi86 tests - libi86_create_items(OurTestCase) - tests = [t[0] for t in inspect.getmembers(OurTestCase, predicate=inspect.isfunction) if t[0].startswith("test")] @@ -5451,8 +5076,6 @@ if __name__ == '__main__': inspect.getmembers(modules[__name__], predicate=inspect.isclass) if issubclass(c[1], OurTestCase) and c[0] != "OurTestCase"] - attrs = sorted(OurTestCase.attrs) - def explode(n, attr=None): if n in tests: return [c + "." + n for c in cases] @@ -5472,17 +5095,7 @@ if __name__ == '__main__': if len(argv) > 1: if argv[1] == "--help": - print(("Usage: %s [--help | --get-test-binaries | " + - "--list-attrs | --list-cases | --list-tests] | " + - "[--require-attr=STRING TestCase ...] | " + - "[TestCase[.testname] ...]") % argv[0]) - exit(0) - elif argv[1] == "--get-test-binaries": - get_test_binaries() - exit(0) - elif argv[1] == "--list-attrs": - for a in attrs: - print(str(a)) + print("Usage: %s [--help | --list-cases | --list-tests] | [--require-attr=STRING TestCase ...] | [TestCase[.testname] ...]" % argv[0]) exit(0) elif argv[1] == "--list-cases": for m in cases: @@ -5493,7 +5106,7 @@ if __name__ == '__main__': print(str(m)) exit(0) else: - x = re.match(r"^--require-attr=(\S+).*$", argv[1]) + x = re.match("^--require-attr=(\S+).*$", argv[1]) if x: attr = x.groups()[0] del argv[1]