From 08b2a725c0061a53a3495a89e2be22d7b8bd0d06 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 4 Feb 2018 22:48:35 -0500 Subject: [PATCH] ICL1900: Initial Commit. --- ICL1900/Makefile | 1120 ++++++++++++++++++++++ ICL1900/icl1900_cpu.c | 2001 ++++++++++++++++++++++++++++++++++++++++ ICL1900/icl1900_defs.h | 226 +++++ ICL1900/icl1900_sys.c | 610 ++++++++++++ 4 files changed, 3957 insertions(+) create mode 100755 ICL1900/Makefile create mode 100644 ICL1900/icl1900_cpu.c create mode 100755 ICL1900/icl1900_defs.h create mode 100755 ICL1900/icl1900_sys.c diff --git a/ICL1900/Makefile b/ICL1900/Makefile new file mode 100755 index 0000000..bbd4314 --- /dev/null +++ b/ICL1900/Makefile @@ -0,0 +1,1120 @@ +# +# This GNU make makefile has been tested on: +# Linux (x86 & Sparc & PPC) +# OS X +# Solaris (x86 & Sparc) (gcc and Sun C) +# OpenBSD +# NetBSD +# FreeBSD +# HP-UX +# AIX +# Windows (MinGW & cygwin) +# Linux x86 targeting Android (using agcc script) +# Haiku x86 (with gcc4) +# +# Android targeted builds should invoke GNU make with GCC=agcc on +# the command line. +# +# In general, the logic below will detect and build with the available +# features which the host build environment provides. +# +# Dynamic loading of libpcap is the preferred default behavior if pcap.h +# is available at build time. Support to statically linking against libpcap +# is deprecated and may be removed in the future. Static linking against +# libpcap can be enabled if GNU make is invoked with USE_NETWORK=1 on the +# command line. +# +# Some platforms may not have vendor supplied libpcap available. HP-UX is +# one such example. The packages which are available for this platform +# install include files and libraries in user specified directories. In +# order for this makefile to locate where these components may have been +# installed, gmake should be invoked with LPATH=/usr/lib:/usr/local/lib +# defined (adjusted as needed depending on where they may be installed). +# +# The default build will build compiler optimized binaries. +# If debugging is desired, then GNU make can be invoked with +# DEBUG=1 on the command line. +# +# simh project support is provided for simulators that are built with +# dependent packages provided with the or by the operating system +# distribution OR for platforms where that isn't directly available (OS X) +# by packages from specific package management systems (MacPorts). Users +# wanting to build simulators with locally build dependent packages or +# packages provided by an unsupported package management system can +# override where this procedure looks for include files and/or libraries. +# Overrides can be specified by define exported environment variables or +# GNU make command line arguments which specify INCLUDES and/or LIBRARIES. +# Each of these, if specified, must be the complete list include directories +# or library directories that should be used with each element separated by +# colons. (i.e. INCLUDES=/usr/include/:/usr/local/include/:...) +# +# Some environments may have the LLVM (clang) compiler installed as +# an alternate to gcc. If you want to build with the clang compiler, +# invoke make with GCC=clang. +# +# Internal ROM support can be disabled if GNU make is invoked with +# DONT_USE_ROMS=1 on the command line. +# +# The use of pthreads for various things can be disabled if GNU make is +# invoked with NOPTHREADS=1 on the command line. +# +# Asynchronous I/O support can be disabled if GNU make is invoked with +# NOASYNCH=1 on the command line. +# +# For linting (or other code analyzers) make may be invoked similar to: +# +# make GCC=cppcheck CC_OUTSPEC= LDFLAGS= CFLAGS_G="--enable=all --template=gcc" CC_STD=--std=c99 +# +# CC Command (and platform available options). (Poor man's autoconf) +# +ifneq (,$(GREP_OPTIONS)) + $(info GREP_OPTIONS is defined in your environment.) + $(info ) + $(info This variable interfers with the proper operation of this script.) + $(info ) + $(info The GREP_OPTIONS environment variable feature of grep is deprecated) + $(info for exactly this reason and will be removed from future versions of) + $(info grep. The grep man page suggests that you use an alias or a script) + $(info to invoke grep with your preferred options.) + $(info ) + $(info unset the GREP_OPTIONS environment variable to use this makefile) + $(error 1) +endif +ifeq (old,$(shell gmake --version /dev/null 2>&1 | grep 'GNU Make' | awk '{ if ($$3 < "3.81") {print "old"} }')) + GMAKE_VERSION = $(shell gmake --version /dev/null 2>&1 | grep 'GNU Make' | awk '{ print $$3 }') + $(warning *** Warning *** GNU Make Version $(GMAKE_VERSION) is too old to) + $(warning *** Warning *** fully process this makefile) +endif +BUILD_SINGLE := $(MAKECMDGOALS) $(BLANK_SUFFIX) +# building the pdp1, pdp11, tx-0, or any microvax simulator could use video support +ifneq (,$(or $(findstring XXpdp1XX,$(addsuffix XX,$(addprefix XX,$(MAKECMDGOALS)))),$(findstring pdp11,$(MAKECMDGOALS)),$(findstring tx-0,$(MAKECMDGOALS)),$(findstring microvax1,$(MAKECMDGOALS)),$(findstring microvax2,$(MAKECMDGOALS)),$(findstring microvax3900,$(MAKECMDGOALS)),$(findstring XXvaxXX,$(addsuffix XX,$(addprefix XX,$(MAKECMDGOALS)))))) + VIDEO_USEFUL = true +endif +# building the besm6 needs both video support and fontfile support +ifneq (,$(findstring besm6,$(MAKECMDGOALS))) + VIDEO_USEFUL = true + BESM6_BUILD = true +endif +# building the pdp11, pdp10, or any vax simulator could use networking support +ifneq (,$(or $(findstring pdp11,$(MAKECMDGOALS)),$(findstring pdp10,$(MAKECMDGOALS)),$(findstring vax,$(MAKECMDGOALS)),$(findstring all,$(MAKECMDGOALS)))) + NETWORK_USEFUL = true + ifneq (,$(findstring all,$(MAKECMDGOALS))) + BUILD_MULTIPLE = s + VIDEO_USEFUL = true + BESM6_BUILD = true + endif + ifneq (,$(word 2,$(MAKECMDGOALS))) + BUILD_MULTIPLE = s + endif +else + ifeq ($(MAKECMDGOALS),) + # default target is all + NETWORK_USEFUL = true + VIDEO_USEFUL = true + BUILD_MULTIPLE = s + BUILD_SINGLE := all $(BUILD_SINGLE) + BESM6_BUILD = true + endif +endif +find_exe = $(abspath $(strip $(firstword $(foreach dir,$(strip $(subst :, ,$(PATH))),$(wildcard $(dir)/$(1)))))) +find_lib = $(abspath $(strip $(firstword $(foreach dir,$(strip $(LIBPATH)),$(wildcard $(dir)/lib$(1).$(LIBEXT)))))) +find_include = $(abspath $(strip $(firstword $(foreach dir,$(strip $(INCPATH)),$(wildcard $(dir)/$(1).h))))) +ifneq ($(findstring Windows,$(OS)),) + ifeq ($(findstring .exe,$(SHELL)),.exe) + # MinGW + WIN32 := 1 + else # Msys or cygwin + ifeq (MINGW,$(findstring MINGW,$(shell uname))) + $(info *** This makefile can not be used with the Msys bash shell) + $(error *** Use build_mingw.bat $(MAKECMDGOALS) from a Windows command prompt) + endif + endif +endif +ifeq ($(WIN32),) #*nix Environments (&& cygwin) + ifeq ($(GCC),) + ifeq (,$(shell which gcc 2>/dev/null)) + $(info *** Warning *** Using local cc since gcc isn't available locally.) + $(info *** Warning *** You may need to install gcc to build working simulators.) + GCC = cc + else + GCC = gcc + endif + endif + OSTYPE = $(shell uname) + # OSNAME is used in messages to indicate the source of libpcap components + OSNAME = $(OSTYPE) + ifeq (SunOS,$(OSTYPE)) + TEST = /bin/test + else + TEST = test + endif + ifeq (CYGWIN,$(findstring CYGWIN,$(OSTYPE))) # uname returns CYGWIN_NT-n.n-ver + OSTYPE = cygwin + OSNAME = windows-build + endif + ifeq (,$(shell $(GCC) -v /dev/null 2>&1 | grep 'clang')) + GCC_VERSION = $(shell $(GCC) -v /dev/null 2>&1 | grep 'gcc version' | awk '{ print $$3 }') + COMPILER_NAME = GCC Version: $(GCC_VERSION) + ifeq (,$(GCC_VERSION)) + ifeq (SunOS,$(OSTYPE)) + ifneq (,$(shell $(GCC) -V 2>&1 | grep 'Sun C')) + SUNC_VERSION = $(shell $(GCC) -V 2>&1 | grep 'Sun C') + COMPILER_NAME = $(wordlist 2,10,$(SUNC_VERSION)) + CC_STD = -std=c99 + endif + endif + ifeq (HP-UX,$(OSTYPE)) + ifneq (,$(shell what `which $(firstword $(GCC)) 2>&1`| grep -i compiler)) + COMPILER_NAME = $(strip $(shell what `which $(firstword $(GCC)) 2>&1` | grep -i compiler)) + CC_STD = -std=gnu99 + endif + endif + else + ifeq (,$(findstring ++,$(GCC))) + CC_STD = -std=gnu99 + else + CPP_BUILD = 1 + endif + endif + else + ifeq (Apple,$(shell $(GCC) -v /dev/null 2>&1 | grep 'Apple' | awk '{ print $$1 }')) + COMPILER_NAME = $(shell $(GCC) -v /dev/null 2>&1 | grep 'Apple' | awk '{ print $$1 " " $$2 " " $$3 " " $$4 }') + CLANG_VERSION = $(word 4,$(COMPILER_NAME)) + else + COMPILER_NAME = $(shell $(GCC) -v /dev/null 2>&1 | grep 'clang version' | awk '{ print $$1 " " $$2 " " $$3 }') + CLANG_VERSION = $(word 3,$(COMPILER_NAME)) + ifeq (,$(findstring .,$(CLANG_VERSION))) + COMPILER_NAME = $(shell $(GCC) -v /dev/null 2>&1 | grep 'clang version' | awk '{ print $$1 " " $$2 " " $$3 " " $$4 }') + CLANG_VERSION = $(word 4,$(COMPILER_NAME)) + endif + endif + ifeq (,$(findstring ++,$(GCC))) + CC_STD = -std=c99 + else + CPP_BUILD = 1 + endif + endif + ifeq (git-repo,$(shell if $(TEST) -d ./.git; then echo git-repo; fi)) + ifeq (need-hooks,$(shell if $(TEST) ! -e ./.git/hooks/post-checkout; then echo need-hooks; fi)) + $(info *** Installing git hooks in local repository ***) + GIT_HOOKS += $(shell /bin/cp './Visual Studio Projects/git-hooks/post-commit' ./.git/hooks/) + GIT_HOOKS += $(shell /bin/cp './Visual Studio Projects/git-hooks/post-checkout' ./.git/hooks/) + GIT_HOOKS += $(shell /bin/cp './Visual Studio Projects/git-hooks/post-merge' ./.git/hooks/) + GIT_HOOKS += $(shell ./.git/hooks/post-checkout) + ifneq (,$(strip $(GIT_HOOKS))) + $(info *** Warning - Error installing git hooks *** $(GIT_HOOKS)) + endif + else + ifneq (commit-id-exists,$(shell if $(TEST) -e .git-commit-id; then echo commit-id-exists; fi)) + GIT_HOOKS = $(shell ./.git/hooks/post-checkout) + ifneq (,$(strip $(GIT_HOOKS))) + $(info *** Warning - Error executing git hooks *** $(GIT_HOOKS)) + endif + endif + endif + endif + LTO_EXCLUDE_VERSIONS = + PCAPLIB = pcap + ifeq (agcc,$(findstring agcc,$(GCC))) # Android target build? + OS_CCDEFS = -D_GNU_SOURCE + ifeq (,$(NOASYNCH)) + OS_CCDEFS += -DSIM_ASYNCH_IO + endif + OS_LDFLAGS = -lm + else # Non-Android Builds + ifeq (,$(INCLUDES)$(LIBRARIES)) + INCPATH:=/usr/include + LIBPATH:=/usr/lib + else + $(info *** Warning ***) + ifeq (,$(INCLUDES)) + INCPATH:=$(shell LANG=C; $(GCC) -x c -v -E /dev/null 2>&1 | grep -A 10 '> search starts here' | grep '^ ' | tr -d '\n') + else + $(info *** Warning *** Unsupported build with INCLUDES defined as: $(INCLUDES)) + INCPATH:=$(strip $(subst :, ,$(INCLUDES))) + UNSUPPORTED_BUILD := include + endif + ifeq (,$(LIBRARIES)) + LIBPATH:=/usr/lib + else + $(info *** Warning *** Unsupported build with LIBRARIES defined as: $(LIBRARIES)) + LIBPATH:=$(strip $(subst :, ,$(LIBRARIES))) + ifeq (include,$(UNSUPPORTED_BUILD)) + UNSUPPORTED_BUILD := include+lib + else + UNSUPPORTED_BUILD := lib + endif + endif + $(info *** Warning ***) + endif + OS_CCDEFS = -D_GNU_SOURCE + GCC_OPTIMIZERS_CMD = $(GCC) -v --help 2>&1 + GCC_WARNINGS_CMD = $(GCC) -v --help 2>&1 + LD_ELF = $(shell echo | $(GCC) -E -dM - | grep __ELF__) + ifeq (Darwin,$(OSTYPE)) + OSNAME = OSX + LIBEXT = dylib + ifneq (include,$(findstring include,$(UNSUPPORTED_BUILD))) + INCPATH:=$(shell LANG=C; $(GCC) -x c -v -E /dev/null 2>&1 | grep -A 10 '> search starts here' | grep '^ ' | grep -v 'framework directory' | tr -d '\n') + endif + ifeq (incopt,$(shell if $(TEST) -d /opt/local/include; then echo incopt; fi)) + INCPATH += /opt/local/include + OS_CCDEFS += -I/opt/local/include + endif + ifeq (libopt,$(shell if $(TEST) -d /opt/local/lib; then echo libopt; fi)) + LIBPATH += /opt/local/lib + OS_LDFLAGS += -L/opt/local/lib + endif + ifeq (HomeBrew,$(shell if $(TEST) -d /usr/local/Cellar; then echo HomeBrew; fi)) + INCPATH += $(foreach dir,$(wildcard /usr/local/Cellar/*/*),$(dir)/include) + LIBPATH += $(foreach dir,$(wildcard /usr/local/Cellar/*/*),$(dir)/lib) + endif + ifeq (libXt,$(shell if $(TEST) -d /usr/X11/lib; then echo libXt; fi)) + LIBPATH += /usr/X11/lib + OS_LDFLAGS += -L/usr/X11/lib + endif + else + ifeq (Linux,$(OSTYPE)) + ifneq (lib,$(findstring lib,$(UNSUPPORTED_BUILD))) + LIBPATH := $(sort $(foreach lib,$(shell /sbin/ldconfig -p | grep ' => /' | sed 's/^.* => //'),$(dir $(lib)))) + endif + LIBEXT = so + else + ifeq (SunOS,$(OSTYPE)) + OSNAME = Solaris + ifneq (lib,$(findstring lib,$(UNSUPPORTED_BUILD))) + LIBPATH := $(shell LANG=C; crle | grep 'Default Library Path' | awk '{ print $$5 }' | sed 's/:/ /g') + endif + LIBEXT = so + OS_LDFLAGS += -lsocket -lnsl + ifeq (incsfw,$(shell if $(TEST) -d /opt/sfw/include; then echo incsfw; fi)) + INCPATH += /opt/sfw/include + OS_CCDEFS += -I/opt/sfw/include + endif + ifeq (libsfw,$(shell if $(TEST) -d /opt/sfw/lib; then echo libsfw; fi)) + LIBPATH += /opt/sfw/lib + OS_LDFLAGS += -L/opt/sfw/lib -R/opt/sfw/lib + endif + OS_CCDEFS += -D_LARGEFILE_SOURCE + else + ifeq (cygwin,$(OSTYPE)) + # use 0readme_ethernet.txt documented Windows pcap build components + INCPATH += ../windows-build/winpcap/WpdPack/include + LIBPATH += ../windows-build/winpcap/WpdPack/lib + PCAPLIB = wpcap + LIBEXT = a + else + ifneq (,$(findstring AIX,$(OSTYPE))) + OS_LDFLAGS += -lm -lrt + ifeq (incopt,$(shell if $(TEST) -d /opt/freeware/include; then echo incopt; fi)) + INCPATH += /opt/freeware/include + OS_CCDEFS += -I/opt/freeware/include + endif + ifeq (libopt,$(shell if $(TEST) -d /opt/freeware/lib; then echo libopt; fi)) + LIBPATH += /opt/freeware/lib + OS_LDFLAGS += -L/opt/freeware/lib + endif + else + ifneq (,$(findstring Haiku,$(OSTYPE))) + HAIKU_ARCH=$(shell getarch) + ifeq ($(HAIKU_ARCH),) + $(error Missing getarch command, your Haiku release is probably too old) + endif + ifeq ($(HAIKU_ARCH),x86_gcc2) + $(error Unsupported arch x86_gcc2. Run setarch x86 and retry) + endif + INCPATH := $(shell findpaths -e -a $(HAIKU_ARCH) B_FIND_PATH_HEADERS_DIRECTORY) + INCPATH += $(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY posix) + LIBPATH := $(shell findpaths -e -a $(HAIKU_ARCH) B_FIND_PATH_DEVELOP_LIB_DIRECTORY) + OS_LDFLAGS += -lnetwork + else + ifeq (,$(findstring NetBSD,$(OSTYPE))) + ifneq (no ldconfig,$(findstring no ldconfig,$(shell which ldconfig 2>&1))) + LDSEARCH :=$(shell LANG=C; ldconfig -r | grep 'search directories' | awk '{print $$3}' | sed 's/:/ /g') + endif + ifneq (,$(LDSEARCH)) + LIBPATH := $(LDSEARCH) + else + ifeq (,$(strip $(LPATH))) + $(info *** Warning ***) + $(info *** Warning *** The library search path on your $(OSTYPE) platform can't be) + $(info *** Warning *** determined. This should be resolved before you can expect) + $(info *** Warning *** to have fully working simulators.) + $(info *** Warning ***) + $(info *** Warning *** You can specify your library paths via the LPATH environment) + $(info *** Warning *** variable.) + $(info *** Warning ***) + else + LIBPATH = $(subst :, ,$(LPATH)) + endif + endif + OS_LDFLAGS += $(patsubst %,-L%,$(LIBPATH)) + endif + endif + endif + ifeq (usrpkglib,$(shell if $(TEST) -d /usr/pkg/lib; then echo usrpkglib; fi)) + LIBPATH += /usr/pkg/lib + INCPATH += /usr/pkg/include + OS_LDFLAGS += -L/usr/pkg/lib -R/usr/pkg/lib + OS_CCDEFS += -I/usr/pkg/include + endif + ifeq (X11R7,$(shell if $(TEST) -d /usr/X11R7/lib; then echo X11R7; fi)) + LIBPATH += /usr/X11R7/lib + INCPATH += /usr/X11R7/include + OS_LDFLAGS += -L/usr/X11R7/lib -R/usr/X11R7/lib + OS_CCDEFS += -I/usr/X11R7/include + endif + ifeq (/usr/local/lib,$(findstring /usr/local/lib,$(LIBPATH))) + INCPATH += /usr/local/include + OS_CCDEFS += -I/usr/local/include + endif + ifneq (,$(findstring NetBSD,$(OSTYPE))$(findstring FreeBSD,$(OSTYPE))$(findstring AIX,$(OSTYPE))) + LIBEXT = so + else + ifeq (HP-UX,$(OSTYPE)) + ifeq (ia64,$(shell uname -m)) + LIBEXT = so + else + LIBEXT = sl + endif + OS_CCDEFS += -D_HPUX_SOURCE -D_LARGEFILE64_SOURCE + OS_LDFLAGS += -Wl,+b: + NO_LTO = 1 + else + LIBEXT = a + endif + endif + endif + endif + endif + endif + # Some gcc versions don't support LTO, so only use LTO when the compiler is known to support it + ifeq (,$(NO_LTO)) + ifneq (,$(GCC_VERSION)) + ifeq (,$(shell $(GCC) -v /dev/null 2>&1 | grep '\-\-enable-lto')) + LTO_EXCLUDE_VERSIONS += $(GCC_VERSION) + endif + endif + endif + endif + $(info lib paths are: $(LIBPATH)) + $(info include paths are: $(INCPATH)) + need_search = $(strip $(shell ld -l$(1) /dev/null 2>&1 | grep $(1) | sed s/$(1)//)) + LD_SEARCH_NEEDED := $(call need_search,ZzzzzzzZ) + ifneq (,$(call find_lib,m)) + OS_LDFLAGS += -lm + $(info using libm: $(call find_lib,m)) + endif + ifneq (,$(call find_lib,rt)) + OS_LDFLAGS += -lrt + $(info using librt: $(call find_lib,rt)) + endif + ifneq (,$(NOPTHREADS)) + OS_CCDEFS += -DDONT_USE_READER_THREAD + else + ifneq (,$(call find_include,pthread)) + ifneq (,$(call find_lib,pthread)) + OS_CCDEFS += -DUSE_READER_THREAD + ifeq (,$(NOASYNCH)) + OS_CCDEFS += -DSIM_ASYNCH_IO + endif + OS_LDFLAGS += -lpthread + $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) + else + LIBEXTSAVE := $(LIBEXT) + LIBEXT = a + ifneq (,$(call find_lib,pthread)) + OS_CCDEFS += -DUSE_READER_THREAD + ifeq (,$(NOASYNCH)) + OS_CCDEFS += -DSIM_ASYNCH_IO + endif + OS_LDFLAGS += -lpthread + $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) + else + ifneq (,$(findstring Haiku,$(OSTYPE))) + OS_CCDEFS += -DUSE_READER_THREAD + ifeq (,$(NOASYNCH)) + OS_CCDEFS += -DSIM_ASYNCH_IO + endif + $(info using libpthread: $(call find_include,pthread)) + endif + endif + LIBEXT = $(LIBEXTSAVE) + endif + endif + endif + # Find available RegEx library. Prefer libpcreposix. + ifneq (,$(call find_include,pcreposix)) + ifneq (,$(call find_lib,pcreposix)) + OS_CCDEFS += -DHAVE_PCREPOSIX_H + OS_LDFLAGS += -lpcreposix + $(info using libpcreposix: $(call find_lib,pcreposix) $(call find_include,pcreposix)) + ifeq ($(LD_SEARCH_NEEDED),$(call need_search,pcreposix)) + OS_LDFLAGS += -L$(dir $(call find_lib,pcreposix)) + endif + endif + else + # If libpcreposix isn't available, fall back to the local regex.h + # Presume that the local regex support is available in the C runtime + # without a specific reference to a library. This may not be true on + # some platforms. + ifneq (,$(call find_include,regex)) + OS_CCDEFS += -DHAVE_REGEX_H + $(info using regex: $(call find_include,regex)) + endif + endif + ifneq (,$(call find_include,dlfcn)) + ifneq (,$(call find_lib,dl)) + OS_CCDEFS += -DHAVE_DLOPEN=$(LIBEXT) + OS_LDFLAGS += -ldl + $(info using libdl: $(call find_lib,dl) $(call find_include,dlfcn)) + else + ifneq (,$(findstring BSD,$(OSTYPE))$(findstring AIX,$(OSTYPE))$(findstring Haiku,$(OSTYPE))) + OS_CCDEFS += -DHAVE_DLOPEN=so + $(info using libdl: $(call find_include,dlfcn)) + else + ifneq (,$(call find_lib,dld)) + OS_CCDEFS += -DHAVE_DLOPEN=$(LIBEXT) + OS_LDFLAGS += -ldld + $(info using libdld: $(call find_lib,dld) $(call find_include,dlfcn)) + endif + endif + endif + endif + ifneq (,$(call find_include,utime)) + OS_CCDEFS += -DHAVE_UTIME + endif + ifneq (,$(call find_include,png)) + ifneq (,$(call find_lib,png)) + OS_CCDEFS += -DHAVE_LIBPNG + OS_LDFLAGS += -lpng + $(info using libpng: $(call find_lib,png) $(call find_include,png)) + endif + endif + ifneq (,$(call find_include,glob)) + OS_CCDEFS += -DHAVE_GLOB + else + ifneq (,$(call find_include,fnmatch)) + OS_CCDEFS += -DHAVE_FNMATCH + endif + endif + ifneq (,$(call find_include,sys/mman)) + ifneq (,$(shell grep shm_open $(call find_include,sys/mman))) + OS_CCDEFS += -DHAVE_SHM_OPEN + $(info using mman: $(call find_include,sys/mman)) + endif + endif + ifneq (,$(VIDEO_USEFUL)) + ifeq (cygwin,$(OSTYPE)) + LIBEXTSAVE := $(LIBEXT) + LIBEXT = dll.a + endif + ifneq (,$(call find_include,SDL2/SDL)) + ifneq (,$(call find_lib,SDL2)) + ifneq (,$(findstring Haiku,$(OSTYPE))) + ifneq (,$(shell which sdl2-config)) + SDLX_CONFIG = sdl2-config + endif + else + SDLX_CONFIG = $(realpath $(dir $(call find_include,SDL2/SDL))../../bin/sdl2-config) + endif + ifneq (,$(SDLX_CONFIG)) + VIDEO_CCDEFS += -DHAVE_LIBSDL -DUSE_SIM_VIDEO `$(SDLX_CONFIG) --cflags` + VIDEO_LDFLAGS += `$(SDLX_CONFIG) --libs` + VIDEO_FEATURES = - video capabilities provided by libSDL2 (Simple Directmedia Layer) + DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/sim_ws.c + DISPLAYVT = ${DISPLAYD}/vt11.c + DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS) + $(info using libSDL2: $(call find_include,SDL2/SDL)) + ifeq (Darwin,$(OSTYPE)) + VIDEO_CCDEFS += -DSDL_MAIN_AVAILABLE + endif + endif + endif + else + ifneq (,$(call find_include,SDL/SDL)) + ifneq (,$(call find_lib,SDL)) + ifneq (,$(findstring Haiku,$(OSTYPE))) + ifneq (,$(shell which sdl-config)) + SDLX_CONFIG = sdl-config + endif + else + SDLX_CONFIG = $(realpath $(dir $(call find_include,SDL/SDL))../../bin/sdl-config) + endif + ifneq (,$(SDLX_CONFIG)) + VIDEO_CCDEFS += -DHAVE_LIBSDL -DUSE_SIM_VIDEO `$(SDLX_CONFIG) --cflags` + VIDEO_LDFLAGS += `$(SDLX_CONFIG) --libs` + VIDEO_FEATURES = - video capabilities provided by libSDL (Simple Directmedia Layer) + DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/sim_ws.c + DISPLAYVT = ${DISPLAYD}/vt11.c + DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS) + $(info using libSDL: $(call find_include,SDL/SDL)) + ifeq (Darwin,$(OSTYPE)) + VIDEO_CCDEFS += -DSDL_MAIN_AVAILABLE + endif + endif + endif + endif + endif + ifeq (cygwin,$(OSTYPE)) + LIBEXT = $(LIBEXTSAVE) + endif + ifeq (,$(findstring HAVE_LIBSDL,$(VIDEO_CCDEFS))) + $(info *** Info ***) + $(info *** Info *** The simulator$(BUILD_MULTIPLE) you are building could provide more) + $(info *** Info *** functionality if video support were available on your system.) + ifeq (Darwin,$(OSTYPE)) + $(info *** Info *** Install the MacPorts libSDL2 package to provide this) + $(info *** Info *** functionality for your OS X system:) + $(info *** Info *** # port install libsdl2) + ifeq (/usr/local/bin/brew,$(shell which brew)) + $(info *** Info ***) + $(info *** Info *** OR) + $(info *** Info ***) + $(info *** Info *** Install the HomeBrew libSDL2 package to provide this) + $(info *** Info *** functionality for your OS X system:) + $(info *** Info *** $$ brew install sdl2) + endif + else + ifneq (,$(and $(findstring Linux,$(OSTYPE)),$(call find_exe,apt-get))) + $(info *** Info *** Install the development components of libSDL or libSDL2) + $(info *** Info *** packaged for your operating system distribution for) + $(info *** Info *** your Linux system:) + $(info *** Info *** $$ sudo apt-get install libsdl2-dev) + $(info *** Info *** or) + $(info *** Info *** $$ sudo apt-get install libsdl-dev) + else + $(info *** Info *** Install the development components of libSDL packaged by your) + $(info *** Info *** operating system distribution and rebuild your simulator to) + $(info *** Info *** enable this extra functionality.) + endif + endif + $(info *** Info ***) + endif + endif + ifneq (,$(NETWORK_USEFUL)) + ifneq (,$(call find_include,pcap)) + ifneq (,$(shell grep 'pcap/pcap.h' $(call find_include,pcap) | grep include)) + PCAP_H_PATH = $(dir $(call find_include,pcap))pcap/pcap.h + else + PCAP_H_PATH = $(call find_include,pcap) + endif + ifneq (,$(shell grep pcap_compile $(PCAP_H_PATH) | grep const)) + BPF_CONST_STRING = -DBPF_CONST_STRING + endif + NETWORK_CCDEFS += -DHAVE_PCAP_NETWORK -I$(dir $(call find_include,pcap)) $(BPF_CONST_STRING) + NETWORK_LAN_FEATURES += PCAP + ifneq (,$(call find_lib,$(PCAPLIB))) + ifneq ($(USE_NETWORK),) # Network support specified on the GNU make command line + NETWORK_CCDEFS += -DUSE_NETWORK + ifeq (,$(findstring Linux,$(OSTYPE))$(findstring Darwin,$(OSTYPE))) + $(info *** Warning ***) + $(info *** Warning *** Statically linking against libpcap is provides no measurable) + $(info *** Warning *** benefits over dynamically linking libpcap.) + $(info *** Warning ***) + $(info *** Warning *** Support for linking this way is currently deprecated and may be removed) + $(info *** Warning *** in the future.) + $(info *** Warning ***) + else + $(info *** Error ***) + $(info *** Error *** Statically linking against libpcap is provides no measurable) + $(info *** Error *** benefits over dynamically linking libpcap.) + $(info *** Error ***) + $(info *** Error *** Support for linking statically has been removed on the $(OSTYPE)) + $(info *** Error *** platform.) + $(info *** Error ***) + $(error Retry your build without specifying USE_NETWORK=1) + endif + ifeq (cygwin,$(OSTYPE)) + # cygwin has no ldconfig so explicitly specify pcap object library + NETWORK_LDFLAGS = -L$(dir $(call find_lib,$(PCAPLIB))) -Wl,-R,$(dir $(call find_lib,$(PCAPLIB))) -l$(PCAPLIB) + else + NETWORK_LDFLAGS = -l$(PCAPLIB) + endif + $(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap)) + NETWORK_FEATURES = - static networking support using $(OSNAME) provided libpcap components + else # default build uses dynamic libpcap + NETWORK_CCDEFS += -DUSE_SHARED + $(info using libpcap: $(call find_include,pcap)) + NETWORK_FEATURES = - dynamic networking support using $(OSNAME) provided libpcap components + endif + else + LIBEXTSAVE := $(LIBEXT) + LIBEXT = a + ifneq (,$(call find_lib,$(PCAPLIB))) + NETWORK_CCDEFS += -DUSE_NETWORK + NETWORK_LDFLAGS := -L$(dir $(call find_lib,$(PCAPLIB))) -l$(PCAPLIB) + NETWORK_FEATURES = - static networking support using $(OSNAME) provided libpcap components + $(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap)) + endif + LIBEXT = $(LIBEXTSAVE) + endif + else + # On non-Linux platforms, we'll still try to provide deprecated support for libpcap in /usr/local + INCPATHSAVE := $(INCPATH) + ifeq (,$(findstring Linux,$(OSTYPE))) + # Look for package built from tcpdump.org sources with default install target (or cygwin winpcap) + INCPATH += /usr/local/include + PCAP_H_FOUND = $(call find_include,pcap) + endif + ifneq (,$(strip $(PCAP_H_FOUND))) + ifneq (,$(shell grep 'pcap/pcap.h' $(call find_include,pcap) | grep include)) + PCAP_H_PATH = $(dir $(call find_include,pcap))pcap/pcap.h + else + PCAP_H_PATH = $(call find_include,pcap) + endif + ifneq (,$(shell grep pcap_compile $(PCAP_H_PATH) | grep const)) + BPF_CONST_STRING = -DBPF_CONST_STRING + endif + LIBEXTSAVE := $(LIBEXT) + # first check if binary - shared objects are available/installed in the linker known search paths + ifneq (,$(call find_lib,$(PCAPLIB))) + NETWORK_CCDEFS = -DUSE_SHARED -I$(dir $(call find_include,pcap)) $(BPF_CONST_STRING) + NETWORK_FEATURES = - dynamic networking support using libpcap components from www.tcpdump.org and locally installed libpcap.$(LIBEXT) + $(info using libpcap: $(call find_include,pcap)) + else + LIBPATH += /usr/local/lib + LIBEXT = a + ifneq (,$(call find_lib,$(PCAPLIB))) + $(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap)) + ifeq (cygwin,$(OSTYPE)) + NETWORK_CCDEFS = -DUSE_NETWORK -DHAVE_PCAP_NETWORK -I$(dir $(call find_include,pcap)) $(BPF_CONST_STRING) + NETWORK_LDFLAGS = -L$(dir $(call find_lib,$(PCAPLIB))) -Wl,-R,$(dir $(call find_lib,$(PCAPLIB))) -l$(PCAPLIB) + NETWORK_FEATURES = - static networking support using libpcap components located in the cygwin directories + else + NETWORK_CCDEFS := -DUSE_NETWORK -DHAVE_PCAP_NETWORK -isystem -I$(dir $(call find_include,pcap)) $(BPF_CONST_STRING) $(call find_lib,$(PCAPLIB)) + NETWORK_FEATURES = - networking support using libpcap components from www.tcpdump.org + $(info *** Warning ***) + $(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) being built with networking support using) + $(info *** Warning *** libpcap components from www.tcpdump.org.) + $(info *** Warning *** Some users have had problems using the www.tcpdump.org libpcap) + $(info *** Warning *** components for simh networking. For best results, with) + $(info *** Warning *** simh networking, it is recommended that you install the) + $(info *** Warning *** libpcap-dev (or libpcap-devel) package from your $(OSNAME) distribution) + $(info *** Warning ***) + $(info *** Warning *** Building with the components manually installed from www.tcpdump.org) + $(info *** Warning *** is officially deprecated. Attempting to do so is unsupported.) + $(info *** Warning ***) + endif + else + $(error using libpcap: $(call find_include,pcap) missing $(PCAPLIB).$(LIBEXT)) + endif + NETWORK_LAN_FEATURES += PCAP + endif + LIBEXT = $(LIBEXTSAVE) + else + INCPATH = $(INCPATHSAVE) + $(info *** Warning ***) + $(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) are being built WITHOUT) + $(info *** Warning *** libpcap networking support) + $(info *** Warning ***) + $(info *** Warning *** To build simulator(s) with libpcap networking support you) + ifneq (,$(and $(findstring Linux,$(OSTYPE)),$(call find_exe,apt-get))) + $(info *** Warning *** should install the libpcap development components for) + $(info *** Warning *** for your Linux system:) + $(info *** Warning *** $$ sudo apt-get install libpcap-dev) + else + $(info *** Warning *** should read 0readme_ethernet.txt and follow the instructions) + $(info *** Warning *** regarding the needed libpcap development components for your) + $(info *** Warning *** $(OSTYPE) platform) + endif + $(info *** Warning ***) + endif + endif + # Consider other network connections + ifneq (,$(call find_lib,vdeplug)) + # libvdeplug requires the use of the OS provided libpcap + ifeq (,$(findstring usr/local,$(NETWORK_CCDEFS))) + ifneq (,$(call find_include,libvdeplug)) + # Provide support for vde networking + NETWORK_CCDEFS += -DHAVE_VDE_NETWORK + NETWORK_LAN_FEATURES += VDE + ifeq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS))) + NETWORK_CCDEFS += -DUSE_NETWORK + endif + ifeq (Darwin,$(OSTYPE)) + NETWORK_LDFLAGS += -lvdeplug -L$(dir $(call find_lib,vdeplug)) + else + NETWORK_LDFLAGS += -lvdeplug -Wl,-R,$(dir $(call find_lib,vdeplug)) -L$(dir $(call find_lib,vdeplug)) + endif + $(info using libvdeplug: $(call find_lib,vdeplug) $(call find_include,libvdeplug)) + endif + endif + endif + ifeq (,$(findstring HAVE_VDE_NETWORK,$(NETWORK_CCDEFS))) + # Support is available on Linux for libvdeplug. Advise on its usage + ifneq (,$(findstring Linux,$(OSTYPE))$(findstring Darwin,$(OSTYPE))) + ifneq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS))) + $(info *** Info ***) + $(info *** Info *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) are being built with) + $(info *** Info *** minimal libpcap networking support) + $(info *** Info ***) + endif + $(info *** Info ***) + $(info *** Info *** Simulators on your $(OSNAME) platform can also be built with) + $(info *** Info *** extended LAN Ethernet networking support by using VDE Ethernet.) + $(info *** Info ***) + $(info *** Info *** To build simulator(s) with extended networking support you) + ifeq (Darwin,$(OSTYPE)) + $(info *** Info *** should install the MacPorts vde2 package to provide this) + $(info *** Info *** functionality for your OS X system:) + $(info *** Info *** # port install vde2) + ifeq (/usr/local/bin/brew,$(shell which brew)) + $(info *** Info ***) + $(info *** Info *** OR) + $(info *** Info ***) + $(info *** Info *** Install the HomeBrew vde package to provide this) + $(info *** Info *** functionality for your OS X system:) + $(info *** Info *** $$ brew install vde) + endif + else + ifneq (,$(and $(findstring Linux,$(OSTYPE)),$(call find_exe,apt-get))) + $(info *** Info *** should install the vde2 package to provide this) + $(info *** Info *** functionality for your $(OSNAME) system:) + ifneq (,$(shell apt list 2>/dev/null| grep libvdeplug-dev)) + $(info *** Info *** $$ sudo apt-get install libvdeplug-dev) + else + $(info *** Info *** $$ sudo apt-get install vde2) + endif + else + $(info *** Info *** should read 0readme_ethernet.txt and follow the instructions) + $(info *** Info *** regarding the needed libvdeplug components for your $(OSNAME)) + $(info *** Info *** platform) + endif + endif + $(info *** Info ***) + endif + endif + ifneq (,$(call find_include,linux/if_tun)) + # Provide support for Tap networking on Linux + NETWORK_CCDEFS += -DHAVE_TAP_NETWORK + NETWORK_LAN_FEATURES += TAP + ifeq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS))) + NETWORK_CCDEFS += -DUSE_NETWORK + endif + endif + ifeq (bsdtuntap,$(shell if $(TEST) -e /usr/include/net/if_tun.h -o -e /Library/Extensions/tap.kext; then echo bsdtuntap; fi)) + # Provide support for Tap networking on BSD platforms (including OS X) + NETWORK_CCDEFS += -DHAVE_TAP_NETWORK -DHAVE_BSDTUNTAP + NETWORK_LAN_FEATURES += TAP + ifeq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS))) + NETWORK_CCDEFS += -DUSE_NETWORK + endif + endif + ifeq (slirp,$(shell if $(TEST) -e slirp_glue/sim_slirp.c; then echo slirp; fi)) + NETWORK_CCDEFS += -Islirp -Islirp_glue -Islirp_glue/qemu -DHAVE_SLIRP_NETWORK -DUSE_SIMH_SLIRP_DEBUG slirp/*.c slirp_glue/*.c + NETWORK_LAN_FEATURES += NAT(SLiRP) + endif + ifeq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS))$(findstring HAVE_VDE_NETWORK,$(NETWORK_CCDEFS))) + NETWORK_CCDEFS += -DUSE_NETWORK + NETWORK_FEATURES = - WITHOUT Local LAN networking support + $(info *** Warning ***) + $(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) are being built WITHOUT LAN networking support) + $(info *** Warning ***) + $(info *** Warning *** To build simulator(s) with networking support you should read) + $(info *** Warning *** 0readme_ethernet.txt and follow the instructions regarding the) + $(info *** Warning *** needed libpcap components for your $(OSTYPE) platform) + $(info *** Warning ***) + endif + NETWORK_OPT = $(NETWORK_CCDEFS) + endif + ifneq (binexists,$(shell if $(TEST) -e BIN; then echo binexists; fi)) + MKDIRBIN = mkdir -p BIN + endif + ifeq (commit-id-exists,$(shell if $(TEST) -e .git-commit-id; then echo commit-id-exists; fi)) + GIT_COMMIT_ID=$(shell cat .git-commit-id) + else + ifeq (,$(shell grep 'define SIM_GIT_COMMIT_ID' ../sim_rev.h | grep 'Format:')) + GIT_COMMIT_ID=$(shell grep 'define SIM_GIT_COMMIT_ID' ../sim_rev.h | awk '{ print $$3 }') + else + ifeq (git-submodule,$(if $(shell cd .. ; git rev-parse --git-dir 2>/dev/null),git-submodule)) + GIT_COMMIT_ID=$(shell cd .. ; git submodule status | grep "$(notdir $(realpath .))" | awk '{ print $$1 }') + else + GIT_COMMIT_ID=undetermined-git-id + endif + endif + endif +else + #Win32 Environments (via MinGW32) + GCC := gcc + GCC_Path := $(abspath $(dir $(word 1,$(wildcard $(addsuffix /$(GCC).exe,$(subst ;, ,$(PATH))))))) + ifeq (rename-build-support,$(shell if exist ..\windows-build-windows-build echo rename-build-support)) + REMOVE_OLD_BUILD := $(shell if exist ..\windows-build rmdir/s/q ..\windows-build) + FIXED_BUILD := $(shell move ..\windows-build-windows-build ..\windows-build >NUL) + endif + GCC_VERSION = $(word 3,$(shell $(GCC) --version)) + COMPILER_NAME = GCC Version: $(GCC_VERSION) + ifeq (,$(findstring ++,$(GCC))) + CC_STD = -std=gnu99 + else + CPP_BUILD = 1 + endif + LTO_EXCLUDE_VERSIONS = 4.5.2 + ifeq (,$(PATH_SEPARATOR)) + PATH_SEPARATOR := ; + endif + INCPATH = $(abspath $(wildcard $(GCC_Path)\..\include $(subst $(PATH_SEPARATOR), ,$(CPATH)) $(subst $(PATH_SEPARATOR), ,$(C_INCLUDE_PATH)))) + LIBPATH = $(abspath $(wildcard $(GCC_Path)\..\lib $(subst :, ,$(LIBRARY_PATH)))) + $(info lib paths are: $(LIBPATH)) + $(info include paths are: $(INCPATH)) + # Give preference to any MinGW provided threading (if available) + ifneq (,$(call find_include,pthread)) + PTHREADS_CCDEFS = -DUSE_READER_THREAD + ifeq (,$(NOASYNCH)) + PTHREADS_CCDEFS += -DSIM_ASYNCH_IO + endif + PTHREADS_LDFLAGS = -lpthread + else + ifeq (pthreads,$(shell if exist ..\windows-build\pthreads\Pre-built.2\include\pthread.h echo pthreads)) + PTHREADS_CCDEFS = -DUSE_READER_THREAD -DPTW32_STATIC_LIB -D_POSIX_C_SOURCE -I../windows-build/pthreads/Pre-built.2/include + ifeq (,$(NOASYNCH)) + PTHREADS_CCDEFS += -DSIM_ASYNCH_IO + endif + PTHREADS_LDFLAGS = -lpthreadGC2 -L..\windows-build\pthreads\Pre-built.2\lib + endif + endif + ifeq (pcap,$(shell if exist ..\windows-build\winpcap\Wpdpack\include\pcap.h echo pcap)) + NETWORK_LDFLAGS = + NETWORK_OPT = -DUSE_SHARED -I../windows-build/winpcap/Wpdpack/include + NETWORK_FEATURES = - dynamic networking support using windows-build provided libpcap components + NETWORK_LAN_FEATURES += PCAP + else + ifneq (,$(call find_include,pcap)) + NETWORK_LDFLAGS = + NETWORK_OPT = -DUSE_SHARED + NETWORK_FEATURES = - dynamic networking support using libpcap components found in the MinGW directories + NETWORK_LAN_FEATURES += PCAP + endif + endif + ifneq (,$(VIDEO_USEFUL)) + SDL_INCLUDE = $(word 1,$(shell dir /b /s ..\windows-build\libSDL\SDL.h)) + ifeq (SDL.h,$(findstring SDL.h,$(SDL_INCLUDE))) + VIDEO_CCDEFS += -DHAVE_LIBSDL -I$(abspath $(dir $(SDL_INCLUDE))) + VIDEO_LDFLAGS += -lSDL2 -L$(abspath $(dir $(SDL_INCLUDE))\..\lib) + VIDEO_FEATURES = - video capabilities provided by libSDL2 (Simple Directmedia Layer) + else + $(info ***********************************************************************) + $(info ***********************************************************************) + $(info ** This build could produce simulators with video capabilities. **) + $(info ** However, the required files to achieve this can't be found on **) + $(info ** this system. Download the file: **) + $(info ** https://github.com/simh/windows-build/archive/windows-build.zip **) + $(info ** Extract the windows-build-windows-build folder it contains to **) + $(info ** $(abspath ..\) **) + $(info ***********************************************************************) + $(info ***********************************************************************) + $(info .) + endif + endif + OS_CCDEFS += -fms-extensions $(PTHREADS_CCDEFS) + OS_LDFLAGS += -lm -lwsock32 -lwinmm $(PTHREADS_LDFLAGS) + EXE = .exe + ifneq (binexists,$(shell if exist BIN echo binexists)) + MKDIRBIN = if not exist BIN mkdir BIN + endif + ifneq ($(USE_NETWORK),) + NETWORK_OPT += -DUSE_SHARED + endif + ifneq (,$(shell if exist .git-commit-id type .git-commit-id)) + GIT_COMMIT_ID=$(shell if exist .git-commit-id type .git-commit-id) + else + ifeq (,$(shell findstr /C:"define SIM_GIT_COMMIT_ID" ../sim_rev.h | findstr Format)) + GIT_COMMIT_ID=$(shell for /F "tokens=3" %%i in ("$(shell findstr /C:"define SIM_GIT_COMMIT_ID" ../sim_rev.h)") do echo %%i) + endif + endif + ifneq (windows-build,$(shell if exist ..\windows-build\README.md echo windows-build)) + $(info ***********************************************************************) + $(info ***********************************************************************) + $(info ** This build is operating without the required windows-build **) + $(info ** components and therefore will produce less than optimal **) + $(info ** simulator operation and features. **) + $(info ** Download the file: **) + $(info ** https://github.com/simh/windows-build/archive/windows-build.zip **) + $(info ** Extract the windows-build-windows-build folder it contains to **) + $(info ** $(abspath ..\) **) + $(info ***********************************************************************) + $(info ***********************************************************************) + $(info .) + else + # Version check on windows-build + WINDOWS_BUILD = $(word 2,$(shell findstr WINDOWS-BUILD ..\windows-build\Windows-Build_Versions.txt)) + ifeq (,$(WINDOWS_BUILD)) + WINDOWS_BUILD = 00000000 + endif + ifneq (,$(or $(shell if 20150412 GTR $(WINDOWS_BUILD) echo old-windows-build),$(and $(shell if 20171112 GTR $(WINDOWS_BUILD) echo old-windows-build),$(findstring pthreadGC2,$(PTHREADS_LDFLAGS))))) + $(info .) + $(info windows-build components at: $(abspath ..\windows-build)) + $(info .) + $(info ***********************************************************************) + $(info ***********************************************************************) + $(info ** This currently available windows-build components are out of **) + $(info ** date. For the most functional and stable features you shoud **) + $(info ** Download the file: **) + $(info ** https://github.com/simh/windows-build/archive/windows-build.zip **) + $(info ** Extract the windows-build-windows-build folder it contains to **) + $(info ** $(abspath ..\) **) + $(info ***********************************************************************) + $(info ***********************************************************************) + $(info .) + endif + ifeq (pcre,$(shell if exist ..\windows-build\PCRE\include\pcre.h echo pcre)) + OS_CCDEFS += -DHAVE_PCREPOSIX_H -DPCRE_STATIC -I$(abspath ../windows-build/PCRE/include) + OS_LDFLAGS += -lpcreposix -lpcre -L../windows-build/PCRE/lib/ + $(info using libpcreposix: $(abspath ../windows-build/PCRE/lib/pcreposix.a) $(abspath ../windows-build/PCRE/include/pcreposix.h)) + endif + ifeq (slirp,slirp) + NETWORK_OPT += -Islirp -Islirp_glue -Islirp_glue/qemu -DHAVE_SLIRP_NETWORK -DUSE_SIMH_SLIRP_DEBUG slirp/*.c slirp_glue/*.c -lIphlpapi + NETWORK_LAN_FEATURES += NAT(SLiRP) + endif + endif + ifneq (,$(call find_include,ddk/ntdddisk)) + CFLAGS_I = -DHAVE_NTDDDISK_H + endif +endif # Win32 (via MinGW) +ifneq (,$(GIT_COMMIT_ID)) + CFLAGS_GIT = -DSIM_GIT_COMMIT_ID=$(GIT_COMMIT_ID) +endif +ifneq (,$(UNSUPPORTED_BUILD)) + CFLAGS_GIT += -DSIM_BUILD=Unsupported=$(UNSUPPORTED_BUILD) +endif +ifneq ($(DEBUG),) + CFLAGS_G = -g -ggdb -g3 + CFLAGS_O = -O0 + BUILD_FEATURES = - debugging support +else + ifneq (clang,$(findstring clang,$(COMPILER_NAME))) + CFLAGS_O = -O2 + ifeq (Darwin,$(OSTYPE)) + NO_LTO = 1 + endif + else + NO_LTO = 1 + ifeq (Darwin,$(OSTYPE)) + CFLAGS_O += -O4 -fno-strict-overflow -flto -fwhole-program + else + CFLAGS_O := -O2 -fno-strict-overflow + endif + endif + LDFLAGS_O = + GCC_MAJOR_VERSION = $(firstword $(subst ., ,$(GCC_VERSION))) + ifneq (3,$(GCC_MAJOR_VERSION)) + ifeq (,$(GCC_OPTIMIZERS_CMD)) + GCC_OPTIMIZERS_CMD = $(GCC) --help=optimizers + endif + GCC_OPTIMIZERS = $(shell $(GCC_OPTIMIZERS_CMD)) + endif + ifneq (,$(findstring $(GCC_VERSION),$(LTO_EXCLUDE_VERSIONS))) + NO_LTO = 1 + endif + ifneq (,$(findstring -finline-functions,$(GCC_OPTIMIZERS))) + CFLAGS_O += -finline-functions + endif + ifneq (,$(findstring -fgcse-after-reload,$(GCC_OPTIMIZERS))) + CFLAGS_O += -fgcse-after-reload + endif + ifneq (,$(findstring -fpredictive-commoning,$(GCC_OPTIMIZERS))) + CFLAGS_O += -fpredictive-commoning + endif + ifneq (,$(findstring -fipa-cp-clone,$(GCC_OPTIMIZERS))) + CFLAGS_O += -fipa-cp-clone + endif + ifneq (,$(findstring -funsafe-loop-optimizations,$(GCC_OPTIMIZERS))) + CFLAGS_O += -fno-unsafe-loop-optimizations + endif + ifneq (,$(findstring -fstrict-overflow,$(GCC_OPTIMIZERS))) + CFLAGS_O += -fno-strict-overflow + endif + ifeq (,$(NO_LTO)) + ifneq (,$(findstring -flto,$(GCC_OPTIMIZERS))) + CFLAGS_O += -flto -fwhole-program + LDFLAGS_O += -flto -fwhole-program + endif + endif + BUILD_FEATURES = - compiler optimizations and no debugging support +endif +ifneq (3,$(GCC_MAJOR_VERSION)) + ifeq (,$(GCC_WARNINGS_CMD)) + GCC_WARNINGS_CMD = $(GCC) --help=warnings + endif + ifneq (,$(findstring -Wunused-result,$(shell $(GCC_WARNINGS_CMD)))) + CFLAGS_O += -Wno-unused-result + endif +endif +ifneq (clean,$(MAKECMDGOALS)) + BUILD_FEATURES := $(BUILD_FEATURES). $(COMPILER_NAME) + $(info ***) + $(info *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) being built with:) + $(info *** $(BUILD_FEATURES).) + ifneq (,$(NETWORK_FEATURES)) + $(info *** $(NETWORK_FEATURES).) + endif + ifneq (,$(NETWORK_LAN_FEATURES)) + $(info *** - Local LAN packet transports: $(NETWORK_LAN_FEATURES)) + endif + ifneq (,$(VIDEO_FEATURES)) + $(info *** $(VIDEO_FEATURES).) + endif + ifneq (,$(GIT_COMMIT_ID)) + $(info ***) + $(info *** git commit id is $(GIT_COMMIT_ID).) + endif + $(info ***) +endif +ifneq ($(DONT_USE_ROMS),) + ROMS_OPT = -DDONT_USE_INTERNAL_ROM +else + BUILD_ROMS = ${BIN}BuildROMs${EXE} +endif +ifneq ($(DONT_USE_READER_THREAD),) + NETWORK_OPT += -DDONT_USE_READER_THREAD +endif + +CC_OUTSPEC = -o $@ +CC := $(GCC) $(CC_STD) -U__STRICT_ANSI__ $(CFLAGS_G) $(CFLAGS_O) $(CFLAGS_GIT) $(CFLAGS_I) -DSIM_COMPILER="$(COMPILER_NAME)" -g -I .. $(OS_CCDEFS) $(ROMS_OPT) +LDFLAGS := $(OS_LDFLAGS) $(NETWORK_LDFLAGS) $(LDFLAGS_O) + +# +# Common Libraries +# +BIN = ./ +SIM = ../scp.c ../sim_console.c ../sim_fio.c ../sim_timer.c ../sim_sock.c \ + ../sim_tmxr.c ../sim_ether.c ../sim_tape.c ../sim_disk.c ../sim_serial.c \ + ../sim_video.c ../sim_imd.c ../sim_card.c + +DISPLAYD = display + +# +# Emulator source files and compile time options +# +ICL1900D = ./ +ICL1900 = ${ICL1900D}icl1900_cpu.c ${ICL1900D}icl1900_sys.c +ICL1900_OPT = -I.. -DUSE_SIM_CARD + +# +# Build everything +# +all : ${BIN}icl1900${EXE} + +clean : +ifeq ($(WIN32),) + ${RM} ${ALL} +else + if exist BIN\*.exe del /q BIN\*.exe +endif +# +# Individual builds +# +${BIN}icl1900${EXE} : ${ICL1900} ${SIM} + ${CC} ${ICL1900} ${SIM} ${ICL1900_OPT} -o $@ ${LDFLAGS} + + +# Front Panel API Demo/Test program + +frontpaneltest : ${BIN}frontpaneltest${EXE} + +${BIN}frontpaneltest${EXE} : frontpanel/FrontPanelTest.c sim_sock.c sim_frontpanel.c + ${MKDIRBIN} + ${CC} frontpanel/FrontPanelTest.c sim_sock.c sim_frontpanel.c $(CC_OUTSPEC) ${LDFLAGS} + + + diff --git a/ICL1900/icl1900_cpu.c b/ICL1900/icl1900_cpu.c new file mode 100644 index 0000000..8acaf64 --- /dev/null +++ b/ICL1900/icl1900_cpu.c @@ -0,0 +1,2001 @@ +/* icl1900_cpu.c: ICL 1900 cpu simulator + + Copyright (c) 2017, Richard Cornwell + + 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 + RICHARD CORNWELL 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. + + The ICL1900 was a 24 bit CPU that supported either 32Kwords of memory or + 4Mwords of memory, depending on model. + + Level A: lacked 066, 116 and 117 instructions and 22 bit addressing. + Level B: Adds 066, 116 and 117 instructions, but lack 22 bit addressing. + Level C: All primary and 22 bit addressing. + + Sub-level 1: Norm 114,115 available only if FP option. + Sub-level 2: Norm 114,115 always available. +*/ + +#include "icl1900_defs.h" +#include "sim_timer.h" + +#define UNIT_V_MSIZE (UNIT_V_UF + 0) +#define UNIT_MSIZE (7 << UNIT_V_MSIZE) +#define MEMAMOUNT(x) (x << UNIT_V_MSIZE) +#define UNIT_V_MODEL (UNIT_V_MSIZE + 4) +#define UNIT_MODEL (0x1f << UNIT_V_MODEL) +#define MODEL(x) (UNIT_MODEL & (x << UNIT_V_MODEL)) + + +#define TMR_RTC 1 + +#define HIST_PC BM1 +#define HIST_MAX 50000 +#define HIST_MIN 64 + +/* Level A Primary no 066, 116, 117 15AM and DBM only */ +/* Level B All Primary 15AM and DBM only */ +/* Level C All Primary 15AM and 22AM, DBM and EBM */ + +/* Level x1, NORM when FP */ +/* Level x2, NORM always */ + +#define MOD1 0 /* Ax OPT */ +#define MOD1A 1 /* A1 OPT 04x -076 111-3 */ +#define MOD1S 2 /* Ax OPT 04x -076 111-3 */ +#define MOD1T 3 /* Ax OPT 04x -076 111-3 */ +#define MOD2 4 /* Ax OPT 04x -076 111-3 */ +#define MOD2A 5 /* B1 OPT */ +#define MOD2S 6 /* B1 or C1 OPT 04x -076 111-3 */ +#define MOD2T 7 /* B1 or C1 OPT 04x -076 111-3 */ +#define MOD3 8 /* A1 or A2 OPT 04x -076 111-3 */ +#define MOD3A 9 /* B1 or C1 OPT 04x -076 111-3 */ +#define MOD3S 10 /* B1 or C1 OPT 04x -076 111-3 */ +#define MOD3T 11 /* A1 or A2 OPT */ +#define MOD4 12 /* A2 OPT */ +#define MOD4A 13 /* C2 OPT */ +#define MOD4E 14 /* C2 OPT */ +#define MOD4F 12+32 +#define MOD4S 15 /* Ax OPT */ +#define MOD5 16 /* A2 FP */ +#define MOD5A 17 /* Ax FP */ +#define MOD5E 18 /* C2 FP */ +#define MOD5F 16+32 +#define MOD5S 19 /* Ax FP */ +#define MOD6 20 /* C2 OPT */ +#define MOD6A 21 /* Ax OPT 076 131 */ +#define MOD6E 22 /* Ax OPT 076 */ +#define MOD6F 20+32 +#define MOD6S 23 /* Ax OPT */ +#define MOD7 24 /* C2 FP */ +#define MOD7A 25 /* Ax FP */ +#define MOD7E 26 /* Ax FP */ +#define MOD7F 24+32 +#define MOD7S 27 /* Ax FP */ +#define MOD8 28 /* Ax FP */ +#define MOD8A 29 /* Ax FP */ +#define MOD8S 30 /* Ax FP */ +#define MOD9 31 /* A2 FP */ +#define MODXF 32 /* C2 FP */ + + + +int cpu_index; /* Current running cpu */ +uint32 M[MAXMEMSIZE] = { 0 }; /* memory */ +uint32 RA; /* Temp register */ +uint32 RB; /* Temp register */ +uint32 RC; /* Instruction Code */ +uint32 RD; /* Datum pointer */ +uint16 RK; /* Counter */ +uint8 RF; /* Function code */ +uint32 RL; /* Limit register */ +uint8 RG; /* General register */ +uint32 RM; /* M field register */ +uint32 RN; /* Current address */ +uint32 RP; /* Temp register */ +uint32 RS; /* Temp register */ +uint32 RT; /* Temp register */ +uint32 MB; /* Memory buffer */ +uint32 MA; /* Memory address */ +uint8 RX; /* X field register */ +uint32 XR[8]; /* Index registers */ +uint32 faccl; /* Floating point accumulator low */ +uint32 facch; /* Floating point accumulator high */ +uint8 fovr; /* Floating point overflow */ +uint8 BCarry; /* Carry bit */ +uint8 BV; /* Overflow flag */ +uint8 Mode; /* Mode */ +uint8 exe_mode = 1; /* Executive mode */ +#define EJM 040 /* Extended jump Mode */ +#define DATUM 020 /* Datum mode */ +#define AM22 010 /* 22 bit addressing */ +#define EXTRC 004 /* Executive trace mode */ +/* 002 */ /* unused mode bit */ +#define ZERSUP 001 /* Zero suppression */ +uint8 OIP; /* Obey instruction */ +uint8 PIP; /* Pre Modify instruction */ +uint8 OPIP; /* Saved Pre Modify instruction */ +uint32 SR1; /* Mill timer */ +uint32 SR2; /* Typewriter I/P */ +uint32 SR3; /* Typewriter O/P */ +uint32 SR64; /* Interrupt status */ +uint32 SR65; /* Interrupt status */ +uint32 adrmask; /* Mask for addressing memory */ + + +struct InstHistory +{ + uint32 rc; + uint32 op; + uint32 ea; + uint32 xr; + uint32 ra; + uint32 rb; + uint32 rr; + uint8 c; + uint8 v; + uint8 e; +}; + +struct InstHistory *hst = NULL; +int32 hst_p = 0; +int32 hst_lnt = 0; + + +t_stat cpu_ex(t_value * vptr, t_addr addr, UNIT * uptr, + int32 sw); +t_stat cpu_dep(t_value val, t_addr addr, UNIT * uptr, + int32 sw); +t_stat cpu_reset(DEVICE * dptr); +t_stat cpu_set_size(UNIT * uptr, int32 val, CONST char *cptr, + void *desc); +t_stat cpu_show_size(FILE * st, UNIT * uptr, int32 val, + CONST void *desc); +t_stat cpu_show_hist(FILE * st, UNIT * uptr, int32 val, + CONST void *desc); +t_stat cpu_set_hist(UNIT * uptr, int32 val, CONST char *cptr, + void *desc); +t_stat cpu_help(FILE *, DEVICE *, UNIT *, int32, const char *); +/* Interval timer */ +t_stat rtc_srv(UNIT * uptr); + +int32 rtc_tps = 60 ; + + +/* CPU data structures + + cpu_dev CPU device descriptor + cpu_unit CPU unit descriptor + cpu_reg CPU register list + cpu_mod CPU modifiers list +*/ + +UNIT cpu_unit[] = + {{ UDATA(rtc_srv, MEMAMOUNT(7)|UNIT_IDLE, MAXMEMSIZE ), 16667 }}; + +REG cpu_reg[] = { + {ORDATAD(C, RC, 22, "Instruction code"), REG_FIT}, + {ORDATAD(F, RF, 7, "Order Code"), REG_FIT}, + {BRDATAD(X, XR, 8, 24, 8, "Index Register"), REG_FIT}, + {NULL} +}; + +MTAB cpu_mod[] = { + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(0), NULL, "4K", &cpu_set_size}, + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(1), NULL, "8K", &cpu_set_size}, + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(3), NULL, "16K", &cpu_set_size}, + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(7), NULL, "32K", &cpu_set_size}, + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(8), NULL, "48K", &cpu_set_size}, + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(9), NULL, "64K", &cpu_set_size}, + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(10), NULL, "96K", &cpu_set_size}, + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(11), NULL, "128K", &cpu_set_size}, + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(12), NULL, "256K", &cpu_set_size}, + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(13), NULL, "512K", &cpu_set_size}, + {UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(14), NULL, "1024K", &cpu_set_size}, + /* Stevenage */ + {UNIT_MODEL, MODEL(MOD1), "1901", "1901", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD1A), "1901A", "1901A", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD1S), "1901S", "1901S", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD1T), "1901T", "1901T", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD2), "1902", "1902", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD2A), "1902A", "1902A", NULL, NULL, NULL}, /* C1 */ + {UNIT_MODEL, MODEL(MOD2S), "1902S", "1902S", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD2T), "1902T", "1902T", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD3), "1903", "1903", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD3A), "1903A", "1903A", NULL, NULL, NULL}, /* C1 */ + {UNIT_MODEL, MODEL(MOD3S), "1903S", "1903S", NULL, NULL, NULL}, + /* West Gorton */ + {UNIT_MODEL, MODEL(MOD3T), "1903T", "1903T", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD4), "1904", "1904", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD4A), "1904A", "1904A", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD4E), "1904E", "1904E", NULL, NULL, NULL}, /* C */ + {UNIT_MODEL, MODEL(MOD4F), "1904F", "1904F", NULL, NULL, NULL}, /* C */ + {UNIT_MODEL, MODEL(MOD4S), "1904S", "1904S", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD5), "1905", "1905", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD5E), "1905E", "1905E", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD5F), "1905F", "1905F", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD5S), "1905S", "1905S", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD6), "1906", "1906", NULL, NULL, NULL}, /* C */ + {UNIT_MODEL, MODEL(MOD6A), "1906A", "1906A", NULL, NULL, NULL}, /* C */ + {UNIT_MODEL, MODEL(MOD6E), "1906E", "1906E", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD6F), "1906F", "1906F", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD7), "1907", "1907", NULL, NULL, NULL}, /* C */ + {UNIT_MODEL, MODEL(MOD7E), "1907E", "1907E", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD7F), "1907F", "1907F", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD8A), "1908A", "1908A", NULL, NULL, NULL}, + {UNIT_MODEL, MODEL(MOD9), "1909", "1909", NULL, NULL, NULL}, + {MTAB_VDV, 0, "MEMORY", NULL, NULL, &cpu_show_size}, + {MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle }, + {MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL }, + {MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist}, + {0} +}; + +DEVICE cpu_dev = { + "CPU", cpu_unit, cpu_reg, cpu_mod, + 1, 8, 22, 1, 8, 24, + &cpu_ex, &cpu_dep, &cpu_reset, NULL, NULL, NULL, + NULL, DEV_DEBUG, 0, dev_debug, + NULL, NULL, &cpu_help +}; + + + + +uint8 Mem_read(uint32 addr, uint32 *data, uint8 flag) { + addr &= M22; + if (addr < 8) { + *data = XR[addr]; + return 0; + } + if (!exe_mode || (flag && (Mode & DATUM) != 0)) { + addr = (addr + RD) ;//& adrmask; +fprintf(stderr, "access:: %08o %08o\n\r", addr, RL); + } + if (!exe_mode && RL && (addr < RD || addr >= RL)) { + SR64 |= B1; +fprintf(stderr, "rev: %08o\n\r", addr); + return 1; + } + addr &= adrmask; + if (addr > MEMSIZE) { + SR64 |= B1; +fprintf(stderr, "mem: %08o\n\r", addr); + return 1; + } + *data = M[addr]; + return 0; +} + +uint8 Mem_write(uint32 addr, uint32 *data, uint8 flag) { + addr &= M22; + if (addr < 8) { + XR[addr] = *data; + return 0; + } + if (!exe_mode || (flag && (Mode & DATUM) != 0)) + addr = (addr + RD) ; //& adrmask; + if (!exe_mode && RL && (addr < RD || addr >= RL)) { + SR64 |= B1; +fprintf(stderr, "wrev: %08o\n\r", addr); + return 1; + } + addr &= adrmask; + if (addr > MEMSIZE) { + SR64 |= B1; +fprintf(stderr, "mem: %08o\n\r", addr); + return 1; + } + M[addr] = *data; + return 0; +} + +t_stat +sim_instr(void) +{ + t_stat reason; + uint32 temp; + uint32 t; + int x_reg; + int m; + int n; + int e1,e2; /* Temp for exponents */ + + reason = 0; + adrmask = (Mode & AM22) ? M22 : M15; + + while (reason == 0) { /* loop until halted */ + if (sim_interval <= 0) { /* event queue? */ + reason = sim_process_event(); + if (reason != SCPE_OK) { + break; /* process */ + } + } + + if (sim_brk_summ) { + if(sim_brk_test(RC, SWMASK('E'))) { + reason = SCPE_STOP; + break; + } + } + +intr: + if (!exe_mode && (SR64 | SR65) != 0) { + exe_mode = 1; + /* Store registers */ + Mem_write(RD+13, &facch, 0); /* Save F.P.U. */ + Mem_write(RD+12, &faccl, 0); + RA = 0; /* Build ZSTAT */ + if (Mode & 1) + RA |= B3; + if (OPIP | PIP) + RA |= B2; + Mem_write(RD+9, &RA, 0); + RA = RC; + if (BV) + RA |= B0; + if (BCarry) + RA |= B1; +#if 0 + if ((Mode & AM22) == 0 && (Mode & 1)) + RA |= B8; +#endif + Mem_write(RD+8, &RA, 0); + for (n = 0; n < 8; n++) + Mem_write(RD+n, &XR[n], 0); + Mode = 0; + adrmask = (Mode & AM22) ? M22 : M15; + RC = 020; + PIP = 0; + } + +fetch: + if (Mem_read(RC, &temp, 0)) { + if (hst_lnt) { /* history enabled? */ + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) + hst_p = 0; + hst[hst_p].rc = RC | HIST_PC; + hst[hst_p].ea = RC; + hst[hst_p].op = 0; + hst[hst_p].xr = 0; + hst[hst_p].ra = 0; + hst[hst_p].rb = 0; + hst[hst_p].rr = 0; + hst[hst_p].c = BCarry; + hst[hst_p].v = BV; + hst[hst_p].e = exe_mode; + } + RC = (RC + 1) & adrmask; + goto intr; + } + +obey: + RM = temp & 037777; + RF = 0177 & (temp >> 14); + RX = 07 & (temp >> 21); + /* Check if branch opcode */ + if (RF >= 050 && RF < 0100) { + RA = XR[RX]; + RM = RB = temp & 077777; + if ((Mode & EJM) && (RF & 1) == 0) { + RB |= (RB & 020000) ? 017740000 : 0; /* Sign extend RB */ +fprintf(stderr, "Rel B: %08o PC=%08o -> ", RB, RC); + RB = (RB + RC) & adrmask; +fprintf(stderr, " %08o\n\r", RC); + } + if (PIP && ((Mode & EJM) == 0 || (RF & 1) == 0)) { + RB = (RB + RP) & adrmask; + } + } else { + RA = XR[RX]; + m = 03 & (RM >> 12); + RB = RM & 07777; + if (PIP) + RB = (RB + RP) & adrmask; + if (m != 0) + RB = (RB + XR[m]) & adrmask; + RS = RB; + if (RF < 050) { + if (Mem_read(RS, &RB, 1)) { + if (hst_lnt) { /* history enabled? */ + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) + hst_p = 0; + hst[hst_p].rc = (RC - 1) | HIST_PC; + hst[hst_p].ea = RS; + hst[hst_p].op = temp; + hst[hst_p].xr = XR[RX]; + hst[hst_p].ra = RA; + hst[hst_p].rb = RB; + hst[hst_p].rr = RB; + hst[hst_p].c = BCarry; + hst[hst_p].v = BV; + hst[hst_p].e = exe_mode; + } + RC = (RC + 1) & adrmask; + goto intr; + } + if (RF & 010) { + t = RA; + RA = RB; + RB = t; + } + } + } + OPIP = PIP; + PIP = 0; + + if (hst_lnt) { /* history enabled? */ + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) + hst_p = 0; + hst[hst_p].rc = RC | HIST_PC; + hst[hst_p].ea = RS; + hst[hst_p].op = temp; + hst[hst_p].xr = XR[RX]; + hst[hst_p].ra = RA; + hst[hst_p].rb = RB; + hst[hst_p].rr = RB; + hst[hst_p].c = BCarry; + hst[hst_p].v = BV; + hst[hst_p].e = exe_mode; + } + + /* Advance to next location */ + if (RF != 023) + RC = (RC + 1) & adrmask; + OIP = 0; + + switch (RF) { + case OP_LDX: /* Load to X */ + case OP_LDXC: /* Load into X with carry */ + case OP_LDN: /* Load direct to X */ + case OP_LDNC: /* Load direct into X with carry */ + case OP_STO: /* Store contents of X */ + case OP_STOC: /* Store contents of X with carry */ + case OP_NGS: /* Negative into Store */ + case OP_NGSC: /* Negative into Store with carry */ + case OP_NGN: /* Negative direct to X */ + case OP_NGNC: /* Negative direct to X with carry */ + case OP_NGX: /* Negative to X */ + case OP_NGXC: /* Negative to X with carry */ + RA = 0; + /* Fall through */ + + case OP_SBX: /* Subtract from X */ + case OP_SBXC: /* Subtract from X with carry */ + case OP_SBS: /* Subtract from store */ + case OP_SBSC: /* Subtract from store with carry */ + case OP_SBN: /* Subtract direct from X */ + case OP_SBNC: /* Subtract direct from X with carry */ + case OP_ADX: /* Add to X */ + case OP_ADXC: /* Add to X with carry */ + case OP_ADN: /* Add direct to X */ + case OP_ADNC: /* Add direct to X with carry */ + case OP_ADS: /* Add X to store */ + case OP_ADSC: /* Add X to store with carry */ + if (RF & 02) { + RB = RB ^ FMASK; + BCarry = !BCarry; + } + t = (RA & B0) != 0; + RA = RA + RB + BCarry; + if (RF & 04) { + if (RF & 02) + BCarry = (RA & BM1) == 0; + else + BCarry = (RA & B0) != 0; + RA &= M23; + } else { + int t2 = (RB & B0) != 0; + int tr = (RA & B0) != 0; + if ((t && t2 && !tr) || (!t && !t2 && tr)) + BV = 1; + BCarry = 0; + } + RA &= FMASK; + if (RF & 010) { + if (Mem_write(RS, &RA, 1)) { + goto intr; + } + } else { + XR[RX] = RA; + } + break; + + case OP_ANDX: /* Logical AND into X */ + case OP_ANDS: /* Logical AND into store */ + case OP_ANDN: /* Logical AND direct into X */ + RA = RA & RB; + BCarry = 0; + if (RF & 010) { + if (Mem_write(RS, &RA, 1)) { + goto intr; + } + } else { + XR[RX] = RA; + } + break; + + case OP_ORX: /* Logical OR into X */ + case OP_ORS: /* Logical OR into store */ + case OP_ORN: /* Logical OR direct into X */ + RA = RA | RB; + BCarry = 0; + if (RF & 010) { + if (Mem_write(RS, &RA, 1)) { + goto intr; + } + } else { + XR[RX] = RA; + } + break; + + case OP_ERX: /* Logical XOR into X */ + case OP_ERS: /* Logical XOR into store */ + case OP_ERN: /* Logical XOR direct into X */ + RA = RA ^ RB; + BCarry = 0; + if (RF & 010) { + if (Mem_write(RS, &RA, 1)) { + goto intr; + } + } else { + XR[RX] = RA; + } + break; + + case OP_OBEY: /* Obey instruction at N */ + temp = RB; + OIP = 1; + goto obey; + + case OP_LDCH: /* Load Character to X */ + m = (m == 0) ? 3 : (XR[m] >> 22) & 3; + RA = RB >> (6 * (3 - m)); + RA = XR[RX] = RA & 077; + BCarry = 0; + break; + + case OP_LDEX: /* Load Exponent */ + RA = XR[RX] = RB & M9; + BCarry = 0; + break; + + case OP_TXU: /* Test X unequal */ + if (RA != RB) + BCarry = 1; + break; + + case OP_TXL: /* Test X Less */ + RB += BCarry; + if (RB != RA) + BCarry = (RB > RA); + break; + + case OP_STOZ: /* Store Zero */ + RA = 0; + BCarry = 0; + if (Mem_write(RS, &RA, 1)) { + goto intr; + } + break; + + case OP_DCH: /* Deposit Character to X */ + m = (m == 0) ? 3 : (XR[m] >> 22) & 3; + m = 6 * (3 - m); + RB = (RB & 077) << m; + RA &= ~(077 << m); + RA |= RB; + BCarry = 0; + if (Mem_write(RS, &RA, 1)) { + goto intr; + } + break; + + case OP_DEX: /* Deposit Exponent */ + RA &= ~M9; + RA = RA | (RB & M9); + BCarry = 0; + if (Mem_write(RS, &RA, 1)) { + goto intr; + } + break; + + case OP_DSA: /* Deposit Short Address */ + RA &= ~M12; + RA |= (RB & M12); + BCarry = 0; + if (Mem_write(RS, &RA, 1)) { + goto intr; + } + break; + + case OP_DLA: /* Deposit Long Address */ + RA &= ~M15; + RA |= (RB & M15); + BCarry = 0; + if (Mem_write(RS, &RA, 1)) { + goto intr; + } + break; + + case OP_MPY: /* Multiply */ + case OP_MPR: /* Multiply and Round */ + case OP_MPA: /* Multiply and Accumulate */ + if (RA == B0 && RB == B0) { + if (RF != OP_MPA || (XR[(RX + 1) & 7] & B0) == 0) + BV = 1; + } + RP = RA; + RA = RB; + t = RP & 1; + RP >>= 1; + if (RF & 1) /* Multiply and Round */ + RP |= B0; + RB = 0; + for(RK = 23; RK != 0; RK--) { + if (t) + RB += RA; + t = RP & 1; + RP >>= 1; + if (RB & 1) + RP |= B0; + if (RB & B0) + RB |= BM1; + RB >>= 1; + } + + if (t) { + RB += (RA ^ FMASK) + 1; + } + t = RP & 1; /* Check for MPR */ + if (t && RP & B0) + RB++; + RP >>= 1; + if (RF == OP_MPA) { + RA = XR[(RX + 1) & 7]; + RP += RA; + if (RA & B0) + RB--; + else if (RP & B0) + RB++; + } + + XR[RX] = RB & FMASK; + RA = XR[(RX+1) & 7] = RP & M23; + BCarry = 0; + break; + + case OP_CDB: /* Convert Decimal to Binary */ + m = (m == 0) ? 3 : (XR[m] >> 22) & 3; + RB = (RB >> (6 * (3 - m))) & 077; + if (RB > 9) { + BCarry = 1; + break; + } + /* Fall through */ + + case OP_CBD: /* Convert Binary to Decimal */ + RT = RB; + RB = XR[(RX+1) & 7]; + /* Multiply by 10 */ + RB <<= 2; + RA <<= 2; + RA |= (RB >> 23) & 07; + RB &= M23; + RB += XR[(RX+1) & 7]; + if (RB & B0) + RA++; + RA += XR[RX]; + RB <<= 1; + RA <<= 1; + if (RB & B0) + RA++; + RB &= M23; + if (RF == OP_CDB) { + /* Add in RT */ + RB += RT; + if (RB & B0) + RA++; + RB &= M23; + if (RA & ~(M23)) + BV = 1; + RA &= M23; + } else { + /* Save bits over 23 to char */ + m = (m == 0) ? 3 : (XR[m] >> 22) & 3; + m = 6 * (3 - m); + RP = (RA >> 23) & 017; + if ((Mode & 1) != 0 && RP == 0) + RP = 020; + else + Mode &= ~1; + RA &= M23; + RT &= ~(077 << m); + RT |= (RP << m); + if (Mem_write(RS, &RT, 1)) { + goto intr; + } + } + XR[(RX+1) & 7] = RB; + XR[RX] = RA; + break; + + case OP_DVD: /* Unrounded Double Length Divide */ + case OP_DVR: /* Rounded Double Length Divide */ + case OP_DVS: /* Single Length Divide */ + /* Load X and X* */ + RP = RA; + RA = RB; + RB = RP; + RB = XR[RX]; + RP = XR[(RX+1) & 07]; + if (RF == OP_DVS) /* Make double length */ + RB = (RP & B0) ? FMASK : 0; + RP &= M23; +fprintf(stderr, "DVD: %08o %08o %08o - %3o C=%08o\n\r", RA, RP, RB, RF, RC); + /* Save Divisor */ + RS = RA; + /* Get Absolute of divisor */ + if ((RA & B0) == 0) { + if (RA == 0) { /* Zero divisor */ + BV = 1; + BCarry = 0; + break; + } + RA = (RA ^ FMASK) + 1; /* Form -DIVISOR */ + } +fprintf(stderr, "DVD1: %08o %08o %08o \n\r", RA, RP, RB); + /* Set flag based on sign */ + BCarry = (RB & B0) != 0; + RT = (RA ^ FMASK) + 1; /* Form +DIVISOR */ + + /* Main loop */ + for(RK = 24; RK != 0; RK--) { + RB = RB + ((BCarry)? RA: RT); /* Add/Sub divisor as previous sign */ + RP <<= 1; + if (RB & BM1) { + BCarry = !BCarry; + RP |= 1; + } + RB <<= 1; + if (RP & B0) + RB |= 1; + RB &= FMASK; + RP &= FMASK; +fprintf(stderr, "DVD2: %08o %08o %08o \n\r", RA, RP, RB); + } + /* 24th iteration */ + RB = RB + ((BCarry)? RT: RA); /* Add/Sub divisor as previous sign */ + RP <<= 1; + if (RB & BM1) { + BCarry = !BCarry; + RP |= 1; + } + RT = B0 + ((RP & B0) != 0); + RB = RB + ((BCarry)? RT: RA); /* Add/Sub divisor as previous sign */ +fprintf(stderr, "DVD3: %08o %08o %08o \n\r", RA, RP, RB); + + BCarry = (RP ^ B0) != 0; + if ((RS & B0) == 0) { + RP ^= FMASK; + RB = RB + RS; + } else if (RS != RB) { +rnd: + RB = RB - RS; + BV = 0; + RP = RP + 1; + if (RP & BM1) { + BV = 1; + BCarry = !BCarry; + } + goto edex; + } +fprintf(stderr, "DVD4: %08o %08o %08o \n\r", RA, RP, RB); + + if ((RF & 1) == 1 && RB != 0) { + temp = RB; + temp += (RS ^ FMASK) + 1; + temp += RB; + temp ^= temp; + if ((temp & B0) == 0) + goto rnd; + } + +edex: +fprintf(stderr, "DVD5: %08o %08o %08o \n\r", RA, RP, RB); + if (BCarry) + BV = 0; +#if 0 + RP = XR[(RX+1) & 7]; /* VR */ + RA = RB; /* Divisor to RA */ + RB = XR[RX]; /* Dividend to RB/RP */ +fprintf(stderr, "DVD: %08o %08o %08o - %3o C=%08o\n\r", RA, RP, RB, RF, RC); +if (RA == FMASK && RP == 1 && RB == 0) { + XR[RX] = 0; + XR[(RX+1) & 7] = FMASK; + break; +} + + if (RA == 0) { /* Exit on zero divisor */ /* VI */ + BV = 1; + BCarry = 0; + break; + } + BCarry = (RP & B0) != 0; + temp = (RP | RB) == 0; /* Save zero dividend */ + + /* Setup for specific divide order code */ /* V11 */ + if (RF & 2) { /* DVS */ + if (BCarry) { + RB = FMASK; + } else { + RB = 0; + } + } + RP <<= 1; + RP &= FMASK; + BCarry = 0; +fprintf(stderr, "DVD1: %08o %08o %08o \n\r", RA, RP, RB); + + /* First partial remainder */ /* V12 */ + if (((RB ^ RA) & B0) == 0) { + t = RB + (RA ^ FMASK) + 1; + RK=1; + } else { + t = RB + RA; + RK=0; + } + if (((t ^ RA) & B0) != 0) + BCarry = 1; + BCarry = RK != BCarry; + RP <<= 1; + if (((t ^ RA) & B0) == 0) { + RP |= 1; + } + RB = t << 1; + if (RP & BM1) + RB |= 1; + RB &= FMASK; + RP &= FMASK; +fprintf(stderr, "DVD2: %08o %08o %08o \n\r", RA, RP, RB); + + /* Main divide loop */ /* V13 */ + for (RK = 22; RK != 0; RK--) { + if (((t ^ RA) & B0) == 0) { + t = RB + (RA ^ FMASK) + 1; + } else { + t = RB + RA; + } + RP <<= 1; + if (((t ^ RA) & B0) == 0) { + RP |= 1; + } + RB = t << 1; + if (RP & BM1) + RB |= 1; + RB &= FMASK; + RP &= FMASK; +fprintf(stderr, "DVD3: %08o %08o %08o \n\r", RA, RP, RB); + } + + /* Final product */ + if (((t ^ RA) & B0) == 0) { /* V14 */ + t = RB + (RA ^ FMASK) + 1; + } else { + t = RB + RA; + } + RP <<= 1; + if (((t ^ RA) & B0) == 0) { + RP |= 1; + } + RP &= FMASK; +fprintf(stderr, "DVD4: %08o %08o %08o \n\r", RA, RP, RB); + + /* Final Remainder */ + if (RP & 1) { + RB = (RB + (RA ^ FMASK) + 1) & FMASK; + } else { + RB = (RB + RA) & FMASK; + } + /* End correction */ + if ((RP & 1) == 0) { + RB = (RB + RA) & FMASK; + } +fprintf(stderr, "DVD5: %08o %08o %08o \n\r", RA, RP, RB); + /* Form final partial product */ + if (RA & B0) { + t = (RB + (RA ^ FMASK) + 1) & FMASK; +fprintf(stderr, "DVD5: %08o %08o %08o %08o\n\r", RA, RP, RB, RT); + if (t == 0) { + RB = 0; + goto dvd1; + } + } + if ((RF & 1) == 0) /* DVR */ + goto dvd2; + if (RB == 0) + goto dvd2; + RT = RB + (RA ^ FMASK) + 1; +fprintf(stderr, "DVDA: %08o %08o %08o %08o \n\r", RA, RP, RB, RT); + RA = RB; + if ((((RT + RA) ^ RA) & B0) != 0) + goto dvd2; + RB = RT & FMASK; +dvd1: +fprintf(stderr, "DVD6: %08o %08o %08o \n\r", RA, RP, RB); + RT = RP; + RP++; + if ((RT ^ RP) & B0) + BCarry = !BCarry; + if (RP & BM1) + BCarry = 1; +dvd2: +fprintf(stderr, "DVD7: %08o %08o %08o \n\r", RA, RP, RB); + if (temp) + BCarry = 0; + if (BCarry) + BV = 1; +#endif + BCarry = 0; + XR[RX] = RB & FMASK; + XR[(RX+1) & 7] = RP & FMASK; + break; + case OP_BZE: /* Branch if X is Zero */ + case OP_BZE1: + BCarry = 0; + if (RA == 0) + goto branch; + break; + + case OP_BNZ: /* Branch if X is not Zero */ + case OP_BNZ1: + BCarry = 0; + if (RA != 0) + goto branch; + break; + + case OP_BPZ: /* Branch if X is Positive or zero */ + case OP_BPZ1: + BCarry = 0; + if ((RA & B0) == 0) + goto branch; + break; + + case OP_BNG: /* Branch if X is Negative */ + case OP_BNG1: + BCarry = 0; + if ((RA & B0) != 0) + goto branch; + break; + + case OP_BUX: /* Branch on Unit indexing */ + case OP_BUX1: + BCarry = 0; + if (Mode & AM22) { + RA = ((RA+1) & M22) | (RA & CMASK); + XR[RX] = RA; + goto branch; + } else { + RS = CNTMSK + RA; /* Actualy a subtract 1 */ + RS &= CNTMSK; + RA = ((RA + 1) & M15) | RS; + } + XR[RX] = RA; + if (RS != 0) + goto branch; + break; + + case OP_BDX: /* Branch on Double Indexing */ + case OP_BDX1: + BCarry = 0; + if (Mode & AM22) { + RA = ((RA+2) & M22) | (RA & CMASK); + XR[RX] = RA; + goto branch; + } else { + RS = CNTMSK + RA; /* Actualy a subtract 1 */ + RS &= CNTMSK; + RA = ((RA + 2) & M15) | RS; + } + XR[RX] = RA; + if (RS != 0) + goto branch; + break; + + case OP_BCHX: /* Branch on Character Indexing */ + case OP_BCHX1: + BCarry = 0; + RA += 020000000; + n = (RA & BM1) != 0; + if (Mode & AM22) { + RA = ((RA + n) & M22) | (RA & CMASK); + XR[RX] = RA; + goto branch; + } else { + RS = CHCMSK + RA; /* Actually a subtract 1 */ + RS &= CHCMSK; + RA = ((RA + n) & M15) | RS | (RA & CMASK); + } + XR[RX] = RA; + if (RS != 0) + goto branch; + break; + + /* Not on A */ + case OP_BCT: /* Branch on Count - BC */ + case OP_BCT1: + BCarry = 0; + if (Mode & AM22) { + RA = ((RA-1) & M22) | (RA & CMASK); + RS = RA & M22; + } else { + RA = ((RA - 1) & M15) | (CNTMSK & RA); + RS = RA & M15; + } + XR[RX] = RA; + if (RS != 0) + goto branch; + break; + + case OP_CALL: /* Call Subroutine */ + case OP_CALL1: + RA = RC; + if (BV) + RA |= B0; + if ((Mode & (AM22|EJM)) == 0) { + if (Mode & 1) + RA |= B8; + } else { + if (Mode & 1) + RA |= B1; + } + BV = 0; + BCarry = 0; + XR[RX] = RA; +branch: + if ((Mode & EJM) != 0) { + if ((RF & 1) != 0) { + RB &= 037777; +fprintf(stderr, "Rep: %08o ->", RB); + if (Mem_read(RB, &RB, 0)) { + goto intr; + } +fprintf(stderr, " %08o \n\r", RB); + RB &= adrmask; + if (OPIP) + RB = (RB + RP) & adrmask; + } + } + if (hst_lnt) { /* history enabled? */ + hst[hst_p].ea = RB; + } + if (Mem_read(RB, &temp, 0)) { + goto intr; + } + /* Monitor mode 2 -> Exec Mon */ + /* Read address to store from location 262. */ + /* Store address transfer address at location, increment 262 mod 128 */ + RC = RB; + /* Monitor mode 3 -> int */ + goto obey; + + case OP_EXIT: /* Exit Subroutine */ + case OP_EXIT1: + if (RA & B0) + BV = 1; + Mode &= ~1; + if ((Mode & (AM22|EJM)) == 0) { + if (RA & B8) + Mode |= 1; + } else { + if (RA & B1) + Mode |= 1; + } + BCarry = 0; + RM |= (RM & 020000) ? 017740000 : 0; /* Sign extend RM */ + RA = RA + RM; + if (PIP) + RA += RP; + if (Mem_read(RA, &temp, 0)) { + goto intr; + } + RC = RA & adrmask; + goto obey; + + case OP_BRN: /* Branch unconditional */ + case OP_BRN1: + /* If priorit mode -> 164 */ + switch(RX) { + case 0: /* BRN */ + goto branch; + + case 1: /* BVS */ + if (BV) + goto branch; + break; + + case 2: /* BVSR */ + n = BV; + BV = 0; + if (n) + goto branch; + break; + + case 3: /* BVC */ + if (BV == 0) + goto branch; + break; + + case 4: /* BVCR */ + if (BV == 0) + goto branch; + BV = 0; + break; + + case 5: /* BCS */ + n = BCarry; + BCarry = 0; + if (n) + goto branch; + break; + + case 6: /* BCC */ + n = BCarry; + BCarry = 0; + if (!n) + goto branch; + break; + + case 7: /* BVC */ + n = BV; + BV = !BV; + if (n == 0) + goto branch; + break; + } + break; + + /* B with Floating or C */ + case OP_BFP: /* Branch state of floating point accumulator */ + case OP_BFP1: + switch (RX & 06) { + case 0: n = (faccl | facch) != 0; break; + case 2: n = (faccl & B0) != 0; break; + case 4: n = fovr; break; + case 6: SR64 |= B1; goto intr; + } + if (n == (RX & 1)) + goto branch; + break; + + case OP_SLL: /* Shift Left */ + m = (RB >> 10) & 03; + RK = RB & 01777; + BCarry = 0; + while (RK != 0) { + t = 0; + switch (m) { + case 0: t = (RA & B0) != 0; break; + case 1: break; + case 2: + case 3: temp = RA & B0; + } + RA <<= 1; + RA |= t; + if ((m & 2) && temp != (RA & B0)) + BV = 1; + RA &= FMASK; + RK--; + } + XR[RX] = RA; + break; + + case OP_SLD: /* Shift Left Double */ + m = (RB >> 10) & 03; + RK = RB & 01777; + BCarry = 0; + RB = XR[(RX+1) & 07]; + while (RK != 0) { + switch (m) { + case 0: + RB <<= 1; + RA <<= 1; + if (RA & BM1) + RB |= 1; + if (RB & BM1) + RA |= 1; + break; + case 1: + RB <<= 1; + RA <<= 1; + if (RB & BM1) + RA |= 1; + break; + case 2: + case 3: + RB <<= 1; + RA <<= 1; + if (RB & B0) + RA |= 1; + RB &= M23; + t = (RA & B0) != 0; + temp = (RA & BM1) != 0; + if (t != temp) + BV = 1; + } + RA &= FMASK; + RB &= FMASK; + RK--; + } + XR[RX] = RA; + XR[(RX+1) & 07] = RB; + break; + + case OP_SRL: /* Shift Right */ + m = (RB >> 10) & 03; + RK = RB & 01777; + t = RA & B0; + BCarry = 0; + switch(m) { + case 0: break; + case 1: t = 0; break; + case 2: break; + case 3: if (BV) { + t = B0 ^ t; + BV = 0; + } + } + while (RK != 0) { + if (m == 0) + t = (RA & 1) ? B0 : 0; + temp = RA & 1; + RA >>= 1; + RA |= t; + RK--; + } + if (m > 1 && temp == 1) + RA = (RA + 1) & FMASK; + XR[RX] = RA; + break; + + case OP_SRD: /* Shift Right Double */ + m = (RB >> 10) & 03; + RK = RB & 01777; + RB = XR[(RX+1) & 07]; + BCarry = 0; + t = RA & B0; + if (m == 3 && RK != 0 && BV) { + t = B0^t; + BV = 0; + } + while (RK != 0) { + switch (m) { + case 0: + if (RA & 1) + RB |= BM1; + if (RB & 1) + RA |= BM1; + RA >>= 1; + RB >>= 1; + break; + case 1: + RB >>= 1; + if (RA & 1) + RB |= B0; + RA >>= 1; + break; + case 2: + case 3: + RB >>= 1; + if (RA & 1) + RB |= B1; + RA >>= 1; + RA |= t; + } + RK--; + } + XR[RX] = RA; + XR[(RX+1) & 07] = RB; + break; + + case OP_NORM: /* Nomarlize Single -2 +FP */ + case OP_NORMD: /* Normalize Double -2 +FP */ + RT = RB; + RB = (RF & 1) ? XR[(RX+1) & 07] & M23 : 0; + if (RT & 04000) { + RT = 0; + } else { + RT &= 01777; + } + if (RT == 0) { + RA = RB = 0; + } else if (BV) { + RT++; + t = (RA & B0) ^ B0; + if (RA & 1 && RF & 1) + RB |= B0; + RB >>= 1; + RA >>= 1; + RA |= t; + } else if (RA != 0 || RB != 0) { + /* Shift left until sign and B1 not same */ + while ((((RA >> 1) ^ RA) & B1) == 0) { + RT--; + RA <<= 1; + if (RB & B1) + RA |= 1; + RB <<= 1; + RA &= FMASK; + RB &= M23; + } + /* Check for overflow */ + if (RT & B0) { /* < 0 */ + RA = RB = 0; + goto norm1; + } + } else + RT = 0; + /* Round RB if needed */ + RP = RB; + RB += 0400; + if (RB & B0) { + RB = RP; + t = (RA & M23) +1; + if (t & B0) + RA = RB = 0; + } + RB = (RB & MMASK) | (RT & M9); + BV = 0; + if (RT > M9) /* Exponent overlfow */ + BV = 1; + norm1: + XR[(RX+1) & 07] = RB; + XR[RX] = RA; + break; + + /* Not on A*/ + case OP_MVCH: /* Move Characters - BC */ + RK = RB; + RB = XR[(RX+1) & 07]; + do { + if (Mem_read(RA, &RT, 0)) { + goto intr; + } + m = (RA >> 22) & 3; + RT = (RT >> (6 * (3 - m))) & 077; + if (Mem_read(RB, &RS, 0)) { + goto intr; + } + m = (RB >> 22) & 3; + m = 6 * (3 - m); + RS &= ~(077 << m); + RS |= (RT & 077) << m; + if (Mem_write(RB, &RS, 0)) { + goto intr; + } + RA += 020000000; + m = (RA & BM1) != 0; + RA = ((RA + m) & M22) | (RA & CMASK); + RB += 020000000; + m = (RB & BM1) != 0; + RB = ((RB + m) & M22) | (RB & CMASK); + RK = (RK - 1) & 0777; + } while (RK != 0); + XR[RX] = RA; + XR[(RX+1)&07] = RB; + break; + + /* Not on A*/ + case OP_SMO: /* Supplementary Modifier - BC */ + if (OPIP) { /* Error */ + SR64 |= B1; + goto intr; + } + if (Mem_read(RS, &RP, 1)) { + goto intr; + } + PIP = 1; + break; + + case OP_NULL: /* No Operation */ + break; + + case OP_LDCT: /* Load Count */ + RA = CNTMSK & (RB << 15); + XR[RX] = RA; + break; + + case OP_MODE: /* Set Mode */ + if (exe_mode) + Mode = RB & 077; + else + Mode = (Mode & 076) | (RB & 1); + break; + + case OP_MOVE: /* Copy N words */ + RK = RB; + RA &= adrmask; + RB = XR[(RX+1) & 07] & adrmask; + do { + if (Mem_read(RA, &RT, 0)) { + goto intr; + } + if (Mem_write(RB, &RT, 0)) { + goto intr; + } + RA++; + RB++; + RK = (RK - 1) & 0777; + } while (RK != 0); + break; + + case OP_SUM: /* Sum N words */ + RK = RB; + RA = 0; + RB = XR[(RX+1) & 07] & adrmask; + do { + if (Mem_read(RB, &RT, 0)) { + goto intr; + } + RA = (RA + RT) & FMASK; + RB++; + RK = (RK - 1) & 0777; + } while (RK != 0); + XR[RX] = RA; + break; + +/* B or C with Floating Point */ + case OP_FLOAT: /* Convert Fixed to Float +FP */ + if (Mem_read(RA, &RB, 0)) { + goto intr; + } + RB++; + if (Mem_read(RB, &RB, 0)) { + goto intr; + } + facch = RA; + faccl = RB; + fovr = (RB & B0) != 0; + RT = 279; + /* Check for zero or -1 */ + if ((faccl & M23) == (facch & M23)) { + if (facch == 0) + break; + if (facch == FMASK) { + facch &= MMASK; + facch |= RT; + break; + } + } + + /* Shift left until sign and B1 not same */ + while ((((facch >> 1) ^ facch) & B1) == 0) { + RT--; + faccl <<= 1; + if (facch & B1) + faccl |= 1; + facch <<= 1; + faccl &= FMASK; + facch &= M23; + } + facch &= MMASK; + facch |= RT & M9; + if (RT < 0) { + fovr = 1; + facch |= B0; + } + break; + + case OP_FIX: /* Convert Float to Fixed +FP */ + RA = faccl; + RB = facch & MMASK; + RT = 279 - (facch & M9); + if (RT > 0) { + while (RT > 0) { + if (RA & 1) + RB |= B0; + if (RA & B0) + RA |= BM1; + RA >>= 1; + RB >>= 1; + RT--; + } + while (RT < 0 && (((RA >> 1) ^ RA) & B1) == 0) { + RA <<= 1; + if (RB & B1) + RA |= 1; + RB <<= 1; + RA &= FMASK; + RB &= M23; + RT++; + } + } + if (RT != 0 || fovr) + BV = 1; + if (Mem_write(RS, &RA, 0)) { + goto intr; + } + RS++; + if (Mem_write(RS, &RB, 0)) { + goto intr; + } + break; + + case OP_FAD: /* Floating Point Add +FP */ + case OP_FSB: /* Floating Point Subtract +FP */ + if (Mem_read(RS, &RA, 0)) { + goto intr; + } + RS++; + if (Mem_read(RS, &RB, 0)) { + goto intr; + } +fprintf(stderr, "FAD0: %08o %08o %08o %08o %08o\n\r", RA, RB, RC, faccl, facch); + fovr |= (RB & B0) != 0; + RB &= M23; + if (RX & 4) { /* See if we should swap operands */ + RT = facch; + facch = RA; + RA = RT; + RT = faccl; + faccl = RB; + RB = RT; +fprintf(stderr, "FAD1: %08o %08o %08o %08o %08o\n\r", RA, RB, RC, faccl, facch); + } + if (RF == OP_FSB) { /* If subtract invert RA&RB */ + RA ^= FMASK; + RB ^= MMASK; + RB += 01000; + if (RB & B0) + RA = (RA + 1) & FMASK; + RB &= M23; +fprintf(stderr, "FAD2: %08o %08o %08o %08o %08o\n\r", RA, RB, RC, faccl, facch); + } + e1 = (facch & M9); + facch &= MMASK; + e2 = (RB & M9); + RB &= MMASK; + n = e1 - e2; +fprintf(stderr, "FADx: %03o %03o %d\n\r", e1, e2, n); + if (n < 0) { + e1 = e2; + if (n < -37) { /* See if more then 37 bits difference */ + faccl = RA; + facch = RB | e1; + break; + } + while(n < 0) { + if (faccl & B0) + faccl |= BM1; + if (faccl & 1) + facch |= B0; + facch >>= 1; + faccl >>= 1; + n++; +fprintf(stderr, "FAD3: %08o %08o %08o %08o %08o\n\r", RA, RB, RC, faccl, facch); + } + } else if (n > 0) { + if (n > 37) { /* See if more then 37 bits difference */ + facch |= e1; + break; + } + while(n > 0) { + if (RA & B0) + RA |= BM1; + if (RA & 1) + RB |= B0; + RA >>= 1; + RB >>= 1; + n--; +fprintf(stderr, "FAD4: %08o %08o %08o %08o %08o\n\r", RA, RB, RC, faccl, facch); + } + } +fprintf(stderr, "FAD5: %08o %08o %08o %08o %08o\n\r", RA, RB, RC, faccl, facch); + if (facch & B0) + facch |= BM1; + if (RA & B0) + RA |= BM1; + faccl += RA; + facch += RB; +fprintf(stderr, "FAD6: %08o %08o %08o %08o %08o\n\r", RA, RB, RC, faccl, facch); + if (facch & B0) { + facch &= M23; + faccl ++; + } + if (faccl & B0) + faccl |= BM1; + if (faccl & 1) + facch |= B0; + faccl >>= 1; + facch >>= 1; + e1--; +fprintf(stderr, "FAD7: %08o %08o %08o %08o %08o %03o\n\r", RA, RB, RC, faccl, facch, e1); + if ((facch | faccl) == 0) + break; + if (faccl == FMASK && (facch & MMASK) == MMASK) { + facch &= MMASK; + facch |= e1; + break; + } +fprintf(stderr, "FAD8: %08o %08o %08o %08o %08o\n\r", RA, RB, RC, faccl, facch); + /* Shift left until sign and B1 not same */ + while ((((faccl >> 1) ^ faccl) & B1) == 0) { + e1++; + facch <<= 1; + faccl <<= 1; + if (facch & B0) + faccl |= 1; + faccl &= FMASK; + facch &= M23; +fprintf(stderr, "FAD9: %08o %08o %08o %08o %08o %03o\n\r", RA, RB, RC, faccl, facch, e1); + } + if (e1 < 0) + fovr = 1; + facch &= MMASK; + facch |= e1 & M9; +fprintf(stderr, "FADA: %08o %08o %08o %08o %08o %03o\n\r", RA, RB, RC, faccl, facch, e1); + break; + + case OP_FMPY: /* Floating Point Multiply +FP */ + break; + + case OP_FDVD: /* Floating Point Divide +FP */ + break; + + case OP_LFP: /* Load Floating Point +FP */ + if (RX & 1) { + faccl = facch = fovr = 0; +fprintf(stderr, "LFP: %08o %08o %o\n\r", faccl, facch, RX); + break; + } + if (Mem_read(RB, &RA, 0)) { + goto intr; + } + RB++; + if (Mem_read(RB, &RS, 0)) { + goto intr; + } + faccl = RA; + facch = RS & M23; + fovr = (RS & B0) != 0; +fprintf(stderr, "LFP: %08o %08o %08o\n\r", faccl, facch, RC); + break; + + case OP_SFP: /* Store Floating Point +FP */ +fprintf(stderr, "SFP: %08o %08o\n\r", faccl, facch); + if (Mem_write(RB, &faccl, 0)) { + goto intr; + } + RA = facch; + if (fovr) { + RA |= B0; + BV = 1; + } + RB++; + if (Mem_write(RB, &RA, 0)) { + goto intr; + } + if (RX & 1) + faccl = facch = fovr = 0; + break; + + case 0150: + case 0151: + if (exe_mode) { + break; + } + case 0170: /* Read special register */ + if (exe_mode) { + RA = 0; + switch(RB) { + case 1: RA = SR1; break; + case 2: RA = SR2; break; + case 3: RA = SR3; break; + case 64: RA = SR64; SR64 = 0; break; + case 65: RA = SR65; SR65 = 0; break; + } + XR[RX] = RA; + break; + } + /* Fall through */ + case 0171: /* Write special register */ + if (exe_mode) { + break; + } + /* Fall through */ + case 0172: /* Exit from executive */ + case 0173: /* Load Datum limit and G */ + if (exe_mode) { +#if 0 /* Type A & B */ /* For non extended address processors. */ + Mem_read(RB, &RA, 0); + RG = RA & 077; + RD = RA & 077700; + RL = (RA >> 9) & 077700; +#else + Mem_read(RB, &RA, 0); /* Read datum */ + RD = RA & (M22 & ~077); + RG = (RA & 17) << 3; + Mem_read(RB+1, &RA, 0); /* Read Limit */ + RL = RA & (M22 & ~077); + RG |= (RA & 07); + Mode &= ~(EJM|AM22|EXTRC); + Mode |= (EJM|AM22|EXTRC) & RA; + adrmask = (Mode & AM22) ? M22 : M15; +fprintf(stderr, "Load limit: %08o D:=%08o %02o\n\r", RL, RD, Mode); +#endif + if (RF & 1) /* Check if 172 or 173 order code */ + break; + /* Restore floating point ACC from D12/D13 */ + for (n = 0; n < 8; n++) /* Restore user mode registers */ + Mem_read(RD+n, &XR[n], 0); + Mem_read(RD+9, &RA, 0); /* Read ZStatus and mode */ + Mode &= ~1; + if ((Mode & AM22) && (RA & B3)) + Mode |= 1; + Mem_read(RD+8, &RC, 0); /* Restore C register */ +fprintf(stderr, "Load PC: %08o D:=%08o z=%08o\n\r", RC, RD, RA); + if ((Mode & AM22) == 0 && (RA & B8)) + Mode |= 1; + BV = (RC & B1) != 0; + BCarry = (RC & B0) != 0; + RC &= adrmask; + Mem_read(RD+12, &faccl, 0); /* Restore F.P.U. */ + Mem_read(RD+13, &facch, 0); /* Restore F.P.U. */ + exe_mode = 0; + break; + } + /* Fall through */ + case 0174: /* Send control character to peripheral */ + if (exe_mode) { + break; + } + /* Fall through */ + case 0175: /* Null operation in Executive mode */ + case 0176: + if (exe_mode) { + break; + } + /* Fall through */ + case 0177: /* Test Datum and Limit */ + if (exe_mode) { + if (RA < RG || RA > RL) + BCarry = 1; + break; + } + default: + /* Voluntary entry to executive */ +voluntary: + if (exe_mode) { + reason = SCPE_STOP; + break; + } + exe_mode = 1; + /* Store registers */ + Mem_write(RD+13, &facch, 0); /* Save F.P.U. */ + Mem_write(RD+12, &faccl, 0); + RA = 0; /* Build ZSTAT */ + if (Mode & 1) + RA |= B3; + if (OPIP) + RA |= B2; + Mem_write(RD+9, &RA, 0); + RA = RC; + if (BV) + RA |= B0; + if (BCarry) + RA |= B1; +#if 0 /* Type A & B */ + if (Mode & 1) + RA |= B8; +#endif + Mem_write(RD+8, &RA, 0); + for (n = 0; n < 8; n++) + Mem_write(RD+n, &XR[n], 0); + Mode = 0; + adrmask = (Mode & AM22) ? M22 : M15; + XR[1] = RB; + XR[2] = temp; + RC = 040; + break; + } + + if (hst_lnt) { /* history enabled? */ + hst[hst_p].rr = RA; + } + sim_interval--; + } /* end while */ + +/* Simulation halted */ + + return reason; +} + +/* Interval timer routines */ +t_stat +rtc_srv(UNIT * uptr) +{ + int32 t; + + t = sim_rtcn_calb(rtc_tps, TMR_RTC); + sim_activate_after(uptr, 1000000/rtc_tps); +// tmxr_poll = t; + return SCPE_OK; +} +/* Reset routine */ + +t_stat +cpu_reset(DEVICE * dptr) +{ + sim_brk_types = sim_brk_dflt = SWMASK('E') | SWMASK('A') | SWMASK('B'); + hst_p = 0; + + sim_register_clock_unit (&cpu_unit[0]); + sim_rtcn_init (cpu_unit[0].wait, TMR_RTC); + sim_activate(&cpu_unit[0], cpu_unit[0].wait) ; + + return SCPE_OK; +} + + +/* Memory examine */ + +t_stat +cpu_ex(t_value * vptr, t_addr addr, UNIT * uptr, int32 sw) +{ + if (addr >= MAXMEMSIZE) + return SCPE_NXM; + if (vptr != NULL) { + if (addr < 010) + *vptr = (t_value)XR[addr]; + else + *vptr = (t_value)M[addr]; + } + return SCPE_OK; +} + +/* Memory deposit */ + +t_stat +cpu_dep(t_value val, t_addr addr, UNIT * uptr, int32 sw) +{ + if (addr >= MAXMEMSIZE) + return SCPE_NXM; + if (addr < 010) + XR[addr] = val; + else + M[addr] = val; + return SCPE_OK; +} + +t_stat +cpu_show_size(FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + fprintf(st, "%dK", MEMSIZE/1024); + return SCPE_OK; +} + +t_stat +cpu_set_size(UNIT * uptr, int32 val, CONST char *cptr, void *desc) +{ + t_uint64 mc = 0; + uint32 i; + + cpu_unit[0].flags &= ~UNIT_MSIZE; + cpu_unit[0].flags |= val; + cpu_unit[1].flags &= ~UNIT_MSIZE; + cpu_unit[1].flags |= val; + val >>= UNIT_V_MSIZE; + val = (val + 1) * 4096; + if ((val < 0) || (val > MAXMEMSIZE)) + return SCPE_ARG; + for (i = val; i < MEMSIZE; i++) + mc |= M[i]; + if ((mc != 0) && (!get_yn("Really truncate memory [N]?", FALSE))) + return SCPE_OK; + MEMSIZE = val; + for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; + return SCPE_OK; +} + +/* Handle execute history */ + +/* Set history */ +t_stat +cpu_set_hist(UNIT * uptr, int32 val, CONST char *cptr, void *desc) +{ + int32 i, lnt; + t_stat r; + + if (cptr == NULL) { + for (i = 0; i < hst_lnt; i++) +// hst[i].c = 0; + hst_p = 0; + return SCPE_OK; + } + lnt = (int32) get_uint(cptr, 10, HIST_MAX, &r); + if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; + hst_p = 0; + if (hst_lnt) { + free(hst); + hst_lnt = 0; + hst = NULL; + } + if (lnt) { + hst = (struct InstHistory *)calloc(sizeof(struct InstHistory), lnt); + + if (hst == NULL) + return SCPE_MEM; + hst_lnt = lnt; + } + return SCPE_OK; +} + +/* Show history */ + +t_stat +cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc) +{ + int32 k, di, lnt; + const char *cptr = (const char *) desc; + t_stat r; + t_value sim_eval; + struct InstHistory *h; + + if (hst_lnt == 0) + return SCPE_NOFNC; /* enabled? */ + if (cptr) { + lnt = (int32) get_uint(cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; + } else + lnt = hst_lnt; + di = hst_p - lnt; /* work forward */ + if (di < 0) + di = di + hst_lnt; + fprintf(st, " C EA XR A B Result c v e Op\n\n"); + for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + + if (h->rc & HIST_PC) { /* instruction? */ + int i; + fprintf(st, " %07o %08o %08o %08o %08o %08o %o %o %o", + h->rc & M22 , h->ea, h->xr, h->ra, h->rb, h->rr, + h->c, h->v, h->e); + sim_eval = h->op; + fprint_sym(st, h->rc & M22, &sim_eval, &cpu_unit[0], SWMASK('M')); + fputc('\n', st); /* end line */ + } /* end else instruction */ + } /* end for */ + return SCPE_OK; +} + + +t_stat +cpu_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ + fprintf(st, "ICL1900 CPU\n\n"); + fprintf(st, "The ICL1900 \n"); + fprint_set_help(st, dptr); + fprint_show_help(st, dptr); + return SCPE_OK; +} diff --git a/ICL1900/icl1900_defs.h b/ICL1900/icl1900_defs.h new file mode 100755 index 0000000..35561b7 --- /dev/null +++ b/ICL1900/icl1900_defs.h @@ -0,0 +1,226 @@ +/* icl1900_defs.h: ICL1900 simulator definitions + + Copyright (c) 2017, Richard Cornwell + + 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 + RICHARD CORNWELL 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 _ICL1900_H_ +#define _ICL1900_H_ + +#include "sim_defs.h" /* simulator defns */ + +/* Definitions for each supported CPU */ + +#define NUM_DEVS_CDR 0 +#define NUM_DEVS_CDP 0 +#define NUM_DEVS_LPR 0 +#define NUM_DEVS_CON 0 +#define NUM_DEVS_MT 0 +#define NUM_DEVS_DSK 0 +#define NUM_DEVS_DTC 0 +#define MAXMEMSIZE (4096 * 1024) + +extern uint32 M[]; /* Main Memory */ + +/* Memory */ +#define MEMSIZE (cpu_unit[0].capac) /* actual memory size */ +#define MEMMASK (MEMSIZE - 1) /* Memory bits */ + + +/* Debuging controls */ +#define DEBUG_CHAN 0x0000001 /* Show channel fetchs */ +#define DEBUG_TRAP 0x0000002 /* Show CPU Traps */ +#define DEBUG_CMD 0x0000004 /* Show device commands */ +#define DEBUG_DATA 0x0000008 /* Show data transfers */ +#define DEBUG_DETAIL 0x0000010 /* Show details */ +#define DEBUG_EXP 0x0000020 /* Show error conditions */ +#define DEBUG_SNS 0x0000040 /* Shows sense data for 7909 devs */ +#define DEBUG_CTSS 0x0000080 /* Shows CTSS specail instructions */ +#define DEBUG_PROT 0x0000100 /* Protection traps */ + +extern DEBTAB dev_debug[]; + + +/* Returns from device commands */ +#define SCPE_BUSY (1) /* Device is active */ +#define SCPE_NODEV (2) /* No device exists */ + +/* Symbol tables */ +typedef struct _opcode +{ + const char *name; + uint8 type; +} +t_opcode; + +#define OP_LDX 0000 /* Load to X */ +#define OP_ADX 0001 /* Add to X */ +#define OP_NGX 0002 /* Negative to X */ +#define OP_SBX 0003 /* Subtract from X */ +#define OP_LDXC 0004 /* Load into X with carry */ +#define OP_ADXC 0005 /* Add to X with carry */ +#define OP_NGXC 0006 /* Negative to X with carry */ +#define OP_SBXC 0007 /* Subtract from X with carry */ +#define OP_STO 0010 /* Store contents of X */ +#define OP_ADS 0011 /* Add X to store */ +#define OP_NGS 0012 /* Negative into Store */ +#define OP_SBS 0013 /* Subtract from store */ +#define OP_STOC 0014 /* Store contents of X with carry */ +#define OP_ADSC 0015 /* Add X to store with carry */ +#define OP_NGSC 0016 /* Negative into Store with carry */ +#define OP_SBSC 0017 /* Subtract from store with carry */ +#define OP_ANDX 0020 /* Logical AND into X */ +#define OP_ORX 0021 /* Logical OR into X */ +#define OP_ERX 0022 /* Logical XOR into X */ +#define OP_OBEY 0023 /* Obey instruction at N */ +#define OP_LDCH 0024 /* Load Character to X */ +#define OP_LDEX 0025 /* Load Exponent */ +#define OP_TXU 0026 /* Test X unequal */ +#define OP_TXL 0027 /* Test X Less */ +#define OP_ANDS 0030 /* Logical AND into store */ +#define OP_ORS 0031 /* Logical OR into store */ +#define OP_ERS 0032 /* Logical XOR into store */ +#define OP_STOZ 0033 /* Store Zero */ +#define OP_DCH 0034 /* Deposit Character to X */ +#define OP_DEX 0035 /* Deposit Exponent */ +#define OP_DSA 0036 /* Deposit Short Address */ +#define OP_DLA 0037 /* Deposit Long Address */ +#define OP_MPY 0040 /* Multiply */ +#define OP_MPR 0041 /* Multiply and Round */ +#define OP_MPA 0042 /* Multiply and Accumulate */ +#define OP_CDB 0043 /* Convert Decimal to Binary */ +#define OP_DVD 0044 /* Unrounded Double Length Divide */ +#define OP_DVR 0045 /* Rounded Double Length Divide */ +#define OP_DVS 0046 /* Single Length Divide */ +#define OP_CBD 0047 /* Convert Binary to Decimal */ +#define OP_BZE 0050 /* Branch if X is Zero */ +#define OP_BZE1 0051 +#define OP_BNZ 0052 /* Branch if X is not Zero */ +#define OP_BNZ1 0053 +#define OP_BPZ 0054 /* Branch if X is Positive or zero */ +#define OP_BPZ1 0055 +#define OP_BNG 0056 /* Branch if X is Positive or zero */ +#define OP_BNG1 0057 +#define OP_BUX 0060 /* Branch on Unit indexing */ +#define OP_BUX1 0061 +#define OP_BDX 0062 /* Branch on Double Indexing */ +#define OP_BDX1 0063 +#define OP_BCHX 0064 /* Branch on Character Indexing */ +#define OP_BCHX1 0065 +#define OP_BCT 0066 /* Branch on Count - BC */ +#define OP_BCT1 0067 +#define OP_CALL 0070 /* Call Subroutine */ +#define OP_CALL1 0071 +#define OP_EXIT 0072 /* Exit Subroutine */ +#define OP_EXIT1 0073 +#define OP_BRN 0074 /* Branch unconditional */ +#define OP_BRN1 0075 +#define OP_BFP 0076 /* Branch state of floating point accumulator */ +#define OP_BFP1 0077 +#define OP_LDN 0100 /* Load direct to X */ +#define OP_ADN 0101 /* Add direct to X */ +#define OP_NGN 0102 /* Negative direct to X */ +#define OP_SBN 0103 /* Subtract direct from X */ +#define OP_LDNC 0104 /* Load direct into X with carry */ +#define OP_ADNC 0105 /* Add direct to X with carry */ +#define OP_NGNC 0106 /* Negative direct to X with carry */ +#define OP_SBNC 0107 /* Subtract direct from X with carry */ +#define OP_SLL 0110 /* Shift Left */ +#define OP_SLD 0111 /* Shift Left Double */ +#define OP_SRL 0112 /* Shift Right */ +#define OP_SRD 0113 /* Shift Right Double*/ +#define OP_NORM 0114 /* Nomarlize Single -2 +FP */ +#define OP_NORMD 0115 /* Normalize Double -2 +FP */ +#define OP_MVCH 0116 /* Move Characters - BC */ +#define OP_SMO 0117 /* Supplementary Modifier - BC */ +#define OP_ANDN 0120 /* Logical AND direct into X */ +#define OP_ORN 0121 /* Logical OR direct into X */ +#define OP_ERN 0122 /* Logical XOR direct into X */ +#define OP_NULL 0123 /* No Operation */ +#define OP_LDCT 0124 /* Load Count */ +#define OP_MODE 0125 /* Set Mode */ +#define OP_MOVE 0126 /* Copy N words */ +#define OP_SUM 0127 /* Sum N words */ +#define OP_FLOAT 0130 /* Convert Fixed to Float +FP */ +#define OP_FIX 0131 /* Convert Float to Fixed +FP */ +#define OP_FAD 0132 /* Floating Point Add +FP */ +#define OP_FSB 0133 /* Floating Point Subtract +FP */ +#define OP_FMPY 0134 /* Floating Point Multiply +FP */ +#define OP_FDVD 0135 /* Floating Point Divide +FP */ +#define OP_LFP 0136 /* Load Floating Point +FP */ +#define OP_SFP 0137 /* Store Floating Point +FP */ + +#define FMASK 077777777 +#define CMASK 060000000 +#define BM1 0100000000 +#define B0 040000000 +#define B1 020000000 +#define B2 010000000 +#define B3 004000000 +#define B8 000100000 +#define B15 000040000 +#define B14 000020000 +#define M9 000000777 +#define M12 000007777 +#define M15 000077777 +#define M22 017777777 +#define M23 037777777 +#define CNTMSK 077700000 +#define CHCMSK 017700000 +#define NMASK 037777400 +#define MMASK 037777000 + +#define CHAR_DEV 0 /* Device transfers via characters */ +#define WORD_DEV 1 /* Device transfers via words */ + +struct icl_dib { + uint8 channel; /* Channel number */ + uint8 type; /* Type of device */ + t_stat (*dev_cmd)(uint32 cmd, uint32 *resp); /* Start io on device */ +}; + +typedef struct icl_dib DIB; + +/* Hessitation operations */ +int chan_write_char(uint8 channel, uint8 data); +int chan_read_char(uint8 channel, uint8 *data); +int chan_write_word(uint8 channel, uint32 data); +int chan_read_word(uint8 channel, uint32 *data); +int chan_end(uint8 channel); + +/* Console tty device routines */ +extern t_stat ctyi_cmd(uint32 cmd, uint32 *resp); +extern t_stat ctyo_cmd(uint32 cmd, uint32 *resp); + +/* Generic devices common to all */ +extern DEVICE cpu_dev; +extern UNIT cpu_unit[]; +extern REG cpu_reg[]; + +/* Global device definitions */ +extern DEVICE cty_dev; +extern DEVICE cdr_dev; +extern DEVICE cdp_dev; +extern DEVICE lpr_dev; +extern DEVICE dtc_dev; +extern DEVICE dsk_dev; +extern DEVICE mt_dev; + +#endif /* _ICL1900_H_ */ diff --git a/ICL1900/icl1900_sys.c b/ICL1900/icl1900_sys.c new file mode 100755 index 0000000..43f0374 --- /dev/null +++ b/ICL1900/icl1900_sys.c @@ -0,0 +1,610 @@ +/* icl1900_sys.c: ICL 1900 Simulator system interface. + + Copyright (c) 2017, Richard Cornwell + + 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 + RICHARD CORNWELL 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 "sim_defs.h" +#include "icl1900_defs.h" +#include "sim_card.h" +#include + +t_stat parse_sym(CONST char *cptr, t_addr addr, UNIT * uptr, t_value * val, int32 sw); + +/* SCP data structures and interface routines + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages + sim_load binary loader +*/ + +char sim_name[] = "ICL1900"; + +REG *sim_PC = &cpu_reg[0]; + +int32 sim_emax = 1; + +DEVICE *sim_devices[] = { + &cpu_dev, +// &cty_dev, +#if NUM_DEVS_CDR > 0 + &cdr_dev, +#endif +#if NUM_DEVS_CDP > 0 + &cdp_dev, +#endif +#if NUM_DEVS_LPR > 0 + &lpr_dev, +#endif +#if NUM_DEVS_MT > 0 + &mt_dev, +#endif +#if NUM_DEVS_DSK > 0 + &dsk_dev, +#endif +#if NUM_DEVS_DTC > 0 + &dtc_dev, +#endif + NULL +}; + +/* Simulator stop codes */ +const char *sim_stop_messages[] = { + 0, +}; + +/* Simulator debug controls */ +DEBTAB dev_debug[] = { + {"CMD", DEBUG_CMD, "Show command execution to devices"}, + {"DATA", DEBUG_DATA, "Show data transfers"}, + {"DETAIL", DEBUG_DETAIL, "Show details about device"}, + {"EXP", DEBUG_EXP, "Show exception information"}, + {0, 0} +}; + + +uint8 parity_table[64] = { + /* 0 1 2 3 4 5 6 7 */ + 0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100, + 0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000, + 0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000, + 0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100, + 0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000, + 0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100, + 0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100, + 0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000 +}; + +uint8 mem_to_ascii[64] = { + /* x0 x1 x2 x3 x4 x5 x6 x7 */ + '0', '1', '2', '3', '4', '5', '6', '7', /* 0x */ + '8', '9', ':', ';', '<', '=', '>', '?', /* 1x */ + ' ', '!', '"', '#', '{', '%', '&', '\'', /* 2x */ + '(', ')', '*', '+', ',', '-', '.', '/', /* 3x */ + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 4x */ + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 5x */ + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 6x */ + 'X', 'Y', 'Z', '[', '$', ']', '^', '_' /* 7x */ +}; + + +const char ascii_to_mem[128] = { + /* Control */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0 - 37 */ + /* Control */ + -1, -1, -1, -1, -1, -1, -1, -1, + /* Control */ + -1, -1, -1, -1, -1, -1, -1, -1, + /* Control */ + -1, -1, -1, -1, -1, -1, -1, -1, + /*sp ! " # $ % & ' */ + 020, 021, 022, 023, 074, 025, 026, 027, /* 4 -1 77 */ + /* ( ) * + , - . / */ + 030, 031, 032, 033, 034, 035, 036, 037, + /* 0 1 2 3 4 5 6 7 */ + 000, 001, 002, 003, 004, 005, 006, 007, + /* 8 9 : ; < = > ? */ + 010, 011, 012, 013, 014, 015, 016, 017, + /* @ A B C D E F G */ + 040, 041, 042, 043, 044, 045, 046, 047, /* 1 -1- 137 */ + /* H I J K L M N O */ + 050, 051, 052, 053, 054, 055, 056, 057, + /* P Q R S T U V W */ + 060, 061, 062, 063, 064, 065, 066, 067, + /* X Y Z [ \ ] ^ _ */ + 070, 071, 072, 073, -1, 075, 076, 077, + /* ` a b c d e f g */ + -1, 041, 042, 043, 044, 045, 046, 047, /* 14 -1 177 */ + /* h i j k l m n o */ + 050, 051, 052, 053, 054, 055, 056, 057, + /* p q r s t u v w */ + 060, 061, 062, 063, 064, 065, 066, 067, + /* x y z { | } ~ del*/ + 070, 071, 072, 024, -1, -1, -1, -1, +}; + + +/* Load a card image file into memory. */ + +t_stat +sim_load(FILE * fileref, CONST char *cptr, CONST char *fnam, int flag) +{ + char buffer[160]; + int i, j, k; + int addr, data; + uint8 image[80]; + int checksum; + + if (match_ext(fnam, "txt")) { + + while (fgets(buffer, 100, fileref)) { + /* Convert bits into image */ + memset(image, 0, sizeof(image)); + for (j = 0; j < 80; j++) { + if (buffer[j] == '\n') + break; + image[j] = ascii_to_mem[buffer[j]]; + if (image[j] < 0) { + fprintf(stderr, "Char %c: %s", buffer[j], buffer); + return SCPE_FMT; + } + } + if (image[0] != 073) { + fprintf(stderr, "F: %s", buffer); + return SCPE_FMT; + } + switch(image[3]) { + case 0: + checksum = 0; + for (j = 0; j < 4; j++) + checksum = (checksum << 6) | image[j]; + addr = 0; + for (; j < 8; j++) + addr = (addr << 6) | image[j]; + checksum += addr; + for (i = 3; i < image[1]; i++) { + data = 0; + for (k = 0; k < 4; k++) + data = (data << 6) | image[j++]; + checksum += data; + M[addr++] = data; + } + data = 0; + for (k = 0; k < 4; k++) + data = (data << 6) | image[j++]; + data = FMASK & (checksum + data); + if (data != 0) + fprintf(stderr, "Check %08o %08o: %s", addr, data, buffer); + break; + case 1: + fprintf(stderr, "%c%c%c%c\n", buffer[4], buffer[5], buffer[6], buffer[7]); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + break; + default: + fprintf(stderr, "B? :%s", buffer); + return SCPE_FMT; + } +// if (load_rec(image)) + // return SCPE_OK; + } + return SCPE_OK; + } + return SCPE_NOFNC; +} + + +#define TYPE_A 0 +#define TYPE_B 1 +#define TYPE_C 2 +#define TYPE_D 3 + +/* Opcodes */ +t_opcode ops[] = { + "LDX", TYPE_A, /* Load to X */ + "ADX", TYPE_A, /* Add to X */ + "NGX", TYPE_A, /* Negative to X */ + "SBX", TYPE_A, /* Subtract from X */ + "LDXC", TYPE_A, /* Load into X with carry */ + "ADXC", TYPE_A, /* Add to X with carry */ + "NGXC", TYPE_A, /* Negative to X with carry */ + "SBXC", TYPE_A, /* Subtract from X with carry */ + "STO", TYPE_A, /* Store contents of X */ + "ADS", TYPE_A, /* Add X to store */ + "NGS", TYPE_A, /* Negative into Store */ + "SBS", TYPE_A, /* Subtract from store */ + "STOC", TYPE_A, /* Store contents of X with carry */ + "ADSC", TYPE_A, /* Add X to store with carry */ + "NGSC", TYPE_A, /* Negative into Store with carry */ + "SBSC", TYPE_A, /* Subtract from store with carry */ + "ANDX", TYPE_A, /* Logical AND into X */ + "ORX", TYPE_A, /* Logical OR into X */ + "ERX", TYPE_A, /* Logical XOR into X */ + "OBEY", TYPE_A, /* Obey instruction at N */ + "LDCH", TYPE_A, /* Load Character to X */ + "LDEX", TYPE_A, /* Load Exponent */ + "TXU", TYPE_A, /* Test X unequal */ + "TXL", TYPE_A, /* Test X Less */ + "ANDS", TYPE_A, /* Logical AND into store */ + "ORS", TYPE_A, /* Logical OR into store */ + "ERS", TYPE_A, /* Logical XOR into store */ + "STOZ", TYPE_A, /* Store Zero */ + "DCH", TYPE_A, /* Deposit Character to X */ + "DEX", TYPE_A, /* Deposit Exponent */ + "DSA", TYPE_A, /* Deposit Short Address */ + "DLA", TYPE_A, /* Deposit Long Address */ + "MPY", TYPE_A, /* Multiply */ + "MPR", TYPE_A, /* Multiply and Round */ + "MPA", TYPE_A, /* Multiply and Accumulate */ + "CDB", TYPE_A, /* Convert Decimal to Binary */ + "DVD", TYPE_A, /* Unrounded Double Length Divide */ + "DVR", TYPE_A, /* Rounded Double Length Divide */ + "DVS", TYPE_A, /* Single Length Divide */ + "CBD", TYPE_A, /* Convert Binary to Decimal */ + "BZE", TYPE_B, /* Branch if X is Zero */ + "BZE", TYPE_B, + "BNZ", TYPE_B, /* Branch if X is not Zero */ + "BNZ", TYPE_B, + "BPZ", TYPE_B, /* Branch if X is Positive or zero */ + "BPZ", TYPE_B, + "BNG", TYPE_B, /* Branch if X is Positive or zero */ + "BNG", TYPE_B, + "BUX", TYPE_B, /* Branch on Unit indexing */ + "BUX", TYPE_B, + "BDX", TYPE_B, /* Branch on Double Indexing */ + "BDX", TYPE_B, + "BCHX", TYPE_B, /* Branch on Character Indexing */ + "BCHX", TYPE_B, + "BCT", TYPE_B, /* Branch on Count - BC */ + "BCT", TYPE_B, + "CALL", TYPE_B, /* Call Subroutine */ + "CALL", TYPE_B, + "EXIT", TYPE_B, /* Exit Subroutine */ + "EXIT", TYPE_B, + NULL, TYPE_D, /* Branch unconditional */ + NULL, TYPE_D, + "BFP", TYPE_B, /* Branch state of floating point accumulator */ + "BFP", TYPE_B, + "LDN", TYPE_A, /* Load direct to X */ + "ADN", TYPE_A, /* Add direct to X */ + "NGN", TYPE_A, /* Negative direct to X */ + "SBN", TYPE_A, /* Subtract direct from X */ + "LDNC", TYPE_A, /* Load direct into X with carry */ + "ADNC", TYPE_A, /* Add direct to X with carry */ + "NGNC", TYPE_A, /* Negative direct to X with carry */ + "SBNC", TYPE_A, /* Subtract direct from X with carry */ + "SL", TYPE_C, /* Shift Left */ + "SLD", TYPE_C, /* Shift Left Double */ + "SR", TYPE_C, /* Shift Right */ + "SRD", TYPE_C, /* Shift Right Double */ + "NORM", TYPE_A, /* Nomarlize Single -2 +FP */ + "NORMD", TYPE_A, /* Normalize Double -2 +FP */ + "MVCH", TYPE_A, /* Move Characters - BC */ + "SMO", TYPE_A, /* Supplementary Modifier - BC */ + "ANDN", TYPE_A, /* Logical AND direct into X */ + "ORN", TYPE_A, /* Logical OR direct into X */ + "ERN", TYPE_A, /* Logical XOR direct into X */ + "NULL", TYPE_A, /* No Operation */ + "LDCT", TYPE_A, /* Load Count */ + "MODE", TYPE_A, /* Set Mode */ + "MOVE", TYPE_A, /* Copy N words */ + "SUM", TYPE_A, /* Sum N words */ + "FLOAT", TYPE_A, /* Convert Fixed to Float +FP */ + "FIX", TYPE_A, /* Convert Float to Fixed +FP */ + "FAD", TYPE_A, /* Floating Point Add +FP */ + "FSB", TYPE_A, /* Floating Point Subtract +FP */ + "FMPY", TYPE_A, /* Floating Point Multiply +FP */ + "FDVD", TYPE_A, /* Floating Point Divide +FP */ + "LFP", TYPE_A, /* Load Floating Point +FP */ + "SFP", TYPE_A, /* Store Floating Point +FP */ + "140", TYPE_A, + "141", TYPE_A, + "142", TYPE_A, + "143", TYPE_A, + "144", TYPE_A, + "145", TYPE_A, + "146", TYPE_A, + "147", TYPE_A, + "150", TYPE_A, + "151", TYPE_A, + "152", TYPE_A, + "153", TYPE_A, + "154", TYPE_A, + "155", TYPE_A, + "156", TYPE_A, + "157", TYPE_A, + "160", TYPE_A, + "161", TYPE_A, + "162", TYPE_A, + "163", TYPE_A, + "164", TYPE_A, + "165", TYPE_A, + "166", TYPE_A, + "167", TYPE_A, + "170", TYPE_A, + "171", TYPE_A, + "172", TYPE_A, + "173", TYPE_A, + "174", TYPE_A, + "175", TYPE_A, + "176", TYPE_A, + "177", TYPE_A, +}; + +char *type_d[] = { "BRN", "BVS", "BVSR", "BVC", "BVCR", "BCS", "BCC", "BVCI" }; + +char type_c[] = { 'C', 'L', 'A', 'V' }; + + +/* Print out an instruction */ +void +print_opcode(FILE * of, t_value val) +{ + int op; + int x; + int m; + int n; + t_opcode *tab; + + op = 0177 & (val >> 14);; + x = 07 & (val >> 21); + m = 03 & (val >> 12); + n = 07777 & val; + tab = &ops[op]; + fprintf(of, " *%03o ", op); + switch(tab->type) { + case TYPE_A: + fprintf(of, "%s %o", tab->name, x); + if (m != 0) { + fputc(' ',of); + fputc('0'+m,of); + } + fprintf(of, "/%04o", n); + break; + case TYPE_B: + fprintf(of, "%s %o/%05o", tab->name, x, val & 077777); + break; + case TYPE_C: + fprintf(of, "%s %o", tab->name, x); + if (m != 0) { + fputc(' ',of); + fputc('0'+m,of); + } + fprintf(of, "/%c+%02o", type_c[(n >> 10) & 3], n & 01777); + break; + case TYPE_D: + fprintf(of, "%s %05o", type_d[x], val & 077777); + break; + } +} + +/* Symbolic decode + + Inputs: + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches + Outputs: + return = status code +*/ + +t_stat +fprint_sym(FILE * of, t_addr addr, t_value * val, UNIT * uptr, int32 sw) +{ + t_value inst = *val; + int i; + + fputc(' ', of); + fprint_val(of, inst, 8, 24, PV_RZRO); + + if (sw & SWMASK('M')) { /* Symbolic Assembly */ + print_opcode(of, inst); + } + if (sw & SWMASK('C')) { /* Char mode opcodes */ + fputc('\'', of); + for (i = 18; i >= 0; i-=6) { + int ch; + + ch = (int)(inst >> i) & 077; + fputc(mem_to_ascii[ch], of); + } + fputc('\'', of); + } + return SCPE_OK; +} + +int +find_opcode(char *op, int *val) +{ + int i; + int v; + t_opcode *tab; + *val = -1; + if (*op >= '0' && *op <= '7') { + for (v = i = 0; op[i] != '\0'; i++) { + if (op[i] >= '0' && op[i] <= '7') + v = (v << 3) + (op[i] - '0'); + else + break; + if (v > 0177) + return -1; + } + } + if (op[i] == 0 && v <= 0177) + return v; + for(i = 0; i <= 0177; i++) { + if (ops[i].name != '\0' && sim_strcasecmp(op, ops[i].name) == 0) + return i; + } + for(i = 0; i < 8; i++) { + if (sim_strcasecmp(op, type_d[i]) == 0) { + *val = i; + return 074; + } + } + return -1; +} + +/* Symbolic input + + Inputs: + *cptr = pointer to input string + addr = current PC + uptr = pointer to unit + *val = pointer to output values + sw = switches + Outputs: + status = error status +*/ + +t_stat +parse_sym(CONST char *cptr, t_addr addr, UNIT * uptr, t_value * val, int32 sw) +{ + int i; + int n; + int x; + int m; + int op; + char gbuf[100]; + t_stat r; + +if (sw & SWMASK ('C')) { + cptr = get_glyph_quoted(cptr, gbuf, 0); /* Get string */ + x = 18; + n = 0; + m = 0; + for(i = 0; gbuf[i] != 0; i++) { + char c = ascii_to_mem[gbuf[i]]; + if (c == -1) + return SCPE_ARG; + n |= c << x; + x -= 6; + if (x < 0) { + val[m++] = n; + n = 0; + x = 18; + } + } + if (x != 18) + val[m++] = n; + return -(m - 1); +} + +if (sw & SWMASK ('M')) { + cptr = get_glyph(cptr, gbuf, 0); /* Get opcode */ + op = find_opcode(gbuf, &i); + if (op < 0) + return SCPE_ARG; + while (sim_isspace (*cptr)) cptr++; + n = 0; + m = -1; + x = -1; + if (*cptr >= '0' || *cptr <= '7') { + x = *cptr++ - '0'; + } + while (sim_isspace (*cptr)) cptr++; + if (*cptr > '0' || *cptr <= '3') { + m = *cptr++ - '0'; + } + while (sim_isspace (*cptr)) cptr++; + *val = (0177 & op) << 14; + if (x >= 0) + *val |= (07 & x) << 21; + + switch (ops[op].type) { + case TYPE_A: /* OP x m/n or OP x /n */ + if (m > 0) + *val |= (m & 03) << 12; + if (*cptr == '/') { + cptr++; + n = get_uint(cptr, 8, 07777, &r); + if (r != SCPE_OK) + return r; + } + break; + + case TYPE_B: /* OP x /n */ + if (m >= 0) + return SCPE_ARG; + *val |= (m & 03) << 12; + if (*cptr == '/') { + cptr++; + n = get_uint(cptr, 8, 077777, &r); + if (r != SCPE_OK) + return r; + } + break; + + case TYPE_C: /* OP x m/c+n or OP X /c+n */ + if (m > 0) + *val |= (m & 03) << 12; + if (*cptr == '/') { + cptr++; + for (i = 0; i< 4; i++) { + if (type_c[i] == *cptr) { + cptr++; + break; + } + } + if (*cptr != '+') + return SCPE_ARG; + cptr++; + n = get_uint(cptr, 8, 01777, &r); + if (r != SCPE_OK) + return r; + n |= i << 10; + } + break; + + case TYPE_D: /* type_d /n */ + if (i < 0 && x >= 0) { + i = x; + x = -1; + } + if (m >= 0 || x >= 0) + return SCPE_ARG; + if (*cptr == '/') { + cptr++; + n = get_uint(cptr, 8, 077777, &r); + if (r != SCPE_OK) + return r; + } + *val |= i << 21; + break; + } + *val |= n; + return 0; +} +n = get_uint(cptr, 8, 077777777, &r); +if (r != SCPE_OK) + return r; +*val = n; +return 0; +} +